-
Notifications
You must be signed in to change notification settings - Fork 15.3k
/
descriptor_pool.rb
75 lines (64 loc) · 3.41 KB
/
descriptor_pool.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# Protocol Buffers - Google's data interchange format
# Copyright 2022 Google Inc. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd
module Google
module Protobuf
class FFI
# DefPool
attach_function :add_serialized_file, :upb_DefPool_AddFile, [:DefPool, :FileDescriptorProto, Status.by_ref], :FileDef
attach_function :free_descriptor_pool, :upb_DefPool_Free, [:DefPool], :void
attach_function :create_descriptor_pool,:upb_DefPool_New, [], :DefPool
attach_function :get_extension_registry,:upb_DefPool_ExtensionRegistry, [:DefPool], :ExtensionRegistry
attach_function :lookup_enum, :upb_DefPool_FindEnumByName, [:DefPool, :string], EnumDescriptor
attach_function :lookup_extension, :upb_DefPool_FindExtensionByName,[:DefPool, :string], FieldDescriptor
attach_function :lookup_msg, :upb_DefPool_FindMessageByName, [:DefPool, :string], Descriptor
# FileDescriptorProto
attach_function :parse, :FileDescriptorProto_parse, [:binary_string, :size_t, Internal::Arena], :FileDescriptorProto
end
class DescriptorPool
attr :descriptor_pool
attr_accessor :descriptor_class_by_def
def initialize
@descriptor_pool = ::FFI::AutoPointer.new(Google::Protobuf::FFI.create_descriptor_pool, Google::Protobuf::FFI.method(:free_descriptor_pool))
@descriptor_class_by_def = {}
# Should always be the last expression of the initializer to avoid
# leaking references to this object before construction is complete.
Google::Protobuf::OBJECT_CACHE.try_add @descriptor_pool.address, self
end
def add_serialized_file(file_contents)
# Allocate memory sized to file_contents
memBuf = ::FFI::MemoryPointer.new(:char, file_contents.bytesize)
# Insert the data
memBuf.put_bytes(0, file_contents)
temporary_arena = Google::Protobuf::FFI.create_arena
file_descriptor_proto = Google::Protobuf::FFI.parse memBuf, file_contents.bytesize, temporary_arena
raise ArgumentError.new("Unable to parse FileDescriptorProto") if file_descriptor_proto.null?
status = Google::Protobuf::FFI::Status.new
file_descriptor = Google::Protobuf::FFI.add_serialized_file @descriptor_pool, file_descriptor_proto, status
if file_descriptor.null?
raise TypeError.new("Unable to build file to DescriptorPool: #{Google::Protobuf::FFI.error_message(status)}")
else
@descriptor_class_by_def[file_descriptor.address] = FileDescriptor.new file_descriptor, self
end
end
def lookup name
Google::Protobuf::FFI.lookup_msg(@descriptor_pool, name) ||
Google::Protobuf::FFI.lookup_enum(@descriptor_pool, name) ||
Google::Protobuf::FFI.lookup_extension(@descriptor_pool, name)
end
def self.generated_pool
@@generated_pool ||= DescriptorPool.new
end
private
# Implementation details below are subject to breaking changes without
# warning and are intended for use only within the gem.
def get_file_descriptor file_def
return nil if file_def.null?
@descriptor_class_by_def[file_def.address] ||= FileDescriptor.new(file_def, self)
end
end
end
end