google-protobuf 3.25.0 → 4.29.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/convert.c +46 -18
- data/ext/google/protobuf_c/defs.c +499 -26
- data/ext/google/protobuf_c/extconf.rb +1 -1
- data/ext/google/protobuf_c/glue.c +53 -2
- data/ext/google/protobuf_c/map.c +82 -17
- data/ext/google/protobuf_c/map.h +9 -2
- data/ext/google/protobuf_c/message.c +144 -104
- data/ext/google/protobuf_c/message.h +8 -5
- data/ext/google/protobuf_c/protobuf.c +30 -17
- data/ext/google/protobuf_c/protobuf.h +3 -7
- data/ext/google/protobuf_c/repeated_field.c +64 -10
- data/ext/google/protobuf_c/repeated_field.h +8 -1
- data/ext/google/protobuf_c/ruby-upb.c +13774 -11526
- data/ext/google/protobuf_c/ruby-upb.h +11198 -9048
- data/ext/google/protobuf_c/shared_convert.c +10 -5
- data/ext/google/protobuf_c/shared_convert.h +2 -2
- data/ext/google/protobuf_c/shared_message.c +3 -31
- data/ext/google/protobuf_c/shared_message.h +0 -4
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +467 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -8
- data/lib/google/protobuf/any_pb.rb +1 -22
- data/lib/google/protobuf/api_pb.rb +1 -24
- data/lib/google/protobuf/descriptor_pb.rb +3 -23
- data/lib/google/protobuf/duration_pb.rb +1 -22
- data/lib/google/protobuf/empty_pb.rb +1 -22
- data/lib/google/protobuf/ffi/descriptor.rb +13 -2
- data/lib/google/protobuf/ffi/descriptor_pool.rb +16 -9
- data/lib/google/protobuf/ffi/enum_descriptor.rb +13 -1
- data/lib/google/protobuf/ffi/ffi.rb +8 -6
- data/lib/google/protobuf/ffi/field_descriptor.rb +37 -16
- data/lib/google/protobuf/ffi/file_descriptor.rb +13 -12
- data/lib/google/protobuf/ffi/internal/arena.rb +0 -6
- data/lib/google/protobuf/ffi/internal/convert.rb +21 -30
- data/lib/google/protobuf/ffi/map.rb +50 -13
- data/lib/google/protobuf/ffi/message.rb +202 -58
- data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
- data/lib/google/protobuf/ffi/object_cache.rb +3 -3
- data/lib/google/protobuf/ffi/oneof_descriptor.rb +20 -11
- data/lib/google/protobuf/ffi/repeated_field.rb +50 -142
- data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
- data/lib/google/protobuf/field_mask_pb.rb +1 -22
- data/lib/google/protobuf/internal/object_cache.rb +99 -0
- data/lib/google/protobuf/plugin_pb.rb +2 -24
- data/lib/google/protobuf/repeated_field.rb +4 -5
- data/lib/google/protobuf/source_context_pb.rb +1 -22
- data/lib/google/protobuf/struct_pb.rb +1 -22
- data/lib/google/protobuf/timestamp_pb.rb +1 -22
- data/lib/google/protobuf/type_pb.rb +1 -24
- data/lib/google/protobuf/wrappers_pb.rb +1 -22
- data/lib/google/protobuf.rb +1 -1
- data/lib/google/protobuf_ffi.rb +3 -2
- data/lib/google/protobuf_native.rb +0 -1
- data/lib/google/tasks/ffi.rake +1 -3
- metadata +25 -12
- data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
- data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
- data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
- data/lib/google/protobuf/descriptor_dsl.rb +0 -465
- data/lib/google/protobuf/object_cache.rb +0 -97
@@ -9,18 +9,20 @@ module Google
|
|
9
9
|
module Protobuf
|
10
10
|
class FFI
|
11
11
|
# Map
|
12
|
-
attach_function :map_clear,
|
13
|
-
attach_function :map_delete,
|
14
|
-
attach_function :map_get,
|
15
|
-
attach_function :create_map,
|
16
|
-
attach_function :map_size,
|
17
|
-
attach_function :map_set,
|
12
|
+
attach_function :map_clear, :upb_Map_Clear, [:Map], :void
|
13
|
+
attach_function :map_delete, :upb_Map_Delete, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool
|
14
|
+
attach_function :map_get, :upb_Map_Get, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool
|
15
|
+
attach_function :create_map, :upb_Map_New, [Internal::Arena, CType, CType], :Map
|
16
|
+
attach_function :map_size, :upb_Map_Size, [:Map], :size_t
|
17
|
+
attach_function :map_set, :upb_Map_Set, [:Map, MessageValue.by_value, MessageValue.by_value, Internal::Arena], :bool
|
18
|
+
attach_function :map_freeze, :upb_Map_Freeze, [:Map, MiniTable.by_ref], :void
|
19
|
+
attach_function :map_frozen?, :upb_Map_IsFrozen, [:Map], :bool
|
18
20
|
|
19
21
|
# MapIterator
|
20
|
-
attach_function :map_next,
|
21
|
-
attach_function :map_done,
|
22
|
-
attach_function :map_key,
|
23
|
-
attach_function :map_value,
|
22
|
+
attach_function :map_next, :upb_MapIterator_Next, [:Map, :pointer], :bool
|
23
|
+
attach_function :map_done, :upb_MapIterator_Done, [:Map, :size_t], :bool
|
24
|
+
attach_function :map_key, :upb_MapIterator_Key, [:Map, :size_t], MessageValue.by_value
|
25
|
+
attach_function :map_value, :upb_MapIterator_Value, [:Map, :size_t], MessageValue.by_value
|
24
26
|
end
|
25
27
|
class Map
|
26
28
|
include Enumerable
|
@@ -155,6 +157,37 @@ module Google
|
|
155
157
|
end
|
156
158
|
alias size length
|
157
159
|
|
160
|
+
##
|
161
|
+
# Is this object frozen?
|
162
|
+
# Returns true if either this Ruby wrapper or the underlying
|
163
|
+
# representation are frozen. Freezes the wrapper if the underlying
|
164
|
+
# representation is already frozen but this wrapper isn't.
|
165
|
+
def frozen?
|
166
|
+
unless Google::Protobuf::FFI.map_frozen? @map_ptr
|
167
|
+
raise RuntimeError.new "Ruby frozen Map with mutable representation" if super
|
168
|
+
return false
|
169
|
+
end
|
170
|
+
method(:freeze).super_method.call unless super
|
171
|
+
true
|
172
|
+
end
|
173
|
+
|
174
|
+
##
|
175
|
+
# Freezes the map object. We have to intercept this so we can freeze the
|
176
|
+
# underlying representation, not just the Ruby wrapper. Returns self.
|
177
|
+
def freeze
|
178
|
+
if method(:frozen?).super_method.call
|
179
|
+
unless Google::Protobuf::FFI.map_frozen? @map_ptr
|
180
|
+
raise RuntimeError.new "Underlying representation of map still mutable despite frozen wrapper"
|
181
|
+
end
|
182
|
+
return self
|
183
|
+
end
|
184
|
+
unless Google::Protobuf::FFI.map_frozen? @map_ptr
|
185
|
+
mini_table = (value_type == :message) ? Google::Protobuf::FFI.get_mini_table(@descriptor) : nil
|
186
|
+
Google::Protobuf::FFI.map_freeze(@map_ptr, mini_table)
|
187
|
+
end
|
188
|
+
super
|
189
|
+
end
|
190
|
+
|
158
191
|
##
|
159
192
|
# call-seq:
|
160
193
|
# Map.dup => new_map
|
@@ -358,10 +391,14 @@ module Google
|
|
358
391
|
OBJECT_CACHE.try_add(@map_ptr.address, self)
|
359
392
|
end
|
360
393
|
|
361
|
-
|
362
|
-
#
|
394
|
+
##
|
395
|
+
# Constructor that uses the type information from the given
|
396
|
+
# FieldDescriptor to configure the new Map instance.
|
397
|
+
# @param field [FieldDescriptor] Type information for the new Map
|
363
398
|
# @param arena [Arena] Owning message's arena
|
364
|
-
|
399
|
+
# @param value [Hash|Map] Initial value
|
400
|
+
# @param map [::FFI::Pointer] Existing upb_Map
|
401
|
+
def self.construct_for_field(field, arena: nil, value: nil, map: nil)
|
365
402
|
raise ArgumentError.new "Expected Hash object as initializer value for map field '#{field.name}' (given #{value.class})." unless value.nil? or value.is_a? Hash
|
366
403
|
instance = allocate
|
367
404
|
raise ArgumentError.new "Expected field with type :message, instead got #{field.class}" unless field.type == :message
|
@@ -17,12 +17,16 @@ module Google
|
|
17
17
|
attach_function :get_message_has, :upb_Message_HasFieldByDef, [:Message, FieldDescriptor], :bool
|
18
18
|
attach_function :set_message_field, :upb_Message_SetFieldByDef, [:Message, FieldDescriptor, MessageValue.by_value, Internal::Arena], :bool
|
19
19
|
attach_function :encode_message, :upb_Encode, [:Message, MiniTable.by_ref, :size_t, Internal::Arena, :pointer, :pointer], EncodeStatus
|
20
|
-
attach_function :
|
20
|
+
attach_function :json_decode_message_detecting_nonconformance, :upb_JsonDecodeDetectingNonconformance, [:binary_string, :size_t, :Message, Descriptor, :DefPool, :int, Internal::Arena, Status.by_ref], :int
|
21
21
|
attach_function :json_encode_message, :upb_JsonEncode, [:Message, Descriptor, :DefPool, :int, :binary_string, :size_t, Status.by_ref], :size_t
|
22
|
-
attach_function :decode_message, :upb_Decode,
|
22
|
+
attach_function :decode_message, :upb_Decode, [:binary_string, :size_t, :Message, MiniTable.by_ref, :ExtensionRegistry, :int, Internal::Arena], DecodeStatus
|
23
23
|
attach_function :get_mutable_message, :upb_Message_Mutable, [:Message, FieldDescriptor, Internal::Arena], MutableMessageValue.by_value
|
24
|
-
attach_function :get_message_which_oneof, :
|
24
|
+
attach_function :get_message_which_oneof, :upb_Message_WhichOneofByDef, [:Message, OneofDescriptor], FieldDescriptor
|
25
25
|
attach_function :message_discard_unknown, :upb_Message_DiscardUnknown, [:Message, Descriptor, :int], :bool
|
26
|
+
attach_function :message_next, :upb_Message_Next, [:Message, Descriptor, :DefPool, :FieldDefPointer, MessageValue.by_ref, :pointer], :bool
|
27
|
+
attach_function :message_freeze, :upb_Message_Freeze, [:Message, MiniTable.by_ref], :void
|
28
|
+
attach_function :message_frozen?, :upb_Message_IsFrozen, [:Message], :bool
|
29
|
+
|
26
30
|
# MessageValue
|
27
31
|
attach_function :message_value_equal, :shared_Msgval_IsEqual, [MessageValue.by_value, MessageValue.by_value, CType, Descriptor], :bool
|
28
32
|
attach_function :message_value_hash, :shared_Msgval_GetHash, [MessageValue.by_value, CType, Descriptor, :uint64_t], :uint64_t
|
@@ -57,11 +61,35 @@ module Google
|
|
57
61
|
instance
|
58
62
|
end
|
59
63
|
|
64
|
+
##
|
65
|
+
# Is this object frozen?
|
66
|
+
# Returns true if either this Ruby wrapper or the underlying
|
67
|
+
# representation are frozen. Freezes the wrapper if the underlying
|
68
|
+
# representation is already frozen but this wrapper isn't.
|
69
|
+
def frozen?
|
70
|
+
unless Google::Protobuf::FFI.message_frozen? @msg
|
71
|
+
raise RuntimeError.new "Ruby frozen Message with mutable representation" if super
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
method(:freeze).super_method.call unless super
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Freezes the map object. We have to intercept this so we can freeze the
|
80
|
+
# underlying representation, not just the Ruby wrapper. Returns self.
|
60
81
|
def freeze
|
82
|
+
if method(:frozen?).super_method.call
|
83
|
+
unless Google::Protobuf::FFI.message_frozen? @msg
|
84
|
+
raise RuntimeError.new "Underlying representation of message still mutable despite frozen wrapper"
|
85
|
+
end
|
86
|
+
return self
|
87
|
+
end
|
88
|
+
unless Google::Protobuf::FFI.message_frozen? @msg
|
89
|
+
Google::Protobuf::FFI.message_freeze(@msg, Google::Protobuf::FFI.get_mini_table(self.class.descriptor))
|
90
|
+
end
|
61
91
|
super
|
62
|
-
|
63
|
-
self
|
64
|
-
end
|
92
|
+
end
|
65
93
|
|
66
94
|
def dup
|
67
95
|
duplicate = self.class.private_constructor(@arena)
|
@@ -170,7 +198,15 @@ module Google
|
|
170
198
|
|
171
199
|
message = new
|
172
200
|
mini_table_ptr = Google::Protobuf::FFI.get_mini_table(message.class.descriptor)
|
173
|
-
status = Google::Protobuf::FFI.decode_message(
|
201
|
+
status = Google::Protobuf::FFI.decode_message(
|
202
|
+
data,
|
203
|
+
data.bytesize,
|
204
|
+
message.instance_variable_get(:@msg),
|
205
|
+
mini_table_ptr,
|
206
|
+
Google::Protobuf::FFI.get_extension_registry(message.class.descriptor.send(:pool).descriptor_pool),
|
207
|
+
decoding_options,
|
208
|
+
message.instance_variable_get(:@arena)
|
209
|
+
)
|
174
210
|
raise ParseError.new "Error occurred during parsing" unless status == :Ok
|
175
211
|
message
|
176
212
|
end
|
@@ -234,7 +270,11 @@ module Google
|
|
234
270
|
message = new
|
235
271
|
pool_def = message.class.descriptor.instance_variable_get(:@descriptor_pool).descriptor_pool
|
236
272
|
status = Google::Protobuf::FFI::Status.new
|
237
|
-
|
273
|
+
result = Google::Protobuf::FFI.json_decode_message_detecting_nonconformance(data, data.bytesize, message.instance_variable_get(:@msg), message.class.descriptor, pool_def, decoding_options, message.instance_variable_get(:@arena), status)
|
274
|
+
case result
|
275
|
+
when Google::Protobuf::FFI::Upb_JsonDecodeResult_OkWithEmptyStringNumerics
|
276
|
+
warn Google::Protobuf::FFI.error_message(status)
|
277
|
+
when Google::Protobuf::FFI::Upb_JsonDecodeResult_Error
|
238
278
|
raise ParseError.new "Error occurred during parsing: #{Google::Protobuf::FFI.error_message(status)}"
|
239
279
|
end
|
240
280
|
message
|
@@ -293,42 +333,136 @@ module Google
|
|
293
333
|
|
294
334
|
include Google::Protobuf::Internal::Convert
|
295
335
|
|
336
|
+
##
|
337
|
+
# Checks ObjectCache for a sentinel empty frozen Map of the key and
|
338
|
+
# value types matching the field descriptor's MessageDef and returns
|
339
|
+
# the cache entry. If an entry is not found, one is created and added
|
340
|
+
# to the cache keyed by the MessageDef pointer first.
|
341
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
342
|
+
def empty_frozen_map(field_descriptor)
|
343
|
+
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor
|
344
|
+
frozen_map = OBJECT_CACHE.get sub_message_def
|
345
|
+
if frozen_map.nil?
|
346
|
+
frozen_map = Google::Protobuf::Map.send(:construct_for_field, field_descriptor)
|
347
|
+
OBJECT_CACHE.try_add(sub_message_def, frozen_map.freeze)
|
348
|
+
end
|
349
|
+
raise "Empty Frozen Map is not frozen" unless frozen_map.frozen?
|
350
|
+
frozen_map
|
351
|
+
end
|
352
|
+
|
353
|
+
##
|
354
|
+
# Returns a frozen Map instance for the given field. If the message
|
355
|
+
# already has a value for that field, it is used. If not, a sentinel
|
356
|
+
# (per FieldDescriptor) empty frozen Map is returned instead.
|
357
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
358
|
+
def frozen_map_from_field_descriptor(field_descriptor)
|
359
|
+
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
360
|
+
return empty_frozen_map field_descriptor if message_value[:map_val].null?
|
361
|
+
get_map_field(message_value[:map_val], field_descriptor).freeze
|
362
|
+
end
|
363
|
+
|
364
|
+
##
|
365
|
+
# Returns a Map instance for the given field. If the message is frozen
|
366
|
+
# the return value is also frozen. If not, a mutable instance is
|
367
|
+
# returned instead.
|
368
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
369
|
+
def map_from_field_descriptor(field_descriptor)
|
370
|
+
return frozen_map_from_field_descriptor field_descriptor if frozen?
|
371
|
+
mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
|
372
|
+
get_map_field(mutable_message_value[:map], field_descriptor)
|
373
|
+
end
|
374
|
+
|
375
|
+
##
|
376
|
+
# Checks ObjectCache for a sentinel empty frozen RepeatedField of the
|
377
|
+
# value type matching the field descriptor's MessageDef and returns
|
378
|
+
# the cache entry. If an entry is not found, one is created and added
|
379
|
+
# to the cache keyed by the MessageDef pointer first.
|
380
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
381
|
+
def empty_frozen_repeated_field(field_descriptor)
|
382
|
+
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor
|
383
|
+
frozen_repeated_field = OBJECT_CACHE.get sub_message_def
|
384
|
+
if frozen_repeated_field.nil?
|
385
|
+
frozen_repeated_field = Google::Protobuf::RepeatedField.send(:construct_for_field, field_descriptor)
|
386
|
+
OBJECT_CACHE.try_add(sub_message_def, frozen_repeated_field.freeze)
|
387
|
+
end
|
388
|
+
raise "Empty frozen RepeatedField is not frozen" unless frozen_repeated_field.frozen?
|
389
|
+
frozen_repeated_field
|
390
|
+
end
|
391
|
+
|
392
|
+
##
|
393
|
+
# Returns a frozen RepeatedField instance for the given field. If the
|
394
|
+
# message already has a value for that field, it is used. If not, a
|
395
|
+
# sentinel (per FieldDescriptor) empty frozen RepeatedField is
|
396
|
+
# returned instead.
|
397
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
398
|
+
def frozen_repeated_field_from_field_descriptor(field_descriptor)
|
399
|
+
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
400
|
+
return empty_frozen_repeated_field field_descriptor if message_value[:array_val].null?
|
401
|
+
get_repeated_field(message_value[:array_val], field_descriptor).freeze
|
402
|
+
end
|
403
|
+
|
404
|
+
##
|
405
|
+
# Returns a RepeatedField instance for the given field. If the message
|
406
|
+
# is frozen the return value is also frozen. If not, a mutable
|
407
|
+
# instance is returned instead.
|
408
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
409
|
+
def repeated_field_from_field_descriptor(field_descriptor)
|
410
|
+
return frozen_repeated_field_from_field_descriptor field_descriptor if frozen?
|
411
|
+
mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
|
412
|
+
get_repeated_field(mutable_message_value[:array], field_descriptor)
|
413
|
+
end
|
414
|
+
|
415
|
+
##
|
416
|
+
# Returns a Message instance for the given field. If the message
|
417
|
+
# is frozen nil is always returned. Otherwise, a mutable instance is
|
418
|
+
# returned instead.
|
419
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
420
|
+
def message_from_field_descriptor(field_descriptor)
|
421
|
+
return nil if frozen?
|
422
|
+
return nil unless Google::Protobuf::FFI.get_message_has @msg, field_descriptor
|
423
|
+
mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
|
424
|
+
sub_message = mutable_message[:msg]
|
425
|
+
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor
|
426
|
+
Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
|
427
|
+
end
|
428
|
+
|
429
|
+
##
|
430
|
+
# Returns a scalar value for the given field. If the message
|
431
|
+
# is frozen the return value is also frozen.
|
432
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
433
|
+
def scalar_from_field_descriptor(field_descriptor)
|
434
|
+
c_type = field_descriptor.send(:c_type)
|
435
|
+
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
436
|
+
msg_or_enum_def = c_type == :enum ? Google::Protobuf::FFI.get_subtype_as_enum(field_descriptor) : nil
|
437
|
+
return_value = convert_upb_to_ruby message_value, c_type, msg_or_enum_def
|
438
|
+
frozen? ? return_value.freeze : return_value
|
439
|
+
end
|
440
|
+
|
441
|
+
##
|
442
|
+
# Dynamically define accessors methods for every field of @descriptor.
|
443
|
+
# Methods with names that conflict with existing methods are skipped.
|
296
444
|
def self.setup_accessors!
|
297
445
|
@descriptor.each do |field_descriptor|
|
298
446
|
field_name = field_descriptor.name
|
299
447
|
unless instance_methods(true).include?(field_name.to_sym)
|
300
|
-
#
|
301
|
-
#
|
448
|
+
# Dispatching to either index_internal or get_field is logically
|
449
|
+
# correct, but slightly slower due to having to perform extra
|
450
|
+
# lookups on each invocation rather than doing it once here.
|
302
451
|
if field_descriptor.map?
|
303
452
|
define_method(field_name) do
|
304
|
-
|
305
|
-
get_map_field(mutable_message_value[:map], field_descriptor)
|
453
|
+
map_from_field_descriptor field_descriptor
|
306
454
|
end
|
307
455
|
elsif field_descriptor.repeated?
|
308
456
|
define_method(field_name) do
|
309
|
-
|
310
|
-
get_repeated_field(mutable_message_value[:array], field_descriptor)
|
457
|
+
repeated_field_from_field_descriptor field_descriptor
|
311
458
|
end
|
312
459
|
elsif field_descriptor.sub_message?
|
313
460
|
define_method(field_name) do
|
314
|
-
|
315
|
-
mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
|
316
|
-
sub_message = mutable_message[:msg]
|
317
|
-
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message(field_descriptor)
|
318
|
-
Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
|
461
|
+
message_from_field_descriptor field_descriptor
|
319
462
|
end
|
320
463
|
else
|
321
|
-
|
322
|
-
|
323
|
-
define_method(field_name) do
|
324
|
-
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
325
|
-
convert_upb_to_ruby message_value, c_type, Google::Protobuf::FFI.get_subtype_as_enum(field_descriptor)
|
326
|
-
end
|
327
|
-
else
|
328
|
-
define_method(field_name) do
|
329
|
-
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
330
|
-
convert_upb_to_ruby message_value, c_type
|
331
|
-
end
|
464
|
+
define_method(field_name) do
|
465
|
+
scalar_from_field_descriptor field_descriptor
|
332
466
|
end
|
333
467
|
end
|
334
468
|
define_method("#{field_name}=") do |value|
|
@@ -338,14 +472,16 @@ module Google
|
|
338
472
|
clear_internal(field_descriptor)
|
339
473
|
end
|
340
474
|
if field_descriptor.type == :enum
|
341
|
-
|
342
|
-
|
475
|
+
if field_descriptor.repeated?
|
476
|
+
define_method("#{field_name}_const") do
|
343
477
|
return_value = []
|
344
|
-
|
478
|
+
repeated_field_from_field_descriptor(field_descriptor).send(:each_msg_val) do |msg_val|
|
345
479
|
return_value << msg_val[:int32_val]
|
346
480
|
end
|
347
481
|
return_value
|
348
|
-
|
482
|
+
end
|
483
|
+
else
|
484
|
+
define_method("#{field_name}_const") do
|
349
485
|
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
350
486
|
message_value[:int32_val]
|
351
487
|
end
|
@@ -372,12 +508,21 @@ module Google
|
|
372
508
|
end
|
373
509
|
end
|
374
510
|
|
511
|
+
##
|
512
|
+
# Dynamically define accessors methods for every OneOf field of
|
513
|
+
# @descriptor.
|
375
514
|
def self.setup_oneof_accessors!
|
376
515
|
@oneof_field_names = []
|
377
516
|
@descriptor.each_oneof do |oneof_descriptor|
|
378
517
|
self.add_oneof_accessors_for! oneof_descriptor
|
379
518
|
end
|
380
519
|
end
|
520
|
+
|
521
|
+
##
|
522
|
+
# Dynamically define accessors methods for the given OneOf field.
|
523
|
+
# Methods with names that conflict with existing methods are skipped.
|
524
|
+
# @param oneof_descriptor [OneofDescriptor] Field to create accessors
|
525
|
+
# for.
|
381
526
|
def self.add_oneof_accessors_for!(oneof_descriptor)
|
382
527
|
field_name = oneof_descriptor.name.to_sym
|
383
528
|
@oneof_field_names << field_name
|
@@ -508,6 +653,10 @@ module Google
|
|
508
653
|
Google::Protobuf::FFI.clear_message_field(@msg, field_def)
|
509
654
|
end
|
510
655
|
|
656
|
+
# Accessor for field by name. Does not delegate to methods setup by
|
657
|
+
# self.setup_accessors! in order to avoid conflicts with bad field
|
658
|
+
# names e.g. `dup` or `class` which are perfectly valid for proto
|
659
|
+
# fields.
|
511
660
|
def index_internal(name)
|
512
661
|
field_descriptor = self.class.descriptor.lookup(name)
|
513
662
|
get_field field_descriptor unless field_descriptor.nil?
|
@@ -535,7 +684,7 @@ module Google
|
|
535
684
|
# one if omitted or nil.
|
536
685
|
def initialize(initial_value = nil, arena = nil, msg = nil)
|
537
686
|
@arena = arena || Google::Protobuf::FFI.create_arena
|
538
|
-
@msg = msg || Google::Protobuf::FFI.new_message_from_def(self.class.descriptor, @arena)
|
687
|
+
@msg = msg || Google::Protobuf::FFI.new_message_from_def(Google::Protobuf::FFI.get_mini_table(self.class.descriptor), @arena)
|
539
688
|
|
540
689
|
unless initial_value.nil?
|
541
690
|
raise ArgumentError.new "Expected hash arguments or message, not #{initial_value.class}" unless initial_value.respond_to? :each
|
@@ -556,9 +705,9 @@ module Google
|
|
556
705
|
|
557
706
|
next if value.nil?
|
558
707
|
if field_descriptor.map?
|
559
|
-
index_assign_internal(Google::Protobuf::Map.send(:construct_for_field, field_descriptor, @arena, value: value), name: key.to_s)
|
708
|
+
index_assign_internal(Google::Protobuf::Map.send(:construct_for_field, field_descriptor, arena: @arena, value: value), name: key.to_s)
|
560
709
|
elsif field_descriptor.repeated?
|
561
|
-
index_assign_internal(RepeatedField.send(:construct_for_field, field_descriptor, @arena, values: value), name: key.to_s)
|
710
|
+
index_assign_internal(RepeatedField.send(:construct_for_field, field_descriptor, arena: @arena, values: value), name: key.to_s)
|
562
711
|
else
|
563
712
|
index_assign_internal(value, name: key.to_s)
|
564
713
|
end
|
@@ -571,21 +720,20 @@ module Google
|
|
571
720
|
end
|
572
721
|
|
573
722
|
##
|
574
|
-
# Gets a field of this message identified by
|
723
|
+
# Gets a field of this message identified by FieldDescriptor.
|
575
724
|
#
|
576
|
-
# @param field [FieldDescriptor]
|
725
|
+
# @param field [FieldDescriptor] Field to retrieve.
|
726
|
+
# @param unwrap [Boolean](false) If true, unwraps wrappers.
|
577
727
|
def get_field(field, unwrap: false)
|
578
728
|
if field.map?
|
579
|
-
|
580
|
-
get_map_field(mutable_message_value[:map], field)
|
729
|
+
map_from_field_descriptor field
|
581
730
|
elsif field.repeated?
|
582
|
-
|
583
|
-
get_repeated_field(mutable_message_value[:array], field)
|
731
|
+
repeated_field_from_field_descriptor field
|
584
732
|
elsif field.sub_message?
|
585
733
|
return nil unless Google::Protobuf::FFI.get_message_has @msg, field
|
586
|
-
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message(field)
|
587
734
|
if unwrap
|
588
735
|
if field.has?(self)
|
736
|
+
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field
|
589
737
|
wrapper_message_value = Google::Protobuf::FFI.get_message_value @msg, field
|
590
738
|
fields = Google::Protobuf::FFI.field_count(sub_message_def)
|
591
739
|
raise "Sub message has #{fields} fields! Expected exactly 1." unless fields == 1
|
@@ -596,41 +744,37 @@ module Google
|
|
596
744
|
nil
|
597
745
|
end
|
598
746
|
else
|
599
|
-
|
600
|
-
sub_message = mutable_message[:msg]
|
601
|
-
Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
|
747
|
+
message_from_field_descriptor field
|
602
748
|
end
|
603
749
|
else
|
604
|
-
|
605
|
-
message_value = Google::Protobuf::FFI.get_message_value @msg, field
|
606
|
-
if c_type == :enum
|
607
|
-
convert_upb_to_ruby message_value, c_type, Google::Protobuf::FFI.get_subtype_as_enum(field)
|
608
|
-
else
|
609
|
-
convert_upb_to_ruby message_value, c_type
|
610
|
-
end
|
750
|
+
scalar_from_field_descriptor field
|
611
751
|
end
|
612
752
|
end
|
613
753
|
|
614
754
|
##
|
615
|
-
#
|
755
|
+
# Gets a RepeatedField from the ObjectCache or creates a new one.
|
756
|
+
# @param array [::FFI::Pointer] Pointer to the upb_Array
|
616
757
|
# @param field [Google::Protobuf::FieldDescriptor] Type of the repeated field
|
617
758
|
def get_repeated_field(array, field)
|
618
759
|
return nil if array.nil? or array.null?
|
619
760
|
repeated_field = OBJECT_CACHE.get(array.address)
|
620
761
|
if repeated_field.nil?
|
621
|
-
repeated_field = RepeatedField.send(:construct_for_field, field, @arena, array: array)
|
762
|
+
repeated_field = RepeatedField.send(:construct_for_field, field, arena: @arena, array: array)
|
763
|
+
repeated_field.freeze if frozen?
|
622
764
|
end
|
623
765
|
repeated_field
|
624
766
|
end
|
625
767
|
|
626
768
|
##
|
627
|
-
#
|
769
|
+
# Gets a Map from the ObjectCache or creates a new one.
|
770
|
+
# @param map [::FFI::Pointer] Pointer to the upb_Map
|
628
771
|
# @param field [Google::Protobuf::FieldDescriptor] Type of the map field
|
629
772
|
def get_map_field(map, field)
|
630
773
|
return nil if map.nil? or map.null?
|
631
774
|
map_field = OBJECT_CACHE.get(map.address)
|
632
775
|
if map_field.nil?
|
633
|
-
map_field = Google::Protobuf::Map.send(:construct_for_field, field, @arena, map: map)
|
776
|
+
map_field = Google::Protobuf::Map.send(:construct_for_field, field, arena: @arena, map: map)
|
777
|
+
map_field.freeze if frozen?
|
634
778
|
end
|
635
779
|
map_field
|
636
780
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# Protocol Buffers - Google's data interchange format
|
2
|
+
# Copyright 2024 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 MethodDescriptor
|
11
|
+
attr :method_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 [MethodDescriptor] MethodDescriptor to convert to an FFI native type
|
24
|
+
# @param _ [Object] Unused
|
25
|
+
def to_native(value, _)
|
26
|
+
method_def_ptr = value.nil? ? nil : value.instance_variable_get(:@method_def)
|
27
|
+
return ::FFI::Pointer::NULL if method_def_ptr.nil?
|
28
|
+
raise "Underlying method_def was null!" if method_def_ptr.null?
|
29
|
+
method_def_ptr
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# @param service_def [::FFI::Pointer] MethodDef pointer to be wrapped
|
34
|
+
# @param _ [Object] Unused
|
35
|
+
def from_native(method_def, _ = nil)
|
36
|
+
return nil if method_def.nil? or method_def.null?
|
37
|
+
service_def = Google::Protobuf::FFI.raw_service_def_by_raw_method_def(method_def)
|
38
|
+
file_def = Google::Protobuf::FFI.file_def_by_raw_service_def(service_def)
|
39
|
+
descriptor_from_file_def(file_def, method_def)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.new(*arguments, &block)
|
44
|
+
raise "Descriptor objects may not be created from Ruby."
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
inspect
|
49
|
+
end
|
50
|
+
|
51
|
+
def inspect
|
52
|
+
"#{self.class.name}: #{name}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def name
|
56
|
+
@name ||= Google::Protobuf::FFI.get_method_name(self)
|
57
|
+
end
|
58
|
+
|
59
|
+
def options
|
60
|
+
@options ||= begin
|
61
|
+
size_ptr = ::FFI::MemoryPointer.new(:size_t, 1)
|
62
|
+
temporary_arena = Google::Protobuf::FFI.create_arena
|
63
|
+
buffer = Google::Protobuf::FFI.method_options(self, size_ptr, temporary_arena)
|
64
|
+
Google::Protobuf::MethodOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze).freeze
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def input_type
|
69
|
+
@input_type ||= Google::Protobuf::FFI.method_input_type(self)
|
70
|
+
end
|
71
|
+
|
72
|
+
def output_type
|
73
|
+
@output_type ||= Google::Protobuf::FFI.method_output_type(self)
|
74
|
+
end
|
75
|
+
|
76
|
+
def client_streaming
|
77
|
+
@client_streaming ||= Google::Protobuf::FFI.method_client_streaming(self)
|
78
|
+
end
|
79
|
+
|
80
|
+
def server_streaming
|
81
|
+
@server_streaming ||= Google::Protobuf::FFI.method_server_streaming(self)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def initialize(method_def, descriptor_pool)
|
87
|
+
@method_def = method_def
|
88
|
+
@descriptor_pool = descriptor_pool
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.private_constructor(method_def, descriptor_pool)
|
92
|
+
instance = allocate
|
93
|
+
instance.send(:initialize, method_def, descriptor_pool)
|
94
|
+
instance
|
95
|
+
end
|
96
|
+
|
97
|
+
def c_type
|
98
|
+
@c_type ||= Google::Protobuf::FFI.get_c_type(self)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class FFI
|
103
|
+
# MethodDef
|
104
|
+
attach_function :raw_service_def_by_raw_method_def, :upb_MethodDef_Service, [:pointer], :pointer
|
105
|
+
attach_function :get_method_name, :upb_MethodDef_Name, [MethodDescriptor], :string
|
106
|
+
attach_function :method_options, :MethodDescriptor_serialized_options, [MethodDescriptor, :pointer, Internal::Arena], :pointer
|
107
|
+
attach_function :method_input_type, :upb_MethodDef_InputType, [MethodDescriptor], Descriptor
|
108
|
+
attach_function :method_output_type, :upb_MethodDef_OutputType, [MethodDescriptor], Descriptor
|
109
|
+
attach_function :method_client_streaming, :upb_MethodDef_ClientStreaming, [MethodDescriptor], :bool
|
110
|
+
attach_function :method_server_streaming, :upb_MethodDef_ServerStreaming, [MethodDescriptor], :bool
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
@@ -18,13 +18,13 @@ module Google
|
|
18
18
|
|
19
19
|
def self.cache_implementation
|
20
20
|
if interpreter_supports_non_finalized_keys_in_weak_map? and SIZEOF_LONG >= SIZEOF_VALUE
|
21
|
-
Google::Protobuf::ObjectCache
|
21
|
+
Google::Protobuf::Internal::ObjectCache
|
22
22
|
else
|
23
|
-
Google::Protobuf::LegacyObjectCache
|
23
|
+
Google::Protobuf::Internal::LegacyObjectCache
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
public
|
28
28
|
OBJECT_CACHE = cache_implementation.new
|
29
29
|
end
|
30
|
-
end
|
30
|
+
end
|