google-protobuf 4.27.3 → 4.30.0

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +32 -14
  3. data/ext/google/protobuf_c/defs.c +162 -4
  4. data/ext/google/protobuf_c/extconf.rb +12 -0
  5. data/ext/google/protobuf_c/glue.c +63 -0
  6. data/ext/google/protobuf_c/map.c +72 -20
  7. data/ext/google/protobuf_c/map.h +6 -2
  8. data/ext/google/protobuf_c/message.c +88 -41
  9. data/ext/google/protobuf_c/message.h +1 -1
  10. data/ext/google/protobuf_c/protobuf.c +13 -12
  11. data/ext/google/protobuf_c/protobuf.h +3 -7
  12. data/ext/google/protobuf_c/repeated_field.c +61 -17
  13. data/ext/google/protobuf_c/repeated_field.h +5 -1
  14. data/ext/google/protobuf_c/ruby-upb.c +6965 -5525
  15. data/ext/google/protobuf_c/ruby-upb.h +5056 -3492
  16. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +15 -275
  17. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_neon.inc +117 -0
  18. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_sse.inc +272 -0
  19. data/lib/google/protobuf/descriptor_pb.rb +2 -1
  20. data/lib/google/protobuf/ffi/descriptor.rb +11 -2
  21. data/lib/google/protobuf/ffi/enum_descriptor.rb +10 -0
  22. data/lib/google/protobuf/ffi/ffi.rb +4 -0
  23. data/lib/google/protobuf/ffi/field_descriptor.rb +10 -0
  24. data/lib/google/protobuf/ffi/file_descriptor.rb +10 -0
  25. data/lib/google/protobuf/ffi/internal/arena.rb +0 -6
  26. data/lib/google/protobuf/ffi/internal/convert.rb +9 -6
  27. data/lib/google/protobuf/ffi/map.rb +45 -21
  28. data/lib/google/protobuf/ffi/message.rb +187 -63
  29. data/lib/google/protobuf/ffi/method_descriptor.rb +11 -1
  30. data/lib/google/protobuf/ffi/oneof_descriptor.rb +10 -0
  31. data/lib/google/protobuf/ffi/repeated_field.rb +42 -16
  32. data/lib/google/protobuf/ffi/service_descriptor.rb +11 -1
  33. data/lib/google/protobuf_ffi.rb +2 -1
  34. metadata +6 -4
@@ -17,13 +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 :json_decode_message, :upb_JsonDecode, [:binary_string, :size_t, :Message, Descriptor, :DefPool, :int, Internal::Arena, Status.by_ref], :bool
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, :upb_Message_WhichOneof, [:Message, OneofDescriptor], FieldDescriptor
25
- attach_function :message_discard_unknown, :upb_Message_DiscardUnknown, [:Message, Descriptor, :int], :bool
24
+ attach_function :get_message_which_oneof, :upb_Message_WhichOneofByDef, [:Message, OneofDescriptor], FieldDescriptor
25
+ attach_function :message_discard_unknown, :upb_Message_DiscardUnknown, [:Message, Descriptor, :DefPool, :int], :bool
26
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
+
27
30
  # MessageValue
28
31
  attach_function :message_value_equal, :shared_Msgval_IsEqual, [MessageValue.by_value, MessageValue.by_value, CType, Descriptor], :bool
29
32
  attach_function :message_value_hash, :shared_Msgval_GetHash, [MessageValue.by_value, CType, Descriptor, :uint64_t], :uint64_t
@@ -58,18 +61,35 @@ module Google
58
61
  instance
59
62
  end
60
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.
61
81
  def freeze
62
- return self if frozen?
63
- super
64
- @arena.pin self
65
- self.class.descriptor.each do |field_descriptor|
66
- next if field_descriptor.has_presence? && !Google::Protobuf::FFI.get_message_has(@msg, field_descriptor)
67
- if field_descriptor.map? or field_descriptor.repeated? or field_descriptor.sub_message?
68
- get_field(field_descriptor).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"
69
85
  end
86
+ return self
70
87
  end
71
- self
72
- 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
91
+ super
92
+ end
73
93
 
74
94
  def dup
75
95
  duplicate = self.class.private_constructor(@arena)
@@ -250,7 +270,9 @@ module Google
250
270
  message = new
251
271
  pool_def = message.class.descriptor.instance_variable_get(:@descriptor_pool).descriptor_pool
252
272
  status = Google::Protobuf::FFI::Status.new
253
- unless Google::Protobuf::FFI.json_decode_message(data, data.bytesize, message.instance_variable_get(:@msg), message.class.descriptor, pool_def, decoding_options, message.instance_variable_get(:@arena), status)
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_Error
254
276
  raise ParseError.new "Error occurred during parsing: #{Google::Protobuf::FFI.error_message(status)}"
255
277
  end
256
278
  message
@@ -309,42 +331,136 @@ module Google
309
331
 
310
332
  include Google::Protobuf::Internal::Convert
311
333
 
334
+ ##
335
+ # Checks ObjectCache for a sentinel empty frozen Map of the key and
336
+ # value types matching the field descriptor's MessageDef and returns
337
+ # the cache entry. If an entry is not found, one is created and added
338
+ # to the cache keyed by the MessageDef pointer first.
339
+ # @param field_descriptor [FieldDescriptor] Field to retrieve.
340
+ def empty_frozen_map(field_descriptor)
341
+ sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor
342
+ frozen_map = OBJECT_CACHE.get sub_message_def
343
+ if frozen_map.nil?
344
+ frozen_map = Google::Protobuf::Map.send(:construct_for_field, field_descriptor)
345
+ OBJECT_CACHE.try_add(sub_message_def, frozen_map.freeze)
346
+ end
347
+ raise "Empty Frozen Map is not frozen" unless frozen_map.frozen?
348
+ frozen_map
349
+ end
350
+
351
+ ##
352
+ # Returns a frozen Map instance for the given field. If the message
353
+ # already has a value for that field, it is used. If not, a sentinel
354
+ # (per FieldDescriptor) empty frozen Map is returned instead.
355
+ # @param field_descriptor [FieldDescriptor] Field to retrieve.
356
+ def frozen_map_from_field_descriptor(field_descriptor)
357
+ message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
358
+ return empty_frozen_map field_descriptor if message_value[:map_val].null?
359
+ get_map_field(message_value[:map_val], field_descriptor).freeze
360
+ end
361
+
362
+ ##
363
+ # Returns a Map instance for the given field. If the message is frozen
364
+ # the return value is also frozen. If not, a mutable instance is
365
+ # returned instead.
366
+ # @param field_descriptor [FieldDescriptor] Field to retrieve.
367
+ def map_from_field_descriptor(field_descriptor)
368
+ return frozen_map_from_field_descriptor field_descriptor if frozen?
369
+ mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
370
+ get_map_field(mutable_message_value[:map], field_descriptor)
371
+ end
372
+
373
+ ##
374
+ # Checks ObjectCache for a sentinel empty frozen RepeatedField of the
375
+ # value type matching the field descriptor's MessageDef and returns
376
+ # the cache entry. If an entry is not found, one is created and added
377
+ # to the cache keyed by the MessageDef pointer first.
378
+ # @param field_descriptor [FieldDescriptor] Field to retrieve.
379
+ def empty_frozen_repeated_field(field_descriptor)
380
+ sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor
381
+ frozen_repeated_field = OBJECT_CACHE.get sub_message_def
382
+ if frozen_repeated_field.nil?
383
+ frozen_repeated_field = Google::Protobuf::RepeatedField.send(:construct_for_field, field_descriptor)
384
+ OBJECT_CACHE.try_add(sub_message_def, frozen_repeated_field.freeze)
385
+ end
386
+ raise "Empty frozen RepeatedField is not frozen" unless frozen_repeated_field.frozen?
387
+ frozen_repeated_field
388
+ end
389
+
390
+ ##
391
+ # Returns a frozen RepeatedField instance for the given field. If the
392
+ # message already has a value for that field, it is used. If not, a
393
+ # sentinel (per FieldDescriptor) empty frozen RepeatedField is
394
+ # returned instead.
395
+ # @param field_descriptor [FieldDescriptor] Field to retrieve.
396
+ def frozen_repeated_field_from_field_descriptor(field_descriptor)
397
+ message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
398
+ return empty_frozen_repeated_field field_descriptor if message_value[:array_val].null?
399
+ get_repeated_field(message_value[:array_val], field_descriptor).freeze
400
+ end
401
+
402
+ ##
403
+ # Returns a RepeatedField instance for the given field. If the message
404
+ # is frozen the return value is also frozen. If not, a mutable
405
+ # instance is returned instead.
406
+ # @param field_descriptor [FieldDescriptor] Field to retrieve.
407
+ def repeated_field_from_field_descriptor(field_descriptor)
408
+ return frozen_repeated_field_from_field_descriptor field_descriptor if frozen?
409
+ mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
410
+ get_repeated_field(mutable_message_value[:array], field_descriptor)
411
+ end
412
+
413
+ ##
414
+ # Returns a Message instance for the given field. If the message
415
+ # is frozen nil is always returned. Otherwise, a mutable instance is
416
+ # returned instead.
417
+ # @param field_descriptor [FieldDescriptor] Field to retrieve.
418
+ def message_from_field_descriptor(field_descriptor)
419
+ return nil if frozen?
420
+ return nil unless Google::Protobuf::FFI.get_message_has @msg, field_descriptor
421
+ mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
422
+ sub_message = mutable_message[:msg]
423
+ sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor
424
+ Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
425
+ end
426
+
427
+ ##
428
+ # Returns a scalar value for the given field. If the message
429
+ # is frozen the return value is also frozen.
430
+ # @param field_descriptor [FieldDescriptor] Field to retrieve.
431
+ def scalar_from_field_descriptor(field_descriptor)
432
+ c_type = field_descriptor.send(:c_type)
433
+ message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
434
+ msg_or_enum_def = c_type == :enum ? Google::Protobuf::FFI.get_subtype_as_enum(field_descriptor) : nil
435
+ return_value = convert_upb_to_ruby message_value, c_type, msg_or_enum_def
436
+ frozen? ? return_value.freeze : return_value
437
+ end
438
+
439
+ ##
440
+ # Dynamically define accessors methods for every field of @descriptor.
441
+ # Methods with names that conflict with existing methods are skipped.
312
442
  def self.setup_accessors!
313
443
  @descriptor.each do |field_descriptor|
314
444
  field_name = field_descriptor.name
315
445
  unless instance_methods(true).include?(field_name.to_sym)
316
- #TODO - at a high level, dispatching to either
317
- # index_internal or get_field would be logically correct, but slightly slower.
446
+ # Dispatching to either index_internal or get_field is logically
447
+ # correct, but slightly slower due to having to perform extra
448
+ # lookups on each invocation rather than doing it once here.
318
449
  if field_descriptor.map?
319
450
  define_method(field_name) do
320
- mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
321
- get_map_field(mutable_message_value[:map], field_descriptor)
451
+ map_from_field_descriptor field_descriptor
322
452
  end
323
453
  elsif field_descriptor.repeated?
324
454
  define_method(field_name) do
325
- mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
326
- get_repeated_field(mutable_message_value[:array], field_descriptor)
455
+ repeated_field_from_field_descriptor field_descriptor
327
456
  end
328
457
  elsif field_descriptor.sub_message?
329
458
  define_method(field_name) do
330
- return nil unless Google::Protobuf::FFI.get_message_has @msg, field_descriptor
331
- mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena
332
- sub_message = mutable_message[:msg]
333
- sub_message_def = Google::Protobuf::FFI.get_subtype_as_message(field_descriptor)
334
- Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
459
+ message_from_field_descriptor field_descriptor
335
460
  end
336
461
  else
337
- c_type = field_descriptor.send(:c_type)
338
- if c_type == :enum
339
- define_method(field_name) do
340
- message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
341
- convert_upb_to_ruby message_value, c_type, Google::Protobuf::FFI.get_subtype_as_enum(field_descriptor)
342
- end
343
- else
344
- define_method(field_name) do
345
- message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
346
- convert_upb_to_ruby message_value, c_type
347
- end
462
+ define_method(field_name) do
463
+ scalar_from_field_descriptor field_descriptor
348
464
  end
349
465
  end
350
466
  define_method("#{field_name}=") do |value|
@@ -354,14 +470,16 @@ module Google
354
470
  clear_internal(field_descriptor)
355
471
  end
356
472
  if field_descriptor.type == :enum
357
- define_method("#{field_name}_const") do
358
- if field_descriptor.repeated?
473
+ if field_descriptor.repeated?
474
+ define_method("#{field_name}_const") do
359
475
  return_value = []
360
- get_field(field_descriptor).send(:each_msg_val) do |msg_val|
476
+ repeated_field_from_field_descriptor(field_descriptor).send(:each_msg_val) do |msg_val|
361
477
  return_value << msg_val[:int32_val]
362
478
  end
363
479
  return_value
364
- else
480
+ end
481
+ else
482
+ define_method("#{field_name}_const") do
365
483
  message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor
366
484
  message_value[:int32_val]
367
485
  end
@@ -388,12 +506,21 @@ module Google
388
506
  end
389
507
  end
390
508
 
509
+ ##
510
+ # Dynamically define accessors methods for every OneOf field of
511
+ # @descriptor.
391
512
  def self.setup_oneof_accessors!
392
513
  @oneof_field_names = []
393
514
  @descriptor.each_oneof do |oneof_descriptor|
394
515
  self.add_oneof_accessors_for! oneof_descriptor
395
516
  end
396
517
  end
518
+
519
+ ##
520
+ # Dynamically define accessors methods for the given OneOf field.
521
+ # Methods with names that conflict with existing methods are skipped.
522
+ # @param oneof_descriptor [OneofDescriptor] Field to create accessors
523
+ # for.
397
524
  def self.add_oneof_accessors_for!(oneof_descriptor)
398
525
  field_name = oneof_descriptor.name.to_sym
399
526
  @oneof_field_names << field_name
@@ -524,6 +651,10 @@ module Google
524
651
  Google::Protobuf::FFI.clear_message_field(@msg, field_def)
525
652
  end
526
653
 
654
+ # Accessor for field by name. Does not delegate to methods setup by
655
+ # self.setup_accessors! in order to avoid conflicts with bad field
656
+ # names e.g. `dup` or `class` which are perfectly valid for proto
657
+ # fields.
527
658
  def index_internal(name)
528
659
  field_descriptor = self.class.descriptor.lookup(name)
529
660
  get_field field_descriptor unless field_descriptor.nil?
@@ -551,7 +682,7 @@ module Google
551
682
  # one if omitted or nil.
552
683
  def initialize(initial_value = nil, arena = nil, msg = nil)
553
684
  @arena = arena || Google::Protobuf::FFI.create_arena
554
- @msg = msg || Google::Protobuf::FFI.new_message_from_def(self.class.descriptor, @arena)
685
+ @msg = msg || Google::Protobuf::FFI.new_message_from_def(Google::Protobuf::FFI.get_mini_table(self.class.descriptor), @arena)
555
686
 
556
687
  unless initial_value.nil?
557
688
  raise ArgumentError.new "Expected hash arguments or message, not #{initial_value.class}" unless initial_value.respond_to? :each
@@ -572,9 +703,9 @@ module Google
572
703
 
573
704
  next if value.nil?
574
705
  if field_descriptor.map?
575
- index_assign_internal(Google::Protobuf::Map.send(:construct_for_field, field_descriptor, @arena, value: value), name: key.to_s)
706
+ index_assign_internal(Google::Protobuf::Map.send(:construct_for_field, field_descriptor, arena: @arena, value: value), name: key.to_s)
576
707
  elsif field_descriptor.repeated?
577
- index_assign_internal(RepeatedField.send(:construct_for_field, field_descriptor, @arena, values: value), name: key.to_s)
708
+ index_assign_internal(RepeatedField.send(:construct_for_field, field_descriptor, arena: @arena, values: value), name: key.to_s)
578
709
  else
579
710
  index_assign_internal(value, name: key.to_s)
580
711
  end
@@ -587,21 +718,20 @@ module Google
587
718
  end
588
719
 
589
720
  ##
590
- # Gets a field of this message identified by the argument definition.
721
+ # Gets a field of this message identified by FieldDescriptor.
591
722
  #
592
- # @param field [FieldDescriptor] Descriptor of the field to get
723
+ # @param field [FieldDescriptor] Field to retrieve.
724
+ # @param unwrap [Boolean](false) If true, unwraps wrappers.
593
725
  def get_field(field, unwrap: false)
594
726
  if field.map?
595
- mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field, @arena
596
- get_map_field(mutable_message_value[:map], field)
727
+ map_from_field_descriptor field
597
728
  elsif field.repeated?
598
- mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field, @arena
599
- get_repeated_field(mutable_message_value[:array], field)
729
+ repeated_field_from_field_descriptor field
600
730
  elsif field.sub_message?
601
731
  return nil unless Google::Protobuf::FFI.get_message_has @msg, field
602
- sub_message_def = Google::Protobuf::FFI.get_subtype_as_message(field)
603
732
  if unwrap
604
733
  if field.has?(self)
734
+ sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field
605
735
  wrapper_message_value = Google::Protobuf::FFI.get_message_value @msg, field
606
736
  fields = Google::Protobuf::FFI.field_count(sub_message_def)
607
737
  raise "Sub message has #{fields} fields! Expected exactly 1." unless fields == 1
@@ -612,42 +742,36 @@ module Google
612
742
  nil
613
743
  end
614
744
  else
615
- mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field, @arena
616
- sub_message = mutable_message[:msg]
617
- Descriptor.send(:get_message, sub_message, sub_message_def, @arena)
745
+ message_from_field_descriptor field
618
746
  end
619
747
  else
620
- c_type = field.send(:c_type)
621
- message_value = Google::Protobuf::FFI.get_message_value @msg, field
622
- if c_type == :enum
623
- convert_upb_to_ruby message_value, c_type, Google::Protobuf::FFI.get_subtype_as_enum(field)
624
- else
625
- convert_upb_to_ruby message_value, c_type
626
- end
748
+ scalar_from_field_descriptor field
627
749
  end
628
750
  end
629
751
 
630
752
  ##
631
- # @param array [::FFI::Pointer] Pointer to the Array
753
+ # Gets a RepeatedField from the ObjectCache or creates a new one.
754
+ # @param array [::FFI::Pointer] Pointer to the upb_Array
632
755
  # @param field [Google::Protobuf::FieldDescriptor] Type of the repeated field
633
756
  def get_repeated_field(array, field)
634
757
  return nil if array.nil? or array.null?
635
758
  repeated_field = OBJECT_CACHE.get(array.address)
636
759
  if repeated_field.nil?
637
- repeated_field = RepeatedField.send(:construct_for_field, field, @arena, array: array)
760
+ repeated_field = RepeatedField.send(:construct_for_field, field, arena: @arena, array: array)
638
761
  repeated_field.freeze if frozen?
639
762
  end
640
763
  repeated_field
641
764
  end
642
765
 
643
766
  ##
644
- # @param map [::FFI::Pointer] Pointer to the Map
767
+ # Gets a Map from the ObjectCache or creates a new one.
768
+ # @param map [::FFI::Pointer] Pointer to the upb_Map
645
769
  # @param field [Google::Protobuf::FieldDescriptor] Type of the map field
646
770
  def get_map_field(map, field)
647
771
  return nil if map.nil? or map.null?
648
772
  map_field = OBJECT_CACHE.get(map.address)
649
773
  if map_field.nil?
650
- map_field = Google::Protobuf::Map.send(:construct_for_field, field, @arena, map: map)
774
+ map_field = Google::Protobuf::Map.send(:construct_for_field, field, arena: @arena, map: map)
651
775
  map_field.freeze if frozen?
652
776
  end
653
777
  map_field
@@ -7,7 +7,7 @@
7
7
 
8
8
  module Google
9
9
  module Protobuf
10
- class MethodDescriptor
10
+ class MethodDescriptor
11
11
  attr :method_def, :descriptor_pool
12
12
 
13
13
  include Google::Protobuf::Internal::Convert
@@ -81,6 +81,15 @@ module Google
81
81
  @server_streaming ||= Google::Protobuf::FFI.method_server_streaming(self)
82
82
  end
83
83
 
84
+ def to_proto
85
+ @to_proto ||= begin
86
+ size_ptr = ::FFI::MemoryPointer.new(:size_t, 1)
87
+ temporary_arena = Google::Protobuf::FFI.create_arena
88
+ buffer = Google::Protobuf::FFI.method_to_proto(self, size_ptr, temporary_arena)
89
+ Google::Protobuf::MethodDescriptorProto.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze)
90
+ end
91
+ end
92
+
84
93
  private
85
94
 
86
95
  def initialize(method_def, descriptor_pool)
@@ -108,6 +117,7 @@ module Google
108
117
  attach_function :method_output_type, :upb_MethodDef_OutputType, [MethodDescriptor], Descriptor
109
118
  attach_function :method_client_streaming, :upb_MethodDef_ClientStreaming, [MethodDescriptor], :bool
110
119
  attach_function :method_server_streaming, :upb_MethodDef_ServerStreaming, [MethodDescriptor], :bool
120
+ attach_function :method_to_proto, :MethodDescriptor_serialized_to_proto, [MethodDescriptor, :pointer, Internal::Arena], :pointer
111
121
  end
112
122
  end
113
123
  end
@@ -64,6 +64,15 @@ module Google
64
64
  end
65
65
  end
66
66
 
67
+ def to_proto
68
+ @to_proto ||= begin
69
+ size_ptr = ::FFI::MemoryPointer.new(:size_t, 1)
70
+ temporary_arena = Google::Protobuf::FFI.create_arena
71
+ buffer = Google::Protobuf::FFI.oneof_to_proto(self, size_ptr, temporary_arena)
72
+ Google::Protobuf::OneofDescriptorProto.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze)
73
+ end
74
+ end
75
+
67
76
  private
68
77
 
69
78
  def initialize(oneof_def, descriptor_pool)
@@ -89,6 +98,7 @@ module Google
89
98
  attach_function :get_oneof_field_by_index, :upb_OneofDef_Field, [OneofDescriptor, :int], FieldDescriptor
90
99
  attach_function :get_oneof_containing_type,:upb_OneofDef_ContainingType, [:pointer], Descriptor
91
100
  attach_function :oneof_options, :OneOfDescriptor_serialized_options, [OneofDescriptor, :pointer, Internal::Arena], :pointer
101
+ attach_function :oneof_to_proto, :OneOfDescriptor_serialized_to_proto, [OneofDescriptor, :pointer, Internal::Arena], :pointer
92
102
 
93
103
  # FieldDescriptor
94
104
  attach_function :real_containing_oneof, :upb_FieldDef_RealContainingOneof, [FieldDescriptor], OneofDescriptor
@@ -24,12 +24,14 @@ module Google
24
24
  module Protobuf
25
25
  class FFI
26
26
  # Array
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
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,16 +176,36 @@ 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.
177
197
  def freeze
178
- return self if frozen?
179
- super
180
- @arena.pin self
181
- if type == :message
182
- each do |element|
183
- element.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"
184
201
  end
202
+ return self
185
203
  end
186
- self
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
187
209
  end
188
210
 
189
211
  def dup
@@ -348,10 +370,14 @@ module Google
348
370
  OBJECT_CACHE.try_add(@array.address, self)
349
371
  end
350
372
 
351
- # @param field [FieldDescriptor] Descriptor of the field where the RepeatedField will be assigned
352
- # @param values [Enumerable] Initial values; may be nil or empty
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
353
377
  # @param arena [Arena] Owning message's arena
354
- def self.construct_for_field(field, arena, values: nil, array: nil)
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)
355
381
  instance = allocate
356
382
  options = {initial_values: values, name: field.name, arena: arena, array: array}
357
383
  if [:enum, :message].include? field.type
@@ -77,10 +77,19 @@ module Google
77
77
  end
78
78
  end
79
79
 
80
+ def to_proto
81
+ @to_proto ||= begin
82
+ size_ptr = ::FFI::MemoryPointer.new(:size_t, 1)
83
+ temporary_arena = Google::Protobuf::FFI.create_arena
84
+ buffer = Google::Protobuf::FFI.service_to_proto(self, size_ptr, temporary_arena)
85
+ Google::Protobuf::ServiceDescriptorProto.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze)
86
+ end
87
+ end
88
+
80
89
  private
81
90
 
82
91
  def initialize(service_def, descriptor_pool)
83
- @service_def = service_def
92
+ @service_def = service_def
84
93
  @descriptor_pool = descriptor_pool
85
94
  end
86
95
 
@@ -102,6 +111,7 @@ module Google
102
111
  attach_function :method_count, :upb_ServiceDef_MethodCount, [ServiceDescriptor], :int
103
112
  attach_function :get_method_by_index, :upb_ServiceDef_Method, [ServiceDescriptor, :int], MethodDescriptor
104
113
  attach_function :service_options, :ServiceDescriptor_serialized_options, [ServiceDescriptor, :pointer, Internal::Arena], :pointer
114
+ attach_function :service_to_proto, :ServiceDescriptor_serialized_to_proto, [ServiceDescriptor, :pointer, Internal::Arena], :pointer
105
115
  end
106
116
  end
107
117
  end
@@ -42,7 +42,8 @@ module Google
42
42
  def self.discard_unknown(message)
43
43
  raise FrozenError if message.frozen?
44
44
  raise ArgumentError.new "Expected message, got #{message.class} instead." if message.instance_variable_get(:@msg).nil?
45
- unless Google::Protobuf::FFI.message_discard_unknown(message.instance_variable_get(:@msg), message.class.descriptor, 128)
45
+ pool_def = message.class.descriptor.instance_variable_get(:@descriptor_pool).descriptor_pool
46
+ unless Google::Protobuf::FFI.message_discard_unknown(message.instance_variable_get(:@msg), message.class.descriptor, pool_def, 128)
46
47
  raise RuntimeError.new "Messages nested too deeply."
47
48
  end
48
49
  nil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-protobuf
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.27.3
4
+ version: 4.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Protobuf Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-31 00:00:00.000000000 Z
11
+ date: 2025-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler-dock
@@ -146,6 +146,8 @@ files:
146
146
  - ext/google/protobuf_c/third_party/utf8_range/LICENSE
147
147
  - ext/google/protobuf_c/third_party/utf8_range/utf8_range.c
148
148
  - ext/google/protobuf_c/third_party/utf8_range/utf8_range.h
149
+ - ext/google/protobuf_c/third_party/utf8_range/utf8_range_neon.inc
150
+ - ext/google/protobuf_c/third_party/utf8_range/utf8_range_sse.inc
149
151
  - ext/google/protobuf_c/wrap_memcpy.c
150
152
  - lib/google/protobuf.rb
151
153
  - lib/google/protobuf/any_pb.rb
@@ -188,7 +190,7 @@ homepage: https://developers.google.com/protocol-buffers
188
190
  licenses:
189
191
  - BSD-3-Clause
190
192
  metadata:
191
- source_code_uri: https://github.com/protocolbuffers/protobuf/tree/v4.27.3/ruby
193
+ source_code_uri: https://github.com/protocolbuffers/protobuf/tree/v4.30.0/ruby
192
194
  post_install_message:
193
195
  rdoc_options: []
194
196
  require_paths:
@@ -204,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
204
206
  - !ruby/object:Gem::Version
205
207
  version: '0'
206
208
  requirements: []
207
- rubygems_version: 3.0.8
209
+ rubygems_version: 3.5.16
208
210
  signing_key:
209
211
  specification_version: 4
210
212
  summary: Protocol Buffers