google-protobuf 3.25.5-x86-linux → 4.29.1-x86-linux
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 +368 -30
- data/ext/google/protobuf_c/extconf.rb +1 -1
- data/ext/google/protobuf_c/glue.c +16 -0
- data/ext/google/protobuf_c/map.c +74 -29
- data/ext/google/protobuf_c/map.h +7 -3
- data/ext/google/protobuf_c/message.c +120 -118
- data/ext/google/protobuf_c/message.h +2 -6
- 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 +58 -23
- data/ext/google/protobuf_c/repeated_field.h +6 -2
- data/ext/google/protobuf_c/ruby-upb.c +13774 -11526
- data/ext/google/protobuf_c/ruby-upb.h +11200 -9050
- 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/3.0/protobuf_c.so +0 -0
- data/lib/google/3.1/protobuf_c.so +0 -0
- data/lib/google/3.2/protobuf_c.so +0 -0
- data/lib/google/3.3/protobuf_c.so +0 -0
- 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 +4 -4
- data/lib/google/protobuf/ffi/descriptor_pool.rb +3 -1
- data/lib/google/protobuf/ffi/enum_descriptor.rb +3 -1
- data/lib/google/protobuf/ffi/ffi.rb +8 -6
- data/lib/google/protobuf/ffi/field_descriptor.rb +13 -2
- data/lib/google/protobuf/ffi/file_descriptor.rb +3 -13
- 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 -24
- data/lib/google/protobuf/ffi/message.rb +189 -66
- 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 +3 -1
- data/lib/google/protobuf/ffi/repeated_field.rb +47 -19
- 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 -13
- 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/2.7/protobuf_c.so +0 -0
- data/lib/google/protobuf/descriptor_dsl.rb +0 -465
- data/lib/google/protobuf/object_cache.rb +0 -97
@@ -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
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)
|
@@ -242,7 +270,11 @@ module Google
|
|
242
270
|
message = new
|
243
271
|
pool_def = message.class.descriptor.instance_variable_get(:@descriptor_pool).descriptor_pool
|
244
272
|
status = Google::Protobuf::FFI::Status.new
|
245
|
-
|
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
|
246
278
|
raise ParseError.new "Error occurred during parsing: #{Google::Protobuf::FFI.error_message(status)}"
|
247
279
|
end
|
248
280
|
message
|
@@ -301,53 +333,136 @@ module Google
|
|
301
333
|
|
302
334
|
include Google::Protobuf::Internal::Convert
|
303
335
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
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)
|
311
348
|
end
|
312
|
-
|
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
|
313
402
|
end
|
314
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.
|
315
444
|
def self.setup_accessors!
|
316
445
|
@descriptor.each do |field_descriptor|
|
317
446
|
field_name = field_descriptor.name
|
318
447
|
unless instance_methods(true).include?(field_name.to_sym)
|
319
|
-
#
|
320
|
-
#
|
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.
|
321
451
|
if field_descriptor.map?
|
322
452
|
define_method(field_name) do
|
323
|
-
|
324
|
-
get_map_field(mutable_message_value[:map], field_descriptor)
|
453
|
+
map_from_field_descriptor field_descriptor
|
325
454
|
end
|
326
455
|
elsif field_descriptor.repeated?
|
327
456
|
define_method(field_name) do
|
328
|
-
|
329
|
-
get_repeated_field(mutable_message_value[:array], field_descriptor)
|
457
|
+
repeated_field_from_field_descriptor field_descriptor
|
330
458
|
end
|
331
459
|
elsif field_descriptor.sub_message?
|
332
460
|
define_method(field_name) do
|
333
|
-
|
334
|
-
mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
|
335
|
-
sub_message = mutable_message[:msg]
|
336
|
-
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message(field_descriptor)
|
337
|
-
Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
|
461
|
+
message_from_field_descriptor field_descriptor
|
338
462
|
end
|
339
463
|
else
|
340
|
-
|
341
|
-
|
342
|
-
define_method(field_name) do
|
343
|
-
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
344
|
-
convert_upb_to_ruby message_value, c_type, Google::Protobuf::FFI.get_subtype_as_enum(field_descriptor)
|
345
|
-
end
|
346
|
-
else
|
347
|
-
define_method(field_name) do
|
348
|
-
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
349
|
-
convert_upb_to_ruby message_value, c_type
|
350
|
-
end
|
464
|
+
define_method(field_name) do
|
465
|
+
scalar_from_field_descriptor field_descriptor
|
351
466
|
end
|
352
467
|
end
|
353
468
|
define_method("#{field_name}=") do |value|
|
@@ -357,14 +472,16 @@ module Google
|
|
357
472
|
clear_internal(field_descriptor)
|
358
473
|
end
|
359
474
|
if field_descriptor.type == :enum
|
360
|
-
|
361
|
-
|
475
|
+
if field_descriptor.repeated?
|
476
|
+
define_method("#{field_name}_const") do
|
362
477
|
return_value = []
|
363
|
-
|
478
|
+
repeated_field_from_field_descriptor(field_descriptor).send(:each_msg_val) do |msg_val|
|
364
479
|
return_value << msg_val[:int32_val]
|
365
480
|
end
|
366
481
|
return_value
|
367
|
-
|
482
|
+
end
|
483
|
+
else
|
484
|
+
define_method("#{field_name}_const") do
|
368
485
|
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
369
486
|
message_value[:int32_val]
|
370
487
|
end
|
@@ -391,12 +508,21 @@ module Google
|
|
391
508
|
end
|
392
509
|
end
|
393
510
|
|
511
|
+
##
|
512
|
+
# Dynamically define accessors methods for every OneOf field of
|
513
|
+
# @descriptor.
|
394
514
|
def self.setup_oneof_accessors!
|
395
515
|
@oneof_field_names = []
|
396
516
|
@descriptor.each_oneof do |oneof_descriptor|
|
397
517
|
self.add_oneof_accessors_for! oneof_descriptor
|
398
518
|
end
|
399
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.
|
400
526
|
def self.add_oneof_accessors_for!(oneof_descriptor)
|
401
527
|
field_name = oneof_descriptor.name.to_sym
|
402
528
|
@oneof_field_names << field_name
|
@@ -527,6 +653,10 @@ module Google
|
|
527
653
|
Google::Protobuf::FFI.clear_message_field(@msg, field_def)
|
528
654
|
end
|
529
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.
|
530
660
|
def index_internal(name)
|
531
661
|
field_descriptor = self.class.descriptor.lookup(name)
|
532
662
|
get_field field_descriptor unless field_descriptor.nil?
|
@@ -554,7 +684,7 @@ module Google
|
|
554
684
|
# one if omitted or nil.
|
555
685
|
def initialize(initial_value = nil, arena = nil, msg = nil)
|
556
686
|
@arena = arena || Google::Protobuf::FFI.create_arena
|
557
|
-
@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)
|
558
688
|
|
559
689
|
unless initial_value.nil?
|
560
690
|
raise ArgumentError.new "Expected hash arguments or message, not #{initial_value.class}" unless initial_value.respond_to? :each
|
@@ -575,9 +705,9 @@ module Google
|
|
575
705
|
|
576
706
|
next if value.nil?
|
577
707
|
if field_descriptor.map?
|
578
|
-
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)
|
579
709
|
elsif field_descriptor.repeated?
|
580
|
-
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)
|
581
711
|
else
|
582
712
|
index_assign_internal(value, name: key.to_s)
|
583
713
|
end
|
@@ -590,21 +720,20 @@ module Google
|
|
590
720
|
end
|
591
721
|
|
592
722
|
##
|
593
|
-
# Gets a field of this message identified by
|
723
|
+
# Gets a field of this message identified by FieldDescriptor.
|
594
724
|
#
|
595
|
-
# @param field [FieldDescriptor]
|
725
|
+
# @param field [FieldDescriptor] Field to retrieve.
|
726
|
+
# @param unwrap [Boolean](false) If true, unwraps wrappers.
|
596
727
|
def get_field(field, unwrap: false)
|
597
728
|
if field.map?
|
598
|
-
|
599
|
-
get_map_field(mutable_message_value[:map], field)
|
729
|
+
map_from_field_descriptor field
|
600
730
|
elsif field.repeated?
|
601
|
-
|
602
|
-
get_repeated_field(mutable_message_value[:array], field)
|
731
|
+
repeated_field_from_field_descriptor field
|
603
732
|
elsif field.sub_message?
|
604
733
|
return nil unless Google::Protobuf::FFI.get_message_has @msg, field
|
605
|
-
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message(field)
|
606
734
|
if unwrap
|
607
735
|
if field.has?(self)
|
736
|
+
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field
|
608
737
|
wrapper_message_value = Google::Protobuf::FFI.get_message_value @msg, field
|
609
738
|
fields = Google::Protobuf::FFI.field_count(sub_message_def)
|
610
739
|
raise "Sub message has #{fields} fields! Expected exactly 1." unless fields == 1
|
@@ -615,43 +744,37 @@ module Google
|
|
615
744
|
nil
|
616
745
|
end
|
617
746
|
else
|
618
|
-
|
619
|
-
sub_message = mutable_message[:msg]
|
620
|
-
Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
|
747
|
+
message_from_field_descriptor field
|
621
748
|
end
|
622
749
|
else
|
623
|
-
|
624
|
-
message_value = Google::Protobuf::FFI.get_message_value @msg, field
|
625
|
-
if c_type == :enum
|
626
|
-
convert_upb_to_ruby message_value, c_type, Google::Protobuf::FFI.get_subtype_as_enum(field)
|
627
|
-
else
|
628
|
-
convert_upb_to_ruby message_value, c_type
|
629
|
-
end
|
750
|
+
scalar_from_field_descriptor field
|
630
751
|
end
|
631
752
|
end
|
632
753
|
|
633
754
|
##
|
634
|
-
#
|
755
|
+
# Gets a RepeatedField from the ObjectCache or creates a new one.
|
756
|
+
# @param array [::FFI::Pointer] Pointer to the upb_Array
|
635
757
|
# @param field [Google::Protobuf::FieldDescriptor] Type of the repeated field
|
636
758
|
def get_repeated_field(array, field)
|
637
759
|
return nil if array.nil? or array.null?
|
638
760
|
repeated_field = OBJECT_CACHE.get(array.address)
|
639
761
|
if repeated_field.nil?
|
640
|
-
repeated_field = RepeatedField.send(:construct_for_field, field, @arena, array: array)
|
641
|
-
repeated_field.
|
762
|
+
repeated_field = RepeatedField.send(:construct_for_field, field, arena: @arena, array: array)
|
763
|
+
repeated_field.freeze if frozen?
|
642
764
|
end
|
643
765
|
repeated_field
|
644
766
|
end
|
645
767
|
|
646
768
|
##
|
647
|
-
#
|
769
|
+
# Gets a Map from the ObjectCache or creates a new one.
|
770
|
+
# @param map [::FFI::Pointer] Pointer to the upb_Map
|
648
771
|
# @param field [Google::Protobuf::FieldDescriptor] Type of the map field
|
649
772
|
def get_map_field(map, field)
|
650
773
|
return nil if map.nil? or map.null?
|
651
774
|
map_field = OBJECT_CACHE.get(map.address)
|
652
775
|
if map_field.nil?
|
653
|
-
map_field = Google::Protobuf::Map.send(:construct_for_field, field, @arena, map: map)
|
654
|
-
map_field.
|
776
|
+
map_field = Google::Protobuf::Map.send(:construct_for_field, field, arena: @arena, map: map)
|
777
|
+
map_field.freeze if frozen?
|
655
778
|
end
|
656
779
|
map_field
|
657
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
|
@@ -58,7 +58,9 @@ module Google
|
|
58
58
|
size_ptr = ::FFI::MemoryPointer.new(:size_t, 1)
|
59
59
|
temporary_arena = Google::Protobuf::FFI.create_arena
|
60
60
|
buffer = Google::Protobuf::FFI.oneof_options(self, size_ptr, temporary_arena)
|
61
|
-
Google::Protobuf::OneofOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze)
|
61
|
+
opts = Google::Protobuf::OneofOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze)
|
62
|
+
opts.clear_features()
|
63
|
+
opts.freeze
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
@@ -24,12 +24,14 @@ module Google
|
|
24
24
|
module Protobuf
|
25
25
|
class FFI
|
26
26
|
# Array
|
27
|
-
attach_function :append_array,
|
28
|
-
attach_function :get_msgval_at
|
29
|
-
attach_function :create_array,
|
30
|
-
attach_function :array_resize,
|
31
|
-
attach_function :array_set,
|
32
|
-
attach_function :array_size,
|
27
|
+
attach_function :append_array, :upb_Array_Append, [:Array, MessageValue.by_value, Internal::Arena], :bool
|
28
|
+
attach_function :get_msgval_at, :upb_Array_Get, [:Array, :size_t], MessageValue.by_value
|
29
|
+
attach_function :create_array, :upb_Array_New, [Internal::Arena, CType], :Array
|
30
|
+
attach_function :array_resize, :upb_Array_Resize, [:Array, :size_t, Internal::Arena], :bool
|
31
|
+
attach_function :array_set, :upb_Array_Set, [:Array, :size_t, MessageValue.by_value], :void
|
32
|
+
attach_function :array_size, :upb_Array_Size, [:Array], :size_t
|
33
|
+
attach_function :array_freeze, :upb_Array_Freeze, [:Array, MiniTable.by_ref], :void
|
34
|
+
attach_function :array_frozen?, :upb_Array_IsFrozen, [:Array], :bool
|
33
35
|
end
|
34
36
|
|
35
37
|
class RepeatedField
|
@@ -174,6 +176,38 @@ module Google
|
|
174
176
|
end
|
175
177
|
alias size :length
|
176
178
|
|
179
|
+
##
|
180
|
+
# Is this object frozen?
|
181
|
+
# Returns true if either this Ruby wrapper or the underlying
|
182
|
+
# representation are frozen. Freezes the wrapper if the underlying
|
183
|
+
# representation is already frozen but this wrapper isn't.
|
184
|
+
def frozen?
|
185
|
+
unless Google::Protobuf::FFI.array_frozen? array
|
186
|
+
raise RuntimeError.new "Ruby frozen RepeatedField with mutable representation" if super
|
187
|
+
return false
|
188
|
+
end
|
189
|
+
method(:freeze).super_method.call unless super
|
190
|
+
true
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Freezes the RepeatedField object. We have to intercept this so we can
|
195
|
+
# freeze the underlying representation, not just the Ruby wrapper. Returns
|
196
|
+
# self.
|
197
|
+
def freeze
|
198
|
+
if method(:frozen?).super_method.call
|
199
|
+
unless Google::Protobuf::FFI.array_frozen? array
|
200
|
+
raise RuntimeError.new "Underlying representation of repeated field still mutable despite frozen wrapper"
|
201
|
+
end
|
202
|
+
return self
|
203
|
+
end
|
204
|
+
unless Google::Protobuf::FFI.array_frozen? array
|
205
|
+
mini_table = (type == :message) ? Google::Protobuf::FFI.get_mini_table(@descriptor) : nil
|
206
|
+
Google::Protobuf::FFI.array_freeze(array, mini_table)
|
207
|
+
end
|
208
|
+
super
|
209
|
+
end
|
210
|
+
|
177
211
|
def dup
|
178
212
|
instance = self.class.allocate
|
179
213
|
instance.send(:initialize, type, descriptor: descriptor, arena: arena)
|
@@ -252,16 +286,6 @@ module Google
|
|
252
286
|
|
253
287
|
attr :name, :arena, :array, :type, :descriptor
|
254
288
|
|
255
|
-
def internal_deep_freeze
|
256
|
-
freeze
|
257
|
-
if type == :message
|
258
|
-
each do |element|
|
259
|
-
element.send :internal_deep_freeze
|
260
|
-
end
|
261
|
-
end
|
262
|
-
self
|
263
|
-
end
|
264
|
-
|
265
289
|
def internal_push(*elements)
|
266
290
|
elements.each do |element|
|
267
291
|
append_msg_val convert_ruby_to_upb(element, arena, type, descriptor)
|
@@ -346,10 +370,14 @@ module Google
|
|
346
370
|
OBJECT_CACHE.try_add(@array.address, self)
|
347
371
|
end
|
348
372
|
|
349
|
-
|
350
|
-
#
|
373
|
+
##
|
374
|
+
# Constructor that uses the type information from the given
|
375
|
+
# FieldDescriptor to configure the new RepeatedField instance.
|
376
|
+
# @param field [FieldDescriptor] Type information for the new RepeatedField
|
351
377
|
# @param arena [Arena] Owning message's arena
|
352
|
-
|
378
|
+
# @param values [Enumerable] Initial values
|
379
|
+
# @param array [::FFI::Pointer] Existing upb_Array
|
380
|
+
def self.construct_for_field(field, arena: nil, values: nil, array: nil)
|
353
381
|
instance = allocate
|
354
382
|
options = {initial_values: values, name: field.name, arena: arena, array: array}
|
355
383
|
if [:enum, :message].include? field.type
|