google-protobuf 3.22.5 → 3.25.5

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +23 -70
  4. data/ext/google/protobuf_c/convert.h +3 -28
  5. data/ext/google/protobuf_c/defs.c +175 -52
  6. data/ext/google/protobuf_c/defs.h +3 -28
  7. data/ext/google/protobuf_c/extconf.rb +2 -1
  8. data/ext/google/protobuf_c/glue.c +56 -0
  9. data/ext/google/protobuf_c/map.c +27 -28
  10. data/ext/google/protobuf_c/map.h +6 -28
  11. data/ext/google/protobuf_c/message.c +83 -83
  12. data/ext/google/protobuf_c/message.h +10 -28
  13. data/ext/google/protobuf_c/protobuf.c +39 -176
  14. data/ext/google/protobuf_c/protobuf.h +24 -32
  15. data/ext/google/protobuf_c/repeated_field.c +28 -29
  16. data/ext/google/protobuf_c/repeated_field.h +6 -28
  17. data/ext/google/protobuf_c/ruby-upb.c +2982 -2494
  18. data/ext/google/protobuf_c/ruby-upb.h +5838 -3467
  19. data/ext/google/protobuf_c/shared_convert.c +64 -0
  20. data/ext/google/protobuf_c/shared_convert.h +26 -0
  21. data/ext/google/protobuf_c/shared_message.c +65 -0
  22. data/ext/google/protobuf_c/shared_message.h +25 -0
  23. data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
  24. data/lib/google/protobuf/any_pb.rb +24 -5
  25. data/lib/google/protobuf/api_pb.rb +26 -23
  26. data/lib/google/protobuf/descriptor_pb.rb +40 -252
  27. data/lib/google/protobuf/duration_pb.rb +24 -5
  28. data/lib/google/protobuf/empty_pb.rb +24 -3
  29. data/lib/google/protobuf/ffi/descriptor.rb +165 -0
  30. data/lib/google/protobuf/ffi/descriptor_pool.rb +75 -0
  31. data/lib/google/protobuf/ffi/enum_descriptor.rb +171 -0
  32. data/lib/google/protobuf/ffi/ffi.rb +213 -0
  33. data/lib/google/protobuf/ffi/field_descriptor.rb +319 -0
  34. data/lib/google/protobuf/ffi/file_descriptor.rb +59 -0
  35. data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
  36. data/lib/google/protobuf/ffi/internal/convert.rb +305 -0
  37. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
  38. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  39. data/lib/google/protobuf/ffi/map.rb +407 -0
  40. data/lib/google/protobuf/ffi/message.rb +662 -0
  41. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  42. data/lib/google/protobuf/ffi/oneof_descriptor.rb +95 -0
  43. data/lib/google/protobuf/ffi/repeated_field.rb +383 -0
  44. data/lib/google/protobuf/field_mask_pb.rb +24 -4
  45. data/lib/google/protobuf/message_exts.rb +3 -26
  46. data/lib/google/protobuf/object_cache.rb +97 -0
  47. data/lib/google/protobuf/plugin_pb.rb +25 -28
  48. data/lib/google/protobuf/repeated_field.rb +3 -26
  49. data/lib/google/protobuf/source_context_pb.rb +24 -4
  50. data/lib/google/protobuf/struct_pb.rb +24 -20
  51. data/lib/google/protobuf/timestamp_pb.rb +24 -5
  52. data/lib/google/protobuf/type_pb.rb +26 -68
  53. data/lib/google/protobuf/well_known_types.rb +5 -34
  54. data/lib/google/protobuf/wrappers_pb.rb +24 -28
  55. data/lib/google/protobuf.rb +27 -45
  56. data/lib/google/protobuf_ffi.rb +50 -0
  57. data/lib/google/protobuf_native.rb +20 -0
  58. data/lib/google/tasks/ffi.rake +102 -0
  59. metadata +72 -4
@@ -0,0 +1,407 @@
1
+ # Protocol Buffers - Google's data interchange format
2
+ # Copyright 2022 Google Inc. All rights reserved.
3
+ #
4
+ # Use of this source code is governed by a BSD-style
5
+ # license that can be found in the LICENSE file or at
6
+ # https://developers.google.com/open-source/licenses/bsd
7
+
8
+ module Google
9
+ module Protobuf
10
+ class FFI
11
+ # Map
12
+ attach_function :map_clear, :upb_Map_Clear, [:Map], :void
13
+ attach_function :map_delete, :upb_Map_Delete, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool
14
+ attach_function :map_get, :upb_Map_Get, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool
15
+ attach_function :create_map, :upb_Map_New, [Internal::Arena, CType, CType], :Map
16
+ attach_function :map_size, :upb_Map_Size, [:Map], :size_t
17
+ attach_function :map_set, :upb_Map_Set, [:Map, MessageValue.by_value, MessageValue.by_value, Internal::Arena], :bool
18
+
19
+ # MapIterator
20
+ attach_function :map_next, :upb_MapIterator_Next, [:Map, :pointer], :bool
21
+ attach_function :map_done, :upb_MapIterator_Done, [:Map, :size_t], :bool
22
+ attach_function :map_key, :upb_MapIterator_Key, [:Map, :size_t], MessageValue.by_value
23
+ attach_function :map_value, :upb_MapIterator_Value, [:Map, :size_t], MessageValue.by_value
24
+ end
25
+ class Map
26
+ include Enumerable
27
+ ##
28
+ # call-seq:
29
+ # Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
30
+ # => new map
31
+ #
32
+ # Allocates a new Map container. This constructor may be called with 2, 3, or 4
33
+ # arguments. The first two arguments are always present and are symbols (taking
34
+ # on the same values as field-type symbols in message descriptors) that
35
+ # indicate the type of the map key and value fields.
36
+ #
37
+ # The supported key types are: :int32, :int64, :uint32, :uint64, :bool,
38
+ # :string, :bytes.
39
+ #
40
+ # The supported value types are: :int32, :int64, :uint32, :uint64, :bool,
41
+ # :string, :bytes, :enum, :message.
42
+ #
43
+ # The third argument, value_typeclass, must be present if value_type is :enum
44
+ # or :message. As in RepeatedField#new, this argument must be a message class
45
+ # (for :message) or enum module (for :enum).
46
+ #
47
+ # The last argument, if present, provides initial content for map. Note that
48
+ # this may be an ordinary Ruby hashmap or another Map instance with identical
49
+ # key and value types. Also note that this argument may be present whether or
50
+ # not value_typeclass is present (and it is unambiguously separate from
51
+ # value_typeclass because value_typeclass's presence is strictly determined by
52
+ # value_type). The contents of this initial hashmap or Map instance are
53
+ # shallow-copied into the new Map: the original map is unmodified, but
54
+ # references to underlying objects will be shared if the value type is a
55
+ # message type.
56
+ def self.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
57
+ instance = allocate
58
+ # TODO This argument mangling doesn't agree with the type signature,
59
+ # but does align with the text of the comments and is required to make unit tests pass.
60
+ if init_hashmap.empty? and ![:enum, :message].include?(value_type)
61
+ init_hashmap = value_typeclass
62
+ value_typeclass = nil
63
+ end
64
+ instance.send(:initialize, key_type, value_type, value_type_class: value_typeclass, initial_values: init_hashmap)
65
+ instance
66
+ end
67
+
68
+ ##
69
+ # call-seq:
70
+ # Map.keys => [list_of_keys]
71
+ #
72
+ # Returns the list of keys contained in the map, in unspecified order.
73
+ def keys
74
+ return_value = []
75
+ internal_iterator do |iterator|
76
+ key_message_value = Google::Protobuf::FFI.map_key(@map_ptr, iterator)
77
+ return_value << convert_upb_to_ruby(key_message_value, key_type)
78
+ end
79
+ return_value
80
+ end
81
+
82
+ ##
83
+ # call-seq:
84
+ # Map.values => [list_of_values]
85
+ #
86
+ # Returns the list of values contained in the map, in unspecified order.
87
+ def values
88
+ return_value = []
89
+ internal_iterator do |iterator|
90
+ value_message_value = Google::Protobuf::FFI.map_value(@map_ptr, iterator)
91
+ return_value << convert_upb_to_ruby(value_message_value, value_type, descriptor, arena)
92
+ end
93
+ return_value
94
+ end
95
+
96
+ ##
97
+ # call-seq:
98
+ # Map.[](key) => value
99
+ #
100
+ # Accesses the element at the given key. Throws an exception if the key type is
101
+ # incorrect. Returns nil when the key is not present in the map.
102
+ def [](key)
103
+ value = Google::Protobuf::FFI::MessageValue.new
104
+ key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
105
+ if Google::Protobuf::FFI.map_get(@map_ptr, key_message_value, value)
106
+ convert_upb_to_ruby(value, value_type, descriptor, arena)
107
+ end
108
+ end
109
+
110
+ ##
111
+ # call-seq:
112
+ # Map.[]=(key, value) => value
113
+ #
114
+ # Inserts or overwrites the value at the given key with the given new value.
115
+ # Throws an exception if the key type is incorrect. Returns the new value that
116
+ # was just inserted.
117
+ def []=(key, value)
118
+ raise FrozenError.new "can't modify frozen #{self.class}" if frozen?
119
+ key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
120
+ value_message_value = convert_ruby_to_upb(value, arena, value_type, descriptor)
121
+ Google::Protobuf::FFI.map_set(@map_ptr, key_message_value, value_message_value, arena)
122
+ value
123
+ end
124
+
125
+ def has_key?(key)
126
+ key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
127
+ Google::Protobuf::FFI.map_get(@map_ptr, key_message_value, nil)
128
+ end
129
+
130
+ ##
131
+ # call-seq:
132
+ # Map.delete(key) => old_value
133
+ #
134
+ # Deletes the value at the given key, if any, returning either the old value or
135
+ # nil if none was present. Throws an exception if the key is of the wrong type.
136
+ def delete(key)
137
+ raise FrozenError.new "can't modify frozen #{self.class}" if frozen?
138
+ value = Google::Protobuf::FFI::MessageValue.new
139
+ key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
140
+ if Google::Protobuf::FFI.map_delete(@map_ptr, key_message_value, value)
141
+ convert_upb_to_ruby(value, value_type, descriptor, arena)
142
+ else
143
+ nil
144
+ end
145
+ end
146
+
147
+ def clear
148
+ raise FrozenError.new "can't modify frozen #{self.class}" if frozen?
149
+ Google::Protobuf::FFI.map_clear(@map_ptr)
150
+ nil
151
+ end
152
+
153
+ def length
154
+ Google::Protobuf::FFI.map_size(@map_ptr)
155
+ end
156
+ alias size length
157
+
158
+ ##
159
+ # call-seq:
160
+ # Map.dup => new_map
161
+ #
162
+ # Duplicates this map with a shallow copy. References to all non-primitive
163
+ # element objects (e.g., submessages) are shared.
164
+ def dup
165
+ internal_dup
166
+ end
167
+ alias clone dup
168
+
169
+ ##
170
+ # call-seq:
171
+ # Map.==(other) => boolean
172
+ #
173
+ # Compares this map to another. Maps are equal if they have identical key sets,
174
+ # and for each key, the values in both maps compare equal. Elements are
175
+ # compared as per normal Ruby semantics, by calling their :== methods (or
176
+ # performing a more efficient comparison for primitive types).
177
+ #
178
+ # Maps with dissimilar key types or value types/typeclasses are never equal,
179
+ # even if value comparison (for example, between integers and floats) would
180
+ # have otherwise indicated that every element has equal value.
181
+ def ==(other)
182
+ if other.is_a? Hash
183
+ other = self.class.send(:private_constructor, key_type, value_type, descriptor, initial_values: other)
184
+ elsif !other.is_a? Google::Protobuf::Map
185
+ return false
186
+ end
187
+
188
+ return true if object_id == other.object_id
189
+ return false if key_type != other.send(:key_type) or value_type != other.send(:value_type) or descriptor != other.send(:descriptor) or length != other.length
190
+ other_map_ptr = other.send(:map_ptr)
191
+ each_msg_val do |key_message_value, value_message_value|
192
+ other_value = Google::Protobuf::FFI::MessageValue.new
193
+ return false unless Google::Protobuf::FFI.map_get(other_map_ptr, key_message_value, other_value)
194
+ return false unless Google::Protobuf::FFI.message_value_equal(value_message_value, other_value, value_type, descriptor)
195
+ end
196
+ true
197
+ end
198
+
199
+ def hash
200
+ return_value = 0
201
+ each_msg_val do |key_message_value, value_message_value|
202
+ return_value = Google::Protobuf::FFI.message_value_hash(key_message_value, key_type, nil, return_value)
203
+ return_value = Google::Protobuf::FFI.message_value_hash(value_message_value, value_type, descriptor, return_value)
204
+ end
205
+ return_value
206
+ end
207
+
208
+ ##
209
+ # call-seq:
210
+ # Map.to_h => {}
211
+ #
212
+ # Returns a Ruby Hash object containing all the values within the map
213
+ def to_h
214
+ return {} if map_ptr.nil? or map_ptr.null?
215
+ return_value = {}
216
+ each_msg_val do |key_message_value, value_message_value|
217
+ hash_key = convert_upb_to_ruby(key_message_value, key_type)
218
+ hash_value = scalar_create_hash(value_message_value, value_type, msg_or_enum_descriptor: descriptor)
219
+ return_value[hash_key] = hash_value
220
+ end
221
+ return_value
222
+ end
223
+
224
+ def inspect
225
+ key_value_pairs = []
226
+ each_msg_val do |key_message_value, value_message_value|
227
+ key_string = convert_upb_to_ruby(key_message_value, key_type).inspect
228
+ if value_type == :message
229
+ sub_msg_descriptor = Google::Protobuf::FFI.get_subtype_as_message(descriptor)
230
+ value_string = sub_msg_descriptor.msgclass.send(:inspect_internal, value_message_value[:msg_val])
231
+ else
232
+ value_string = convert_upb_to_ruby(value_message_value, value_type, descriptor).inspect
233
+ end
234
+ key_value_pairs << "#{key_string}=>#{value_string}"
235
+ end
236
+ "{#{key_value_pairs.join(", ")}}"
237
+ end
238
+
239
+ ##
240
+ # call-seq:
241
+ # Map.merge(other_map) => map
242
+ #
243
+ # Copies key/value pairs from other_map into a copy of this map. If a key is
244
+ # set in other_map and this map, the value from other_map overwrites the value
245
+ # in the new copy of this map. Returns the new copy of this map with merged
246
+ # contents.
247
+ def merge(other)
248
+ internal_merge(other)
249
+ end
250
+
251
+ ##
252
+ # call-seq:
253
+ # Map.each(&block)
254
+ #
255
+ # Invokes &block on each |key, value| pair in the map, in unspecified order.
256
+ # Note that Map also includes Enumerable; map thus acts like a normal Ruby
257
+ # sequence.
258
+ def each &block
259
+ each_msg_val do |key_message_value, value_message_value|
260
+ key_value = convert_upb_to_ruby(key_message_value, key_type)
261
+ value_value = convert_upb_to_ruby(value_message_value, value_type, descriptor, arena)
262
+ yield key_value, value_value
263
+ end
264
+ nil
265
+ end
266
+
267
+ private
268
+ attr :arena, :map_ptr, :key_type, :value_type, :descriptor, :name
269
+
270
+ include Google::Protobuf::Internal::Convert
271
+
272
+ def internal_deep_freeze
273
+ freeze
274
+ if value_type == :message
275
+ internal_iterator do |iterator|
276
+ value_message_value = Google::Protobuf::FFI.map_value(@map_ptr, iterator)
277
+ convert_upb_to_ruby(value_message_value, value_type, descriptor, arena).send :internal_deep_freeze
278
+ end
279
+ end
280
+ self
281
+ end
282
+
283
+ def internal_iterator
284
+ iter = ::FFI::MemoryPointer.new(:size_t, 1)
285
+ iter.write(:size_t, Google::Protobuf::FFI::Upb_Map_Begin)
286
+ while Google::Protobuf::FFI.map_next(@map_ptr, iter) do
287
+ iter_size_t = iter.read(:size_t)
288
+ yield iter_size_t
289
+ end
290
+ end
291
+
292
+ def each_msg_val &block
293
+ internal_iterator do |iterator|
294
+ key_message_value = Google::Protobuf::FFI.map_key(@map_ptr, iterator)
295
+ value_message_value = Google::Protobuf::FFI.map_value(@map_ptr, iterator)
296
+ yield key_message_value, value_message_value
297
+ end
298
+ end
299
+
300
+ def internal_dup
301
+ instance = self.class.send(:private_constructor, key_type, value_type, descriptor, arena: arena)
302
+ new_map_ptr = instance.send(:map_ptr)
303
+ each_msg_val do |key_message_value, value_message_value|
304
+ Google::Protobuf::FFI.map_set(new_map_ptr, key_message_value, value_message_value, arena)
305
+ end
306
+ instance
307
+ end
308
+
309
+ def internal_merge_into_self(other)
310
+ case other
311
+ when Hash
312
+ other.each do |key, value|
313
+ key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
314
+ value_message_value = convert_ruby_to_upb(value, arena, value_type, descriptor)
315
+ Google::Protobuf::FFI.map_set(@map_ptr, key_message_value, value_message_value, arena)
316
+ end
317
+ when Google::Protobuf::Map
318
+ unless key_type == other.send(:key_type) and value_type == other.send(:value_type) and descriptor == other.descriptor
319
+ raise ArgumentError.new "Attempt to merge Map with mismatching types" #TODO Improve error message by adding type information
320
+ end
321
+ arena.fuse(other.send(:arena))
322
+ iter = ::FFI::MemoryPointer.new(:size_t, 1)
323
+ iter.write(:size_t, Google::Protobuf::FFI::Upb_Map_Begin)
324
+ other.send(:each_msg_val) do |key_message_value, value_message_value|
325
+ Google::Protobuf::FFI.map_set(@map_ptr, key_message_value, value_message_value, arena)
326
+ end
327
+ else
328
+ raise ArgumentError.new "Unknown type merging into Map" #TODO improve this error message by including type information
329
+ end
330
+ self
331
+ end
332
+
333
+ def internal_merge(other)
334
+ internal_dup.internal_merge_into_self(other)
335
+ end
336
+
337
+ def initialize(key_type, value_type, value_type_class: nil, initial_values: nil, arena: nil, map: nil, descriptor: nil, name: nil)
338
+ @name = name || 'Map'
339
+
340
+ unless [:int32, :int64, :uint32, :uint64, :bool, :string, :bytes].include? key_type
341
+ raise ArgumentError.new "Invalid key type for map." #TODO improve error message to include what type was passed
342
+ end
343
+ @key_type = key_type
344
+
345
+ unless [:int32, :int64, :uint32, :uint64, :bool, :string, :bytes, :enum, :message].include? value_type
346
+ raise ArgumentError.new "Invalid value type for map." #TODO improve error message to include what type was passed
347
+ end
348
+ @value_type = value_type
349
+
350
+ if !descriptor.nil?
351
+ raise ArgumentError "Expected descriptor to be a Descriptor or EnumDescriptor" unless [EnumDescriptor, Descriptor].include? descriptor.class
352
+ @descriptor = descriptor
353
+ elsif [:message, :enum].include? value_type
354
+ raise ArgumentError.new "Expected at least 3 arguments for message/enum." if value_type_class.nil?
355
+ descriptor = value_type_class.respond_to?(:descriptor) ? value_type_class.descriptor : nil
356
+ raise ArgumentError.new "Type class #{value_type_class} has no descriptor. Please pass a class or enum as returned by the DescriptorPool." if descriptor.nil?
357
+ @descriptor = descriptor
358
+ else
359
+ @descriptor = nil
360
+ end
361
+
362
+ @arena = arena || Google::Protobuf::FFI.create_arena
363
+ @map_ptr = map || Google::Protobuf::FFI.create_map(@arena, @key_type, @value_type)
364
+
365
+ internal_merge_into_self(initial_values) unless initial_values.nil?
366
+
367
+ # Should always be the last expression of the initializer to avoid
368
+ # leaking references to this object before construction is complete.
369
+ OBJECT_CACHE.try_add(@map_ptr.address, self)
370
+ end
371
+
372
+ # @param field [FieldDescriptor] Descriptor of the field where the RepeatedField will be assigned
373
+ # @param values [Hash|Map] Initial value; may be nil or empty
374
+ # @param arena [Arena] Owning message's arena
375
+ def self.construct_for_field(field, arena, value: nil, map: nil)
376
+ raise ArgumentError.new "Expected Hash object as initializer value for map field '#{field.name}' (given #{value.class})." unless value.nil? or value.is_a? Hash
377
+ instance = allocate
378
+ raise ArgumentError.new "Expected field with type :message, instead got #{field.class}" unless field.type == :message
379
+ message_descriptor = field.send(:subtype)
380
+ key_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 1)
381
+ key_field_type = Google::Protobuf::FFI.get_type(key_field_def)
382
+
383
+ value_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 2)
384
+ value_field_type = Google::Protobuf::FFI.get_type(value_field_def)
385
+ instance.send(:initialize, key_field_type, value_field_type, initial_values: value, name: field.name, arena: arena, map: map, descriptor: value_field_def.subtype)
386
+ instance
387
+ end
388
+
389
+ def self.private_constructor(key_type, value_type, descriptor, initial_values: nil, arena: nil)
390
+ instance = allocate
391
+ instance.send(:initialize, key_type, value_type, descriptor: descriptor, initial_values: initial_values, arena: arena)
392
+ instance
393
+ end
394
+
395
+ extend Google::Protobuf::Internal::Convert
396
+
397
+ def self.deep_copy(map)
398
+ instance = allocate
399
+ instance.send(:initialize, map.send(:key_type), map.send(:value_type), descriptor: map.send(:descriptor))
400
+ map.send(:each_msg_val) do |key_message_value, value_message_value|
401
+ Google::Protobuf::FFI.map_set(instance.send(:map_ptr), key_message_value, message_value_deep_copy(value_message_value, map.send(:value_type), map.send(:descriptor), instance.send(:arena)), instance.send(:arena))
402
+ end
403
+ instance
404
+ end
405
+ end
406
+ end
407
+ end