google-protobuf 3.25.5 → 4.28.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 +368 -29
- 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 +106 -114
- data/ext/google/protobuf_c/message.h +2 -6
- data/ext/google/protobuf_c/protobuf.c +30 -15
- 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 +13047 -10836
- data/ext/google/protobuf_c/ruby-upb.h +11114 -9028
- 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 +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 +3 -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 +183 -64
- 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 +24 -11
- 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
@@ -21,8 +21,12 @@ module Google
|
|
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)
|
@@ -301,53 +329,136 @@ module Google
|
|
301
329
|
|
302
330
|
include Google::Protobuf::Internal::Convert
|
303
331
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
332
|
+
##
|
333
|
+
# Checks ObjectCache for a sentinel empty frozen Map of the key and
|
334
|
+
# value types matching the field descriptor's MessageDef and returns
|
335
|
+
# the cache entry. If an entry is not found, one is created and added
|
336
|
+
# to the cache keyed by the MessageDef pointer first.
|
337
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
338
|
+
def empty_frozen_map(field_descriptor)
|
339
|
+
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor
|
340
|
+
frozen_map = OBJECT_CACHE.get sub_message_def
|
341
|
+
if frozen_map.nil?
|
342
|
+
frozen_map = Google::Protobuf::Map.send(:construct_for_field, field_descriptor)
|
343
|
+
OBJECT_CACHE.try_add(sub_message_def, frozen_map.freeze)
|
311
344
|
end
|
312
|
-
|
345
|
+
raise "Empty Frozen Map is not frozen" unless frozen_map.frozen?
|
346
|
+
frozen_map
|
347
|
+
end
|
348
|
+
|
349
|
+
##
|
350
|
+
# Returns a frozen Map instance for the given field. If the message
|
351
|
+
# already has a value for that field, it is used. If not, a sentinel
|
352
|
+
# (per FieldDescriptor) empty frozen Map is returned instead.
|
353
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
354
|
+
def frozen_map_from_field_descriptor(field_descriptor)
|
355
|
+
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
356
|
+
return empty_frozen_map field_descriptor if message_value[:map_val].null?
|
357
|
+
get_map_field(message_value[:map_val], field_descriptor).freeze
|
358
|
+
end
|
359
|
+
|
360
|
+
##
|
361
|
+
# Returns a Map instance for the given field. If the message is frozen
|
362
|
+
# the return value is also frozen. If not, a mutable instance is
|
363
|
+
# returned instead.
|
364
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
365
|
+
def map_from_field_descriptor(field_descriptor)
|
366
|
+
return frozen_map_from_field_descriptor field_descriptor if frozen?
|
367
|
+
mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
|
368
|
+
get_map_field(mutable_message_value[:map], field_descriptor)
|
369
|
+
end
|
370
|
+
|
371
|
+
##
|
372
|
+
# Checks ObjectCache for a sentinel empty frozen RepeatedField of the
|
373
|
+
# value type matching the field descriptor's MessageDef and returns
|
374
|
+
# the cache entry. If an entry is not found, one is created and added
|
375
|
+
# to the cache keyed by the MessageDef pointer first.
|
376
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
377
|
+
def empty_frozen_repeated_field(field_descriptor)
|
378
|
+
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor
|
379
|
+
frozen_repeated_field = OBJECT_CACHE.get sub_message_def
|
380
|
+
if frozen_repeated_field.nil?
|
381
|
+
frozen_repeated_field = Google::Protobuf::RepeatedField.send(:construct_for_field, field_descriptor)
|
382
|
+
OBJECT_CACHE.try_add(sub_message_def, frozen_repeated_field.freeze)
|
383
|
+
end
|
384
|
+
raise "Empty frozen RepeatedField is not frozen" unless frozen_repeated_field.frozen?
|
385
|
+
frozen_repeated_field
|
386
|
+
end
|
387
|
+
|
388
|
+
##
|
389
|
+
# Returns a frozen RepeatedField instance for the given field. If the
|
390
|
+
# message already has a value for that field, it is used. If not, a
|
391
|
+
# sentinel (per FieldDescriptor) empty frozen RepeatedField is
|
392
|
+
# returned instead.
|
393
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
394
|
+
def frozen_repeated_field_from_field_descriptor(field_descriptor)
|
395
|
+
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
396
|
+
return empty_frozen_repeated_field field_descriptor if message_value[:array_val].null?
|
397
|
+
get_repeated_field(message_value[:array_val], field_descriptor).freeze
|
313
398
|
end
|
314
399
|
|
400
|
+
##
|
401
|
+
# Returns a RepeatedField instance for the given field. If the message
|
402
|
+
# is frozen the return value is also frozen. If not, a mutable
|
403
|
+
# instance is returned instead.
|
404
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
405
|
+
def repeated_field_from_field_descriptor(field_descriptor)
|
406
|
+
return frozen_repeated_field_from_field_descriptor field_descriptor if frozen?
|
407
|
+
mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
|
408
|
+
get_repeated_field(mutable_message_value[:array], field_descriptor)
|
409
|
+
end
|
410
|
+
|
411
|
+
##
|
412
|
+
# Returns a Message instance for the given field. If the message
|
413
|
+
# is frozen nil is always returned. Otherwise, a mutable instance is
|
414
|
+
# returned instead.
|
415
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
416
|
+
def message_from_field_descriptor(field_descriptor)
|
417
|
+
return nil if frozen?
|
418
|
+
return nil unless Google::Protobuf::FFI.get_message_has @msg, field_descriptor
|
419
|
+
mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
|
420
|
+
sub_message = mutable_message[:msg]
|
421
|
+
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor
|
422
|
+
Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
|
423
|
+
end
|
424
|
+
|
425
|
+
##
|
426
|
+
# Returns a scalar value for the given field. If the message
|
427
|
+
# is frozen the return value is also frozen.
|
428
|
+
# @param field_descriptor [FieldDescriptor] Field to retrieve.
|
429
|
+
def scalar_from_field_descriptor(field_descriptor)
|
430
|
+
c_type = field_descriptor.send(:c_type)
|
431
|
+
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
432
|
+
msg_or_enum_def = c_type == :enum ? Google::Protobuf::FFI.get_subtype_as_enum(field_descriptor) : nil
|
433
|
+
return_value = convert_upb_to_ruby message_value, c_type, msg_or_enum_def
|
434
|
+
frozen? ? return_value.freeze : return_value
|
435
|
+
end
|
436
|
+
|
437
|
+
##
|
438
|
+
# Dynamically define accessors methods for every field of @descriptor.
|
439
|
+
# Methods with names that conflict with existing methods are skipped.
|
315
440
|
def self.setup_accessors!
|
316
441
|
@descriptor.each do |field_descriptor|
|
317
442
|
field_name = field_descriptor.name
|
318
443
|
unless instance_methods(true).include?(field_name.to_sym)
|
319
|
-
#
|
320
|
-
#
|
444
|
+
# Dispatching to either index_internal or get_field is logically
|
445
|
+
# correct, but slightly slower due to having to perform extra
|
446
|
+
# lookups on each invocation rather than doing it once here.
|
321
447
|
if field_descriptor.map?
|
322
448
|
define_method(field_name) do
|
323
|
-
|
324
|
-
get_map_field(mutable_message_value[:map], field_descriptor)
|
449
|
+
map_from_field_descriptor field_descriptor
|
325
450
|
end
|
326
451
|
elsif field_descriptor.repeated?
|
327
452
|
define_method(field_name) do
|
328
|
-
|
329
|
-
get_repeated_field(mutable_message_value[:array], field_descriptor)
|
453
|
+
repeated_field_from_field_descriptor field_descriptor
|
330
454
|
end
|
331
455
|
elsif field_descriptor.sub_message?
|
332
456
|
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)
|
457
|
+
message_from_field_descriptor field_descriptor
|
338
458
|
end
|
339
459
|
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
|
460
|
+
define_method(field_name) do
|
461
|
+
scalar_from_field_descriptor field_descriptor
|
351
462
|
end
|
352
463
|
end
|
353
464
|
define_method("#{field_name}=") do |value|
|
@@ -357,14 +468,16 @@ module Google
|
|
357
468
|
clear_internal(field_descriptor)
|
358
469
|
end
|
359
470
|
if field_descriptor.type == :enum
|
360
|
-
|
361
|
-
|
471
|
+
if field_descriptor.repeated?
|
472
|
+
define_method("#{field_name}_const") do
|
362
473
|
return_value = []
|
363
|
-
|
474
|
+
repeated_field_from_field_descriptor(field_descriptor).send(:each_msg_val) do |msg_val|
|
364
475
|
return_value << msg_val[:int32_val]
|
365
476
|
end
|
366
477
|
return_value
|
367
|
-
|
478
|
+
end
|
479
|
+
else
|
480
|
+
define_method("#{field_name}_const") do
|
368
481
|
message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
|
369
482
|
message_value[:int32_val]
|
370
483
|
end
|
@@ -391,12 +504,21 @@ module Google
|
|
391
504
|
end
|
392
505
|
end
|
393
506
|
|
507
|
+
##
|
508
|
+
# Dynamically define accessors methods for every OneOf field of
|
509
|
+
# @descriptor.
|
394
510
|
def self.setup_oneof_accessors!
|
395
511
|
@oneof_field_names = []
|
396
512
|
@descriptor.each_oneof do |oneof_descriptor|
|
397
513
|
self.add_oneof_accessors_for! oneof_descriptor
|
398
514
|
end
|
399
515
|
end
|
516
|
+
|
517
|
+
##
|
518
|
+
# Dynamically define accessors methods for the given OneOf field.
|
519
|
+
# Methods with names that conflict with existing methods are skipped.
|
520
|
+
# @param oneof_descriptor [OneofDescriptor] Field to create accessors
|
521
|
+
# for.
|
400
522
|
def self.add_oneof_accessors_for!(oneof_descriptor)
|
401
523
|
field_name = oneof_descriptor.name.to_sym
|
402
524
|
@oneof_field_names << field_name
|
@@ -527,6 +649,10 @@ module Google
|
|
527
649
|
Google::Protobuf::FFI.clear_message_field(@msg, field_def)
|
528
650
|
end
|
529
651
|
|
652
|
+
# Accessor for field by name. Does not delegate to methods setup by
|
653
|
+
# self.setup_accessors! in order to avoid conflicts with bad field
|
654
|
+
# names e.g. `dup` or `class` which are perfectly valid for proto
|
655
|
+
# fields.
|
530
656
|
def index_internal(name)
|
531
657
|
field_descriptor = self.class.descriptor.lookup(name)
|
532
658
|
get_field field_descriptor unless field_descriptor.nil?
|
@@ -554,7 +680,7 @@ module Google
|
|
554
680
|
# one if omitted or nil.
|
555
681
|
def initialize(initial_value = nil, arena = nil, msg = nil)
|
556
682
|
@arena = arena || Google::Protobuf::FFI.create_arena
|
557
|
-
@msg = msg || Google::Protobuf::FFI.new_message_from_def(self.class.descriptor, @arena)
|
683
|
+
@msg = msg || Google::Protobuf::FFI.new_message_from_def(Google::Protobuf::FFI.get_mini_table(self.class.descriptor), @arena)
|
558
684
|
|
559
685
|
unless initial_value.nil?
|
560
686
|
raise ArgumentError.new "Expected hash arguments or message, not #{initial_value.class}" unless initial_value.respond_to? :each
|
@@ -575,9 +701,9 @@ module Google
|
|
575
701
|
|
576
702
|
next if value.nil?
|
577
703
|
if field_descriptor.map?
|
578
|
-
index_assign_internal(Google::Protobuf::Map.send(:construct_for_field, field_descriptor, @arena, value: value), name: key.to_s)
|
704
|
+
index_assign_internal(Google::Protobuf::Map.send(:construct_for_field, field_descriptor, arena: @arena, value: value), name: key.to_s)
|
579
705
|
elsif field_descriptor.repeated?
|
580
|
-
index_assign_internal(RepeatedField.send(:construct_for_field, field_descriptor, @arena, values: value), name: key.to_s)
|
706
|
+
index_assign_internal(RepeatedField.send(:construct_for_field, field_descriptor, arena: @arena, values: value), name: key.to_s)
|
581
707
|
else
|
582
708
|
index_assign_internal(value, name: key.to_s)
|
583
709
|
end
|
@@ -590,21 +716,20 @@ module Google
|
|
590
716
|
end
|
591
717
|
|
592
718
|
##
|
593
|
-
# Gets a field of this message identified by
|
719
|
+
# Gets a field of this message identified by FieldDescriptor.
|
594
720
|
#
|
595
|
-
# @param field [FieldDescriptor]
|
721
|
+
# @param field [FieldDescriptor] Field to retrieve.
|
722
|
+
# @param unwrap [Boolean](false) If true, unwraps wrappers.
|
596
723
|
def get_field(field, unwrap: false)
|
597
724
|
if field.map?
|
598
|
-
|
599
|
-
get_map_field(mutable_message_value[:map], field)
|
725
|
+
map_from_field_descriptor field
|
600
726
|
elsif field.repeated?
|
601
|
-
|
602
|
-
get_repeated_field(mutable_message_value[:array], field)
|
727
|
+
repeated_field_from_field_descriptor field
|
603
728
|
elsif field.sub_message?
|
604
729
|
return nil unless Google::Protobuf::FFI.get_message_has @msg, field
|
605
|
-
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message(field)
|
606
730
|
if unwrap
|
607
731
|
if field.has?(self)
|
732
|
+
sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field
|
608
733
|
wrapper_message_value = Google::Protobuf::FFI.get_message_value @msg, field
|
609
734
|
fields = Google::Protobuf::FFI.field_count(sub_message_def)
|
610
735
|
raise "Sub message has #{fields} fields! Expected exactly 1." unless fields == 1
|
@@ -615,43 +740,37 @@ module Google
|
|
615
740
|
nil
|
616
741
|
end
|
617
742
|
else
|
618
|
-
|
619
|
-
sub_message = mutable_message[:msg]
|
620
|
-
Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
|
743
|
+
message_from_field_descriptor field
|
621
744
|
end
|
622
745
|
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
|
746
|
+
scalar_from_field_descriptor field
|
630
747
|
end
|
631
748
|
end
|
632
749
|
|
633
750
|
##
|
634
|
-
#
|
751
|
+
# Gets a RepeatedField from the ObjectCache or creates a new one.
|
752
|
+
# @param array [::FFI::Pointer] Pointer to the upb_Array
|
635
753
|
# @param field [Google::Protobuf::FieldDescriptor] Type of the repeated field
|
636
754
|
def get_repeated_field(array, field)
|
637
755
|
return nil if array.nil? or array.null?
|
638
756
|
repeated_field = OBJECT_CACHE.get(array.address)
|
639
757
|
if repeated_field.nil?
|
640
|
-
repeated_field = RepeatedField.send(:construct_for_field, field, @arena, array: array)
|
641
|
-
repeated_field.
|
758
|
+
repeated_field = RepeatedField.send(:construct_for_field, field, arena: @arena, array: array)
|
759
|
+
repeated_field.freeze if frozen?
|
642
760
|
end
|
643
761
|
repeated_field
|
644
762
|
end
|
645
763
|
|
646
764
|
##
|
647
|
-
#
|
765
|
+
# Gets a Map from the ObjectCache or creates a new one.
|
766
|
+
# @param map [::FFI::Pointer] Pointer to the upb_Map
|
648
767
|
# @param field [Google::Protobuf::FieldDescriptor] Type of the map field
|
649
768
|
def get_map_field(map, field)
|
650
769
|
return nil if map.nil? or map.null?
|
651
770
|
map_field = OBJECT_CACHE.get(map.address)
|
652
771
|
if map_field.nil?
|
653
|
-
map_field = Google::Protobuf::Map.send(:construct_for_field, field, @arena, map: map)
|
654
|
-
map_field.
|
772
|
+
map_field = Google::Protobuf::Map.send(:construct_for_field, field, arena: @arena, map: map)
|
773
|
+
map_field.freeze if frozen?
|
655
774
|
end
|
656
775
|
map_field
|
657
776
|
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
|