google-protobuf 3.24.4 → 3.25.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +23 -70
  4. data/ext/google/protobuf_c/convert.h +3 -26
  5. data/ext/google/protobuf_c/defs.c +3 -26
  6. data/ext/google/protobuf_c/defs.h +3 -26
  7. data/ext/google/protobuf_c/extconf.rb +2 -1
  8. data/ext/google/protobuf_c/glue.c +21 -0
  9. data/ext/google/protobuf_c/map.c +3 -26
  10. data/ext/google/protobuf_c/map.h +3 -26
  11. data/ext/google/protobuf_c/message.c +21 -69
  12. data/ext/google/protobuf_c/message.h +3 -26
  13. data/ext/google/protobuf_c/protobuf.c +3 -26
  14. data/ext/google/protobuf_c/protobuf.h +3 -26
  15. data/ext/google/protobuf_c/repeated_field.c +4 -27
  16. data/ext/google/protobuf_c/repeated_field.h +3 -26
  17. data/ext/google/protobuf_c/ruby-upb.c +8351 -8160
  18. data/ext/google/protobuf_c/ruby-upb.h +4077 -3784
  19. data/ext/google/protobuf_c/shared_convert.c +64 -0
  20. data/ext/google/protobuf_c/shared_convert.h +26 -0
  21. data/ext/google/protobuf_c/shared_message.c +65 -0
  22. data/ext/google/protobuf_c/shared_message.h +25 -0
  23. data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
  24. data/lib/google/protobuf/any_pb.rb +1 -1
  25. data/lib/google/protobuf/api_pb.rb +1 -1
  26. data/lib/google/protobuf/descriptor_pb.rb +6 -3
  27. data/lib/google/protobuf/duration_pb.rb +1 -1
  28. data/lib/google/protobuf/empty_pb.rb +1 -1
  29. data/lib/google/protobuf/ffi/descriptor.rb +154 -0
  30. data/lib/google/protobuf/ffi/descriptor_pool.rb +70 -0
  31. data/lib/google/protobuf/ffi/enum_descriptor.rb +161 -0
  32. data/lib/google/protobuf/ffi/ffi.rb +213 -0
  33. data/lib/google/protobuf/ffi/field_descriptor.rb +309 -0
  34. data/lib/google/protobuf/ffi/file_descriptor.rb +48 -0
  35. data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
  36. data/lib/google/protobuf/ffi/internal/convert.rb +305 -0
  37. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
  38. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  39. data/lib/google/protobuf/ffi/map.rb +396 -0
  40. data/lib/google/protobuf/ffi/message.rb +641 -0
  41. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  42. data/lib/google/protobuf/ffi/oneof_descriptor.rb +88 -0
  43. data/lib/google/protobuf/ffi/repeated_field.rb +503 -0
  44. data/lib/google/protobuf/field_mask_pb.rb +1 -1
  45. data/lib/google/protobuf/message_exts.rb +3 -26
  46. data/lib/google/protobuf/object_cache.rb +3 -26
  47. data/lib/google/protobuf/plugin_pb.rb +1 -1
  48. data/lib/google/protobuf/repeated_field.rb +3 -26
  49. data/lib/google/protobuf/source_context_pb.rb +1 -1
  50. data/lib/google/protobuf/struct_pb.rb +1 -1
  51. data/lib/google/protobuf/timestamp_pb.rb +1 -1
  52. data/lib/google/protobuf/type_pb.rb +1 -1
  53. data/lib/google/protobuf/well_known_types.rb +3 -26
  54. data/lib/google/protobuf/wrappers_pb.rb +1 -1
  55. data/lib/google/protobuf.rb +26 -45
  56. data/lib/google/protobuf_ffi.rb +50 -0
  57. data/lib/google/protobuf_native.rb +20 -0
  58. data/lib/google/tasks/ffi.rake +94 -0
  59. metadata +72 -5
@@ -0,0 +1,161 @@
1
+ # Protocol Buffers - Google's data interchange format
2
+ # Copyright 2022 Google Inc. All rights reserved.
3
+ #
4
+ # Use of this source code is governed by a BSD-style
5
+ # license that can be found in the LICENSE file or at
6
+ # https://developers.google.com/open-source/licenses/bsd
7
+
8
+ module Google
9
+ module Protobuf
10
+ class EnumDescriptor
11
+ attr :descriptor_pool, :enum_def
12
+ include Enumerable
13
+
14
+ # FFI Interface methods and setup
15
+ extend ::FFI::DataConverter
16
+ native_type ::FFI::Type::POINTER
17
+
18
+ class << self
19
+ prepend Google::Protobuf::Internal::TypeSafety
20
+ include Google::Protobuf::Internal::PointerHelper
21
+
22
+ # @param value [Arena] Arena to convert to an FFI native type
23
+ # @param _ [Object] Unused
24
+ def to_native(value, _)
25
+ value.instance_variable_get(:@enum_def) || ::FFI::Pointer::NULL
26
+ end
27
+
28
+ ##
29
+ # @param enum_def [::FFI::Pointer] EnumDef pointer to be wrapped
30
+ # @param _ [Object] Unused
31
+ def from_native(enum_def, _)
32
+ return nil if enum_def.nil? or enum_def.null?
33
+ file_def = Google::Protobuf::FFI.get_message_file_def enum_def
34
+ descriptor_from_file_def(file_def, enum_def)
35
+ end
36
+ end
37
+
38
+ def self.new(*arguments, &block)
39
+ raise "Descriptor objects may not be created from Ruby."
40
+ end
41
+
42
+ def file_descriptor
43
+ @descriptor_pool.send(:get_file_descriptor, Google::Protobuf::FFI.get_enum_file_descriptor(self))
44
+ end
45
+
46
+ def name
47
+ Google::Protobuf::FFI.get_enum_fullname(self)
48
+ end
49
+
50
+ def to_s
51
+ inspect
52
+ end
53
+
54
+ def inspect
55
+ "#{self.class.name}: #{name}"
56
+ end
57
+
58
+ def lookup_name(name)
59
+ self.class.send(:lookup_name, self, name)
60
+ end
61
+
62
+ def lookup_value(number)
63
+ self.class.send(:lookup_value, self, number)
64
+ end
65
+
66
+ def each &block
67
+ n = Google::Protobuf::FFI.enum_value_count(self)
68
+ 0.upto(n - 1) do |i|
69
+ enum_value = Google::Protobuf::FFI.enum_value_by_index(self, i)
70
+ yield(Google::Protobuf::FFI.enum_name(enum_value).to_sym, Google::Protobuf::FFI.enum_number(enum_value))
71
+ end
72
+ nil
73
+ end
74
+
75
+ def enummodule
76
+ if @module.nil?
77
+ @module = build_enum_module
78
+ end
79
+ @module
80
+ end
81
+
82
+ private
83
+
84
+ def initialize(enum_def, descriptor_pool)
85
+ @descriptor_pool = descriptor_pool
86
+ @enum_def = enum_def
87
+ @module = nil
88
+ end
89
+
90
+ def self.private_constructor(enum_def, descriptor_pool)
91
+ instance = allocate
92
+ instance.send(:initialize, enum_def, descriptor_pool)
93
+ instance
94
+ end
95
+
96
+ def self.lookup_value(enum_def, number)
97
+ enum_value = Google::Protobuf::FFI.enum_value_by_number(enum_def, number)
98
+ if enum_value.null?
99
+ nil
100
+ else
101
+ Google::Protobuf::FFI.enum_name(enum_value).to_sym
102
+ end
103
+ end
104
+
105
+ def self.lookup_name(enum_def, name)
106
+ enum_value = Google::Protobuf::FFI.enum_value_by_name(enum_def, name.to_s, name.size)
107
+ if enum_value.null?
108
+ nil
109
+ else
110
+ Google::Protobuf::FFI.enum_number(enum_value)
111
+ end
112
+ end
113
+
114
+ def build_enum_module
115
+ descriptor = self
116
+ dynamic_module = Module.new do
117
+ @descriptor = descriptor
118
+
119
+ class << self
120
+ attr_accessor :descriptor
121
+ end
122
+
123
+ def self.lookup(number)
124
+ descriptor.lookup_value number
125
+ end
126
+
127
+ def self.resolve(name)
128
+ descriptor.lookup_name name
129
+ end
130
+ end
131
+
132
+ self.each do |name, value|
133
+ if name[0] < 'A' || name[0] > 'Z'
134
+ if name[0] >= 'a' and name[0] <= 'z'
135
+ name = name[0].upcase + name[1..-1] # auto capitalize
136
+ else
137
+ warn(
138
+ "Enum value '#{name}' does not start with an uppercase letter " +
139
+ "as is required for Ruby constants.")
140
+ next
141
+ end
142
+ end
143
+ dynamic_module.const_set(name.to_sym, value)
144
+ end
145
+ dynamic_module
146
+ end
147
+ end
148
+
149
+ class FFI
150
+ # EnumDescriptor
151
+ attach_function :get_enum_file_descriptor, :upb_EnumDef_File, [EnumDescriptor], :FileDef
152
+ attach_function :enum_value_by_name, :upb_EnumDef_FindValueByNameWithSize,[EnumDescriptor, :string, :size_t], :EnumValueDef
153
+ attach_function :enum_value_by_number, :upb_EnumDef_FindValueByNumber, [EnumDescriptor, :int], :EnumValueDef
154
+ attach_function :get_enum_fullname, :upb_EnumDef_FullName, [EnumDescriptor], :string
155
+ attach_function :enum_value_by_index, :upb_EnumDef_Value, [EnumDescriptor, :int], :EnumValueDef
156
+ attach_function :enum_value_count, :upb_EnumDef_ValueCount, [EnumDescriptor], :int
157
+ attach_function :enum_name, :upb_EnumValueDef_Name, [:EnumValueDef], :string
158
+ attach_function :enum_number, :upb_EnumValueDef_Number, [:EnumValueDef], :int
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,213 @@
1
+ # Protocol Buffers - Google's data interchange format
2
+ # Copyright 2022 Google Inc. All rights reserved.
3
+ #
4
+ # Use of this source code is governed by a BSD-style
5
+ # license that can be found in the LICENSE file or at
6
+ # https://developers.google.com/open-source/licenses/bsd
7
+
8
+ module Google
9
+ module Protobuf
10
+ class FFI
11
+ extend ::FFI::Library
12
+ # Workaround for Bazel's use of symlinks + JRuby's __FILE__ and `caller`
13
+ # that resolves them.
14
+ if ENV['BAZEL'] == 'true'
15
+ ffi_lib ::FFI::Compiler::Loader.find 'protobuf_c_ffi', ENV['PWD']
16
+ else
17
+ ffi_lib ::FFI::Compiler::Loader.find 'protobuf_c_ffi'
18
+ end
19
+
20
+ ## Map
21
+ Upb_Map_Begin = -1
22
+
23
+ ## Encoding Status
24
+ Upb_Status_MaxMessage = 127
25
+ Upb_Encode_Deterministic = 1
26
+ Upb_Encode_SkipUnknown = 2
27
+
28
+ ## JSON Encoding options
29
+ # When set, emits 0/default values. TODO: proto3 only?
30
+ Upb_JsonEncode_EmitDefaults = 1
31
+ # When set, use normal (snake_case) field names instead of JSON (camelCase) names.
32
+ Upb_JsonEncode_UseProtoNames = 2
33
+ # When set, emits enums as their integer values instead of as their names.
34
+ Upb_JsonEncode_FormatEnumsAsIntegers = 4
35
+
36
+ ## JSON Decoding options
37
+ Upb_JsonDecode_IgnoreUnknown = 1
38
+
39
+ typedef :pointer, :Array
40
+ typedef :pointer, :DefPool
41
+ typedef :pointer, :EnumValueDef
42
+ typedef :pointer, :ExtensionRegistry
43
+ typedef :pointer, :FieldDefPointer
44
+ typedef :pointer, :FileDef
45
+ typedef :pointer, :FileDescriptorProto
46
+ typedef :pointer, :Map
47
+ typedef :pointer, :Message # Instances of a message
48
+ typedef :pointer, :OneofDefPointer
49
+ typedef :pointer, :binary_string
50
+ if ::FFI::Platform::ARCH == "aarch64"
51
+ typedef :u_int8_t, :uint8_t
52
+ typedef :u_int16_t, :uint16_t
53
+ typedef :u_int32_t, :uint32_t
54
+ typedef :u_int64_t, :uint64_t
55
+ end
56
+
57
+ FieldType = enum(
58
+ :double, 1,
59
+ :float,
60
+ :int64,
61
+ :uint64,
62
+ :int32,
63
+ :fixed64,
64
+ :fixed32,
65
+ :bool,
66
+ :string,
67
+ :group,
68
+ :message,
69
+ :bytes,
70
+ :uint32,
71
+ :enum,
72
+ :sfixed32,
73
+ :sfixed64,
74
+ :sint32,
75
+ :sint64
76
+ )
77
+
78
+ CType = enum(
79
+ :bool, 1,
80
+ :float,
81
+ :int32,
82
+ :uint32,
83
+ :enum,
84
+ :message,
85
+ :double,
86
+ :int64,
87
+ :uint64,
88
+ :string,
89
+ :bytes
90
+ )
91
+
92
+ Label = enum(
93
+ :optional, 1,
94
+ :required,
95
+ :repeated
96
+ )
97
+
98
+ Syntax = enum(
99
+ :Proto2, 2,
100
+ :Proto3
101
+ )
102
+
103
+ # All the different kind of well known type messages. For simplicity of check,
104
+ # number wrappers and string wrappers are grouped together. Make sure the
105
+ # order and merber of these groups are not changed.
106
+
107
+ WellKnown = enum(
108
+ :Unspecified,
109
+ :Any,
110
+ :FieldMask,
111
+ :Duration,
112
+ :Timestamp,
113
+ # number wrappers
114
+ :DoubleValue,
115
+ :FloatValue,
116
+ :Int64Value,
117
+ :UInt64Value,
118
+ :Int32Value,
119
+ :UInt32Value,
120
+ # string wrappers
121
+ :StringValue,
122
+ :BytesValue,
123
+ :BoolValue,
124
+ :Value,
125
+ :ListValue,
126
+ :Struct
127
+ )
128
+
129
+ DecodeStatus = enum(
130
+ :Ok,
131
+ :Malformed, # Wire format was corrupt
132
+ :OutOfMemory, # Arena alloc failed
133
+ :BadUtf8, # String field had bad UTF-8
134
+ :MaxDepthExceeded, # Exceeded UPB_DECODE_MAXDEPTH
135
+
136
+ # CheckRequired failed, but the parse otherwise succeeded.
137
+ :MissingRequired,
138
+ )
139
+
140
+ EncodeStatus = enum(
141
+ :Ok,
142
+ :OutOfMemory, # Arena alloc failed
143
+ :MaxDepthExceeded, # Exceeded UPB_DECODE_MAXDEPTH
144
+
145
+ # CheckRequired failed, but the parse otherwise succeeded.
146
+ :MissingRequired,
147
+ )
148
+
149
+ class StringView < ::FFI::Struct
150
+ layout :data, :pointer,
151
+ :size, :size_t
152
+ end
153
+
154
+ class MiniTable < ::FFI::Struct
155
+ layout :subs, :pointer,
156
+ :fields, :pointer,
157
+ :size, :uint16_t,
158
+ :field_count, :uint16_t,
159
+ :ext, :uint8_t, # upb_ExtMode, declared as uint8_t so sizeof(ext) == 1
160
+ :dense_below, :uint8_t,
161
+ :table_mask, :uint8_t,
162
+ :required_count, :uint8_t # Required fields have the lowest hasbits.
163
+ # To statically initialize the tables of variable length, we need a flexible
164
+ # array member, and we need to compile in gnu99 mode (constant initialization
165
+ # of flexible array members is a GNU extension, not in C99 unfortunately. */
166
+ # _upb_FastTable_Entry fasttable[];
167
+ end
168
+
169
+ class Status < ::FFI::Struct
170
+ layout :ok, :bool,
171
+ :msg, [:char, Upb_Status_MaxMessage]
172
+
173
+ def initialize
174
+ super
175
+ FFI.clear self
176
+ end
177
+ end
178
+
179
+ class MessageValue < ::FFI::Union
180
+ layout :bool_val, :bool,
181
+ :float_val, :float,
182
+ :double_val, :double,
183
+ :int32_val, :int32_t,
184
+ :int64_val, :int64_t,
185
+ :uint32_val, :uint32_t,
186
+ :uint64_val,:uint64_t,
187
+ :map_val, :pointer,
188
+ :msg_val, :pointer,
189
+ :array_val,:pointer,
190
+ :str_val, StringView
191
+ end
192
+
193
+ class MutableMessageValue < ::FFI::Union
194
+ layout :map, :Map,
195
+ :msg, :Message,
196
+ :array, :Array
197
+ end
198
+
199
+ # Status
200
+ attach_function :clear, :upb_Status_Clear, [Status.by_ref], :void
201
+ attach_function :error_message, :upb_Status_ErrorMessage, [Status.by_ref], :string
202
+
203
+ # Generic
204
+ attach_function :memcmp, [:pointer, :pointer, :size_t], :int
205
+ attach_function :memcpy, [:pointer, :pointer, :size_t], :int
206
+
207
+ # Alternatives to pre-processor macros
208
+ def self.decode_max_depth(i)
209
+ i << 16
210
+ end
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,309 @@
1
+ # Protocol Buffers - Google's data interchange format
2
+ # Copyright 2022 Google Inc. All rights reserved.
3
+ #
4
+ # Use of this source code is governed by a BSD-style
5
+ # license that can be found in the LICENSE file or at
6
+ # https://developers.google.com/open-source/licenses/bsd
7
+
8
+ module Google
9
+ module Protobuf
10
+ class FieldDescriptor
11
+ attr :field_def, :descriptor_pool
12
+
13
+ include Google::Protobuf::Internal::Convert
14
+
15
+ # FFI Interface methods and setup
16
+ extend ::FFI::DataConverter
17
+ native_type ::FFI::Type::POINTER
18
+
19
+ class << self
20
+ prepend Google::Protobuf::Internal::TypeSafety
21
+ include Google::Protobuf::Internal::PointerHelper
22
+
23
+ # @param value [FieldDescriptor] FieldDescriptor to convert to an FFI native type
24
+ # @param _ [Object] Unused
25
+ def to_native(value, _)
26
+ field_def_ptr = value.instance_variable_get(:@field_def)
27
+ warn "Underlying field_def was nil!" if field_def_ptr.nil?
28
+ raise "Underlying field_def was null!" if !field_def_ptr.nil? and field_def_ptr.null?
29
+ field_def_ptr
30
+ end
31
+
32
+ ##
33
+ # @param field_def [::FFI::Pointer] FieldDef pointer to be wrapped
34
+ # @param _ [Object] Unused
35
+ def from_native(field_def, _ = nil)
36
+ return nil if field_def.nil? or field_def.null?
37
+ file_def = Google::Protobuf::FFI.file_def_by_raw_field_def(field_def)
38
+ descriptor_from_file_def(file_def, field_def)
39
+ end
40
+ end
41
+
42
+ def self.new(*arguments, &block)
43
+ raise "Descriptor objects may not be created from Ruby."
44
+ end
45
+
46
+ def to_s
47
+ inspect
48
+ end
49
+
50
+ def inspect
51
+ "#{self.class.name}: #{name}"
52
+ end
53
+
54
+ def name
55
+ @name ||= Google::Protobuf::FFI.get_full_name(self)
56
+ end
57
+
58
+ def json_name
59
+ @json_name ||= Google::Protobuf::FFI.get_json_name(self)
60
+ end
61
+
62
+ def number
63
+ @number ||= Google::Protobuf::FFI.get_number(self)
64
+ end
65
+
66
+ def type
67
+ @type ||= Google::Protobuf::FFI.get_type(self)
68
+ end
69
+
70
+ def label
71
+ @label ||= Google::Protobuf::FFI::Label[Google::Protobuf::FFI.get_label(self)]
72
+ end
73
+
74
+ def default
75
+ return nil if Google::Protobuf::FFI.is_sub_message(self)
76
+ if Google::Protobuf::FFI.is_repeated(self)
77
+ message_value = Google::Protobuf::FFI::MessageValue.new
78
+ else
79
+ message_value = Google::Protobuf::FFI.get_default(self)
80
+ end
81
+ enum_def = Google::Protobuf::FFI.get_subtype_as_enum(self)
82
+ if enum_def.null?
83
+ convert_upb_to_ruby message_value, c_type
84
+ else
85
+ convert_upb_to_ruby message_value, c_type, enum_def
86
+ end
87
+ end
88
+
89
+ def submsg_name
90
+ if defined? @submsg_name
91
+ @submsg_name
92
+ else
93
+ @submsg_name = case c_type
94
+ when :enum
95
+ Google::Protobuf::FFI.get_enum_fullname Google::Protobuf::FFI.get_subtype_as_enum self
96
+ when :message
97
+ Google::Protobuf::FFI.get_message_fullname Google::Protobuf::FFI.get_subtype_as_message self
98
+ else
99
+ nil
100
+ end
101
+ end
102
+ end
103
+
104
+ ##
105
+ # Tests if this field has been set on the argument message.
106
+ #
107
+ # @param msg [Google::Protobuf::Message]
108
+ # @return [Object] Value of the field on this message.
109
+ # @raise [TypeError] If the field is not defined on this message.
110
+ def get(msg)
111
+ if msg.class.descriptor == Google::Protobuf::FFI.get_containing_message_def(self)
112
+ msg.send :get_field, self
113
+ else
114
+ raise TypeError.new "get method called on wrong message type"
115
+ end
116
+ end
117
+
118
+ def subtype
119
+ if defined? @subtype
120
+ @subtype
121
+ else
122
+ @subtype = case c_type
123
+ when :enum
124
+ Google::Protobuf::FFI.get_subtype_as_enum(self)
125
+ when :message
126
+ Google::Protobuf::FFI.get_subtype_as_message(self)
127
+ else
128
+ nil
129
+ end
130
+ end
131
+ end
132
+
133
+ ##
134
+ # Tests if this field has been set on the argument message.
135
+ #
136
+ # @param msg [Google::Protobuf::Message]
137
+ # @return [Boolean] True iff message has this field set
138
+ # @raise [TypeError] If this field does not exist on the message
139
+ # @raise [ArgumentError] If this field does not track presence
140
+ def has?(msg)
141
+ if msg.class.descriptor != Google::Protobuf::FFI.get_containing_message_def(self)
142
+ raise TypeError.new "has method called on wrong message type"
143
+ end
144
+ unless has_presence?
145
+ raise ArgumentError.new "does not track presence"
146
+ end
147
+
148
+ Google::Protobuf::FFI.get_message_has msg.instance_variable_get(:@msg), self
149
+ end
150
+
151
+ ##
152
+ # Tests if this field tracks presence.
153
+ #
154
+ # @return [Boolean] True iff this field tracks presence
155
+ def has_presence?
156
+ @has_presence ||= Google::Protobuf::FFI.get_has_presence(self)
157
+ end
158
+
159
+ # @param msg [Google::Protobuf::Message]
160
+ def clear(msg)
161
+ if msg.class.descriptor != Google::Protobuf::FFI.get_containing_message_def(self)
162
+ raise TypeError.new "clear method called on wrong message type"
163
+ end
164
+ Google::Protobuf::FFI.clear_message_field msg.instance_variable_get(:@msg), self
165
+ nil
166
+ end
167
+
168
+ ##
169
+ # call-seq:
170
+ # FieldDescriptor.set(message, value)
171
+ #
172
+ # Sets the value corresponding to this field to the given value on the given
173
+ # message. Raises an exception if message is of the wrong type. Performs the
174
+ # ordinary type-checks for field setting.
175
+ #
176
+ # @param msg [Google::Protobuf::Message]
177
+ # @param value [Object]
178
+ def set(msg, value)
179
+ if msg.class.descriptor != Google::Protobuf::FFI.get_containing_message_def(self)
180
+ raise TypeError.new "set method called on wrong message type"
181
+ end
182
+ unless set_value_on_message value, msg.instance_variable_get(:@msg), msg.instance_variable_get(:@arena)
183
+ raise RuntimeError.new "allocation failed"
184
+ end
185
+ nil
186
+ end
187
+
188
+ def map?
189
+ @map ||= Google::Protobuf::FFI.is_map self
190
+ end
191
+
192
+ def repeated?
193
+ @repeated ||= Google::Protobuf::FFI.is_repeated self
194
+ end
195
+
196
+ def sub_message?
197
+ @sub_message ||= Google::Protobuf::FFI.is_sub_message self
198
+ end
199
+
200
+ def wrapper?
201
+ if defined? @wrapper
202
+ @wrapper
203
+ else
204
+ message_descriptor = Google::Protobuf::FFI.get_subtype_as_message(self)
205
+ @wrapper = message_descriptor.nil? ? false : message_descriptor.send(:wrapper?)
206
+ end
207
+ end
208
+
209
+ private
210
+
211
+ def initialize(field_def, descriptor_pool)
212
+ @field_def = field_def
213
+ @descriptor_pool = descriptor_pool
214
+ end
215
+
216
+ def self.private_constructor(field_def, descriptor_pool)
217
+ instance = allocate
218
+ instance.send(:initialize, field_def, descriptor_pool)
219
+ instance
220
+ end
221
+
222
+ # TODO Can this be added to the public API?
223
+ def real_containing_oneof
224
+ @real_containing_oneof ||= Google::Protobuf::FFI.real_containing_oneof self
225
+ end
226
+
227
+ # Implementation details below are subject to breaking changes without
228
+ # warning and are intended for use only within the gem.
229
+
230
+ ##
231
+ # Sets the field this FieldDescriptor represents to the given value on the given message.
232
+ # @param value [Object] Value to be set
233
+ # @param msg [::FFI::Pointer] Pointer the the upb_Message
234
+ # @param arena [Arena] Arena of the message that owns msg
235
+ def set_value_on_message(value, msg, arena, wrap: false)
236
+ message_to_alter = msg
237
+ field_def_to_set = self
238
+ if map?
239
+ raise TypeError.new "Expected map" unless value.is_a? Google::Protobuf::Map
240
+ message_descriptor = subtype
241
+
242
+ key_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 1)
243
+ key_field_type = Google::Protobuf::FFI.get_type(key_field_def)
244
+ raise TypeError.new "Map key type does not match field's key type" unless key_field_type == value.send(:key_type)
245
+
246
+ value_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 2)
247
+ value_field_type = Google::Protobuf::FFI.get_type(value_field_def)
248
+ raise TypeError.new "Map value type does not match field's value type" unless value_field_type == value.send(:value_type)
249
+
250
+ raise TypeError.new "Map value type has wrong message/enum class" unless value_field_def.subtype == value.send(:descriptor)
251
+
252
+ arena.fuse(value.send(:arena))
253
+ message_value = Google::Protobuf::FFI::MessageValue.new
254
+ message_value[:map_val] = value.send(:map_ptr)
255
+ elsif repeated?
256
+ raise TypeError.new "Expected repeated field array" unless value.is_a? RepeatedField
257
+ raise TypeError.new "Repeated field array has wrong message/enum class" unless value.send(:type) == type
258
+ arena.fuse(value.send(:arena))
259
+ message_value = Google::Protobuf::FFI::MessageValue.new
260
+ message_value[:array_val] = value.send(:array)
261
+ else
262
+ if value.nil? and (sub_message? or !real_containing_oneof.nil?)
263
+ Google::Protobuf::FFI.clear_message_field message_to_alter, field_def_to_set
264
+ return true
265
+ end
266
+ if wrap
267
+ value_field_def = Google::Protobuf::FFI.get_field_by_number subtype, 1
268
+ type_for_conversion = Google::Protobuf::FFI.get_c_type(value_field_def)
269
+ raise RuntimeError.new "Not expecting to get a msg or enum when unwrapping" if [:enum, :message].include? type_for_conversion
270
+ message_value = convert_ruby_to_upb(value, arena, type_for_conversion, nil)
271
+ message_to_alter = Google::Protobuf::FFI.get_mutable_message(msg, self, arena)[:msg]
272
+ field_def_to_set = value_field_def
273
+ else
274
+ message_value = convert_ruby_to_upb(value, arena, c_type, subtype)
275
+ end
276
+ end
277
+ Google::Protobuf::FFI.set_message_field message_to_alter, field_def_to_set, message_value, arena
278
+ end
279
+
280
+ def c_type
281
+ @c_type ||= Google::Protobuf::FFI.get_c_type(self)
282
+ end
283
+ end
284
+
285
+ class FFI
286
+ # MessageDef
287
+ attach_function :get_field_by_index, :upb_MessageDef_Field, [Descriptor, :int], FieldDescriptor
288
+ attach_function :get_field_by_name, :upb_MessageDef_FindFieldByNameWithSize,[Descriptor, :string, :size_t], FieldDescriptor
289
+ attach_function :get_field_by_number, :upb_MessageDef_FindFieldByNumber, [Descriptor, :uint32_t], FieldDescriptor
290
+
291
+ # FieldDescriptor
292
+ attach_function :get_containing_message_def, :upb_FieldDef_ContainingType, [FieldDescriptor], Descriptor
293
+ attach_function :get_c_type, :upb_FieldDef_CType, [FieldDescriptor], CType
294
+ attach_function :get_default, :upb_FieldDef_Default, [FieldDescriptor], MessageValue.by_value
295
+ attach_function :get_subtype_as_enum, :upb_FieldDef_EnumSubDef, [FieldDescriptor], EnumDescriptor
296
+ attach_function :get_has_presence, :upb_FieldDef_HasPresence, [FieldDescriptor], :bool
297
+ attach_function :is_map, :upb_FieldDef_IsMap, [FieldDescriptor], :bool
298
+ attach_function :is_repeated, :upb_FieldDef_IsRepeated, [FieldDescriptor], :bool
299
+ attach_function :is_sub_message, :upb_FieldDef_IsSubMessage, [FieldDescriptor], :bool
300
+ attach_function :get_json_name, :upb_FieldDef_JsonName, [FieldDescriptor], :string
301
+ attach_function :get_label, :upb_FieldDef_Label, [FieldDescriptor], Label
302
+ attach_function :get_subtype_as_message, :upb_FieldDef_MessageSubDef, [FieldDescriptor], Descriptor
303
+ attach_function :get_full_name, :upb_FieldDef_Name, [FieldDescriptor], :string
304
+ attach_function :get_number, :upb_FieldDef_Number, [FieldDescriptor], :uint32_t
305
+ attach_function :get_type, :upb_FieldDef_Type, [FieldDescriptor], FieldType
306
+ attach_function :file_def_by_raw_field_def, :upb_FieldDef_File, [:pointer], :FileDef
307
+ end
308
+ end
309
+ end