google-protobuf 3.14.0 → 4.26.1

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.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +317 -0
  4. data/ext/google/protobuf_c/convert.h +50 -0
  5. data/ext/google/protobuf_c/defs.c +759 -1709
  6. data/ext/google/protobuf_c/defs.h +82 -0
  7. data/ext/google/protobuf_c/extconf.rb +15 -8
  8. data/ext/google/protobuf_c/glue.c +56 -0
  9. data/ext/google/protobuf_c/map.c +328 -485
  10. data/ext/google/protobuf_c/map.h +44 -0
  11. data/ext/google/protobuf_c/message.c +1061 -530
  12. data/ext/google/protobuf_c/message.h +86 -0
  13. data/ext/google/protobuf_c/protobuf.c +314 -94
  14. data/ext/google/protobuf_c/protobuf.h +66 -621
  15. data/ext/google/protobuf_c/repeated_field.c +314 -353
  16. data/ext/google/protobuf_c/repeated_field.h +41 -0
  17. data/ext/google/protobuf_c/ruby-upb.c +15407 -0
  18. data/ext/google/protobuf_c/ruby-upb.h +13966 -0
  19. data/ext/google/protobuf_c/shared_convert.c +66 -0
  20. data/ext/google/protobuf_c/shared_convert.h +26 -0
  21. data/ext/google/protobuf_c/shared_message.c +67 -0
  22. data/ext/google/protobuf_c/shared_message.h +25 -0
  23. data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +22 -0
  24. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +467 -0
  25. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +22 -0
  26. data/ext/google/protobuf_c/wrap_memcpy.c +7 -29
  27. data/lib/google/protobuf/any_pb.rb +6 -8
  28. data/lib/google/protobuf/api_pb.rb +7 -26
  29. data/lib/google/protobuf/descriptor_pb.rb +65 -0
  30. data/lib/google/protobuf/duration_pb.rb +6 -8
  31. data/lib/google/protobuf/empty_pb.rb +6 -6
  32. data/lib/google/protobuf/ffi/descriptor.rb +164 -0
  33. data/lib/google/protobuf/ffi/descriptor_pool.rb +75 -0
  34. data/lib/google/protobuf/ffi/enum_descriptor.rb +171 -0
  35. data/lib/google/protobuf/ffi/ffi.rb +215 -0
  36. data/lib/google/protobuf/ffi/field_descriptor.rb +328 -0
  37. data/lib/google/protobuf/ffi/file_descriptor.rb +47 -0
  38. data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
  39. data/lib/google/protobuf/ffi/internal/convert.rb +289 -0
  40. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
  41. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  42. data/lib/google/protobuf/ffi/map.rb +409 -0
  43. data/lib/google/protobuf/ffi/message.rb +659 -0
  44. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  45. data/lib/google/protobuf/ffi/oneof_descriptor.rb +95 -0
  46. data/lib/google/protobuf/ffi/repeated_field.rb +385 -0
  47. data/lib/google/protobuf/field_mask_pb.rb +6 -7
  48. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  49. data/lib/google/protobuf/message_exts.rb +10 -28
  50. data/lib/google/protobuf/plugin_pb.rb +25 -0
  51. data/lib/google/protobuf/repeated_field.rb +19 -30
  52. data/lib/google/protobuf/source_context_pb.rb +6 -7
  53. data/lib/google/protobuf/struct_pb.rb +6 -23
  54. data/lib/google/protobuf/timestamp_pb.rb +6 -8
  55. data/lib/google/protobuf/type_pb.rb +7 -71
  56. data/lib/google/protobuf/well_known_types.rb +17 -36
  57. data/lib/google/protobuf/wrappers_pb.rb +6 -31
  58. data/lib/google/protobuf.rb +32 -118
  59. data/lib/google/protobuf_ffi.rb +49 -0
  60. data/lib/google/protobuf_native.rb +19 -0
  61. data/lib/google/tasks/ffi.rake +100 -0
  62. metadata +88 -37
  63. data/ext/google/protobuf_c/encode_decode.c +0 -1795
  64. data/ext/google/protobuf_c/storage.c +0 -1198
  65. data/ext/google/protobuf_c/upb.c +0 -13817
  66. data/ext/google/protobuf_c/upb.h +0 -6777
  67. data/tests/basic.rb +0 -543
  68. data/tests/generated_code_test.rb +0 -23
  69. data/tests/stress.rb +0 -38
@@ -0,0 +1,409 @@
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
+ def freeze
159
+ return self if frozen?
160
+ super
161
+ @arena.pin self
162
+ if value_type == :message
163
+ internal_iterator do |iterator|
164
+ value_message_value = Google::Protobuf::FFI.map_value(@map_ptr, iterator)
165
+ convert_upb_to_ruby(value_message_value, value_type, descriptor, arena).freeze
166
+ end
167
+ end
168
+ self
169
+ end
170
+
171
+ ##
172
+ # call-seq:
173
+ # Map.dup => new_map
174
+ #
175
+ # Duplicates this map with a shallow copy. References to all non-primitive
176
+ # element objects (e.g., submessages) are shared.
177
+ def dup
178
+ internal_dup
179
+ end
180
+ alias clone dup
181
+
182
+ ##
183
+ # call-seq:
184
+ # Map.==(other) => boolean
185
+ #
186
+ # Compares this map to another. Maps are equal if they have identical key sets,
187
+ # and for each key, the values in both maps compare equal. Elements are
188
+ # compared as per normal Ruby semantics, by calling their :== methods (or
189
+ # performing a more efficient comparison for primitive types).
190
+ #
191
+ # Maps with dissimilar key types or value types/typeclasses are never equal,
192
+ # even if value comparison (for example, between integers and floats) would
193
+ # have otherwise indicated that every element has equal value.
194
+ def ==(other)
195
+ if other.is_a? Hash
196
+ other = self.class.send(:private_constructor, key_type, value_type, descriptor, initial_values: other)
197
+ elsif !other.is_a? Google::Protobuf::Map
198
+ return false
199
+ end
200
+
201
+ return true if object_id == other.object_id
202
+ 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
203
+ other_map_ptr = other.send(:map_ptr)
204
+ each_msg_val do |key_message_value, value_message_value|
205
+ other_value = Google::Protobuf::FFI::MessageValue.new
206
+ return false unless Google::Protobuf::FFI.map_get(other_map_ptr, key_message_value, other_value)
207
+ return false unless Google::Protobuf::FFI.message_value_equal(value_message_value, other_value, value_type, descriptor)
208
+ end
209
+ true
210
+ end
211
+
212
+ def hash
213
+ return_value = 0
214
+ each_msg_val do |key_message_value, value_message_value|
215
+ return_value = Google::Protobuf::FFI.message_value_hash(key_message_value, key_type, nil, return_value)
216
+ return_value = Google::Protobuf::FFI.message_value_hash(value_message_value, value_type, descriptor, return_value)
217
+ end
218
+ return_value
219
+ end
220
+
221
+ ##
222
+ # call-seq:
223
+ # Map.to_h => {}
224
+ #
225
+ # Returns a Ruby Hash object containing all the values within the map
226
+ def to_h
227
+ return {} if map_ptr.nil? or map_ptr.null?
228
+ return_value = {}
229
+ each_msg_val do |key_message_value, value_message_value|
230
+ hash_key = convert_upb_to_ruby(key_message_value, key_type)
231
+ hash_value = scalar_create_hash(value_message_value, value_type, msg_or_enum_descriptor: descriptor)
232
+ return_value[hash_key] = hash_value
233
+ end
234
+ return_value
235
+ end
236
+
237
+ def inspect
238
+ key_value_pairs = []
239
+ each_msg_val do |key_message_value, value_message_value|
240
+ key_string = convert_upb_to_ruby(key_message_value, key_type).inspect
241
+ if value_type == :message
242
+ sub_msg_descriptor = Google::Protobuf::FFI.get_subtype_as_message(descriptor)
243
+ value_string = sub_msg_descriptor.msgclass.send(:inspect_internal, value_message_value[:msg_val])
244
+ else
245
+ value_string = convert_upb_to_ruby(value_message_value, value_type, descriptor).inspect
246
+ end
247
+ key_value_pairs << "#{key_string}=>#{value_string}"
248
+ end
249
+ "{#{key_value_pairs.join(", ")}}"
250
+ end
251
+
252
+ ##
253
+ # call-seq:
254
+ # Map.merge(other_map) => map
255
+ #
256
+ # Copies key/value pairs from other_map into a copy of this map. If a key is
257
+ # set in other_map and this map, the value from other_map overwrites the value
258
+ # in the new copy of this map. Returns the new copy of this map with merged
259
+ # contents.
260
+ def merge(other)
261
+ internal_merge(other)
262
+ end
263
+
264
+ ##
265
+ # call-seq:
266
+ # Map.each(&block)
267
+ #
268
+ # Invokes &block on each |key, value| pair in the map, in unspecified order.
269
+ # Note that Map also includes Enumerable; map thus acts like a normal Ruby
270
+ # sequence.
271
+ def each &block
272
+ each_msg_val do |key_message_value, value_message_value|
273
+ key_value = convert_upb_to_ruby(key_message_value, key_type)
274
+ value_value = convert_upb_to_ruby(value_message_value, value_type, descriptor, arena)
275
+ yield key_value, value_value
276
+ end
277
+ nil
278
+ end
279
+
280
+ private
281
+ attr :arena, :map_ptr, :key_type, :value_type, :descriptor, :name
282
+
283
+ include Google::Protobuf::Internal::Convert
284
+
285
+ def internal_iterator
286
+ iter = ::FFI::MemoryPointer.new(:size_t, 1)
287
+ iter.write(:size_t, Google::Protobuf::FFI::Upb_Map_Begin)
288
+ while Google::Protobuf::FFI.map_next(@map_ptr, iter) do
289
+ iter_size_t = iter.read(:size_t)
290
+ yield iter_size_t
291
+ end
292
+ end
293
+
294
+ def each_msg_val &block
295
+ internal_iterator do |iterator|
296
+ key_message_value = Google::Protobuf::FFI.map_key(@map_ptr, iterator)
297
+ value_message_value = Google::Protobuf::FFI.map_value(@map_ptr, iterator)
298
+ yield key_message_value, value_message_value
299
+ end
300
+ end
301
+
302
+ def internal_dup
303
+ instance = self.class.send(:private_constructor, key_type, value_type, descriptor, arena: arena)
304
+ new_map_ptr = instance.send(:map_ptr)
305
+ each_msg_val do |key_message_value, value_message_value|
306
+ Google::Protobuf::FFI.map_set(new_map_ptr, key_message_value, value_message_value, arena)
307
+ end
308
+ instance
309
+ end
310
+
311
+ def internal_merge_into_self(other)
312
+ case other
313
+ when Hash
314
+ other.each do |key, value|
315
+ key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
316
+ value_message_value = convert_ruby_to_upb(value, arena, value_type, descriptor)
317
+ Google::Protobuf::FFI.map_set(@map_ptr, key_message_value, value_message_value, arena)
318
+ end
319
+ when Google::Protobuf::Map
320
+ unless key_type == other.send(:key_type) and value_type == other.send(:value_type) and descriptor == other.descriptor
321
+ raise ArgumentError.new "Attempt to merge Map with mismatching types" #TODO Improve error message by adding type information
322
+ end
323
+ arena.fuse(other.send(:arena))
324
+ iter = ::FFI::MemoryPointer.new(:size_t, 1)
325
+ iter.write(:size_t, Google::Protobuf::FFI::Upb_Map_Begin)
326
+ other.send(:each_msg_val) do |key_message_value, value_message_value|
327
+ Google::Protobuf::FFI.map_set(@map_ptr, key_message_value, value_message_value, arena)
328
+ end
329
+ else
330
+ raise ArgumentError.new "Unknown type merging into Map" #TODO improve this error message by including type information
331
+ end
332
+ self
333
+ end
334
+
335
+ def internal_merge(other)
336
+ internal_dup.internal_merge_into_self(other)
337
+ end
338
+
339
+ def initialize(key_type, value_type, value_type_class: nil, initial_values: nil, arena: nil, map: nil, descriptor: nil, name: nil)
340
+ @name = name || 'Map'
341
+
342
+ unless [:int32, :int64, :uint32, :uint64, :bool, :string, :bytes].include? key_type
343
+ raise ArgumentError.new "Invalid key type for map." #TODO improve error message to include what type was passed
344
+ end
345
+ @key_type = key_type
346
+
347
+ unless [:int32, :int64, :uint32, :uint64, :bool, :string, :bytes, :enum, :message].include? value_type
348
+ raise ArgumentError.new "Invalid value type for map." #TODO improve error message to include what type was passed
349
+ end
350
+ @value_type = value_type
351
+
352
+ if !descriptor.nil?
353
+ raise ArgumentError "Expected descriptor to be a Descriptor or EnumDescriptor" unless [EnumDescriptor, Descriptor].include? descriptor.class
354
+ @descriptor = descriptor
355
+ elsif [:message, :enum].include? value_type
356
+ raise ArgumentError.new "Expected at least 3 arguments for message/enum." if value_type_class.nil?
357
+ descriptor = value_type_class.respond_to?(:descriptor) ? value_type_class.descriptor : nil
358
+ 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?
359
+ @descriptor = descriptor
360
+ else
361
+ @descriptor = nil
362
+ end
363
+
364
+ @arena = arena || Google::Protobuf::FFI.create_arena
365
+ @map_ptr = map || Google::Protobuf::FFI.create_map(@arena, @key_type, @value_type)
366
+
367
+ internal_merge_into_self(initial_values) unless initial_values.nil?
368
+
369
+ # Should always be the last expression of the initializer to avoid
370
+ # leaking references to this object before construction is complete.
371
+ OBJECT_CACHE.try_add(@map_ptr.address, self)
372
+ end
373
+
374
+ # @param field [FieldDescriptor] Descriptor of the field where the RepeatedField will be assigned
375
+ # @param values [Hash|Map] Initial value; may be nil or empty
376
+ # @param arena [Arena] Owning message's arena
377
+ def self.construct_for_field(field, arena, value: nil, map: nil)
378
+ 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
379
+ instance = allocate
380
+ raise ArgumentError.new "Expected field with type :message, instead got #{field.class}" unless field.type == :message
381
+ message_descriptor = field.send(:subtype)
382
+ key_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 1)
383
+ key_field_type = Google::Protobuf::FFI.get_type(key_field_def)
384
+
385
+ value_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 2)
386
+ value_field_type = Google::Protobuf::FFI.get_type(value_field_def)
387
+ instance.send(:initialize, key_field_type, value_field_type, initial_values: value, name: field.name, arena: arena, map: map, descriptor: value_field_def.subtype)
388
+ instance
389
+ end
390
+
391
+ def self.private_constructor(key_type, value_type, descriptor, initial_values: nil, arena: nil)
392
+ instance = allocate
393
+ instance.send(:initialize, key_type, value_type, descriptor: descriptor, initial_values: initial_values, arena: arena)
394
+ instance
395
+ end
396
+
397
+ extend Google::Protobuf::Internal::Convert
398
+
399
+ def self.deep_copy(map)
400
+ instance = allocate
401
+ instance.send(:initialize, map.send(:key_type), map.send(:value_type), descriptor: map.send(:descriptor))
402
+ map.send(:each_msg_val) do |key_message_value, value_message_value|
403
+ 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))
404
+ end
405
+ instance
406
+ end
407
+ end
408
+ end
409
+ end