google-protobuf 3.21.2 → 4.29.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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +67 -86
  4. data/ext/google/protobuf_c/convert.h +3 -28
  5. data/ext/google/protobuf_c/defs.c +538 -77
  6. data/ext/google/protobuf_c/defs.h +3 -28
  7. data/ext/google/protobuf_c/extconf.rb +4 -4
  8. data/ext/google/protobuf_c/glue.c +72 -0
  9. data/ext/google/protobuf_c/map.c +114 -85
  10. data/ext/google/protobuf_c/map.h +12 -30
  11. data/ext/google/protobuf_c/message.c +264 -238
  12. data/ext/google/protobuf_c/message.h +11 -33
  13. data/ext/google/protobuf_c/protobuf.c +63 -187
  14. data/ext/google/protobuf_c/protobuf.h +27 -39
  15. data/ext/google/protobuf_c/repeated_field.c +72 -38
  16. data/ext/google/protobuf_c/repeated_field.h +11 -29
  17. data/ext/google/protobuf_c/ruby-upb.c +13783 -8236
  18. data/ext/google/protobuf_c/ruby-upb.h +14077 -4495
  19. data/ext/google/protobuf_c/shared_convert.c +69 -0
  20. data/ext/google/protobuf_c/shared_convert.h +26 -0
  21. data/ext/google/protobuf_c/shared_message.c +37 -0
  22. data/ext/google/protobuf_c/shared_message.h +21 -0
  23. data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +1 -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 +20 -7
  26. data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
  27. data/lib/google/protobuf/any_pb.rb +6 -8
  28. data/lib/google/protobuf/api_pb.rb +6 -26
  29. data/lib/google/protobuf/descriptor_pb.rb +23 -226
  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 +165 -0
  33. data/lib/google/protobuf/ffi/descriptor_pool.rb +77 -0
  34. data/lib/google/protobuf/ffi/enum_descriptor.rb +173 -0
  35. data/lib/google/protobuf/ffi/ffi.rb +215 -0
  36. data/lib/google/protobuf/ffi/field_descriptor.rb +330 -0
  37. data/lib/google/protobuf/ffi/file_descriptor.rb +49 -0
  38. data/lib/google/protobuf/ffi/internal/arena.rb +60 -0
  39. data/lib/google/protobuf/ffi/internal/convert.rb +296 -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 +433 -0
  43. data/lib/google/protobuf/ffi/message.rb +785 -0
  44. data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
  45. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  46. data/lib/google/protobuf/ffi/oneof_descriptor.rb +97 -0
  47. data/lib/google/protobuf/ffi/repeated_field.rb +411 -0
  48. data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
  49. data/lib/google/protobuf/field_mask_pb.rb +6 -7
  50. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  51. data/lib/google/protobuf/message_exts.rb +8 -26
  52. data/lib/google/protobuf/plugin_pb.rb +25 -0
  53. data/lib/google/protobuf/repeated_field.rb +7 -31
  54. data/lib/google/protobuf/source_context_pb.rb +6 -7
  55. data/lib/google/protobuf/struct_pb.rb +6 -23
  56. data/lib/google/protobuf/timestamp_pb.rb +6 -8
  57. data/lib/google/protobuf/type_pb.rb +6 -71
  58. data/lib/google/protobuf/well_known_types.rb +5 -34
  59. data/lib/google/protobuf/wrappers_pb.rb +6 -31
  60. data/lib/google/protobuf.rb +27 -45
  61. data/lib/google/protobuf_ffi.rb +51 -0
  62. data/lib/google/protobuf_native.rb +19 -0
  63. data/lib/google/tasks/ffi.rake +100 -0
  64. metadata +92 -16
  65. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  66. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  67. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  68. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
  69. data/tests/basic.rb +0 -739
  70. data/tests/generated_code_test.rb +0 -23
  71. data/tests/stress.rb +0 -38
@@ -0,0 +1,330 @@
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 FieldDescriptor
11
+ attr :field_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 [FieldDescriptor] FieldDescriptor to convert to an FFI native type
24
+ # @param _ [Object] Unused
25
+ def to_native(value, _)
26
+ field_def_ptr = value.instance_variable_get(:@field_def)
27
+ warn "Underlying field_def was nil!" if field_def_ptr.nil?
28
+ raise "Underlying field_def was null!" if !field_def_ptr.nil? and field_def_ptr.null?
29
+ field_def_ptr
30
+ end
31
+
32
+ ##
33
+ # @param field_def [::FFI::Pointer] FieldDef pointer to be wrapped
34
+ # @param _ [Object] Unused
35
+ def from_native(field_def, _ = nil)
36
+ return nil if field_def.nil? or field_def.null?
37
+ file_def = Google::Protobuf::FFI.file_def_by_raw_field_def(field_def)
38
+ descriptor_from_file_def(file_def, field_def)
39
+ end
40
+ end
41
+
42
+ def self.new(*arguments, &block)
43
+ raise "Descriptor objects may not be created from Ruby."
44
+ end
45
+
46
+ def to_s
47
+ inspect
48
+ end
49
+
50
+ def inspect
51
+ "#{self.class.name}: #{name}"
52
+ end
53
+
54
+ def name
55
+ @name ||= Google::Protobuf::FFI.get_full_name(self)
56
+ end
57
+
58
+ def json_name
59
+ @json_name ||= Google::Protobuf::FFI.get_json_name(self)
60
+ end
61
+
62
+ def number
63
+ @number ||= Google::Protobuf::FFI.get_number(self)
64
+ end
65
+
66
+ def type
67
+ @type ||= Google::Protobuf::FFI.get_type(self)
68
+ end
69
+
70
+ def label
71
+ @label ||= Google::Protobuf::FFI.get_label(self)
72
+ end
73
+
74
+ def default
75
+ return nil if Google::Protobuf::FFI.is_sub_message(self)
76
+ if Google::Protobuf::FFI.is_repeated(self)
77
+ message_value = Google::Protobuf::FFI::MessageValue.new
78
+ else
79
+ message_value = Google::Protobuf::FFI.get_default(self)
80
+ end
81
+ enum_def = Google::Protobuf::FFI.get_subtype_as_enum(self)
82
+ if enum_def.null?
83
+ convert_upb_to_ruby message_value, c_type
84
+ else
85
+ convert_upb_to_ruby message_value, c_type, enum_def
86
+ end
87
+ end
88
+
89
+ def submsg_name
90
+ if defined? @submsg_name
91
+ @submsg_name
92
+ else
93
+ @submsg_name = case c_type
94
+ when :enum
95
+ Google::Protobuf::FFI.get_enum_fullname Google::Protobuf::FFI.get_subtype_as_enum self
96
+ when :message
97
+ Google::Protobuf::FFI.get_message_fullname Google::Protobuf::FFI.get_subtype_as_message self
98
+ else
99
+ nil
100
+ end
101
+ end
102
+ end
103
+
104
+ ##
105
+ # Tests if this field has been set on the argument message.
106
+ #
107
+ # @param msg [Google::Protobuf::Message]
108
+ # @return [Object] Value of the field on this message.
109
+ # @raise [TypeError] If the field is not defined on this message.
110
+ def get(msg)
111
+ if msg.class.descriptor == Google::Protobuf::FFI.get_containing_message_def(self)
112
+ msg.send :get_field, self
113
+ else
114
+ raise TypeError.new "get method called on wrong message type"
115
+ end
116
+ end
117
+
118
+ def subtype
119
+ if defined? @subtype
120
+ @subtype
121
+ else
122
+ @subtype = case c_type
123
+ when :enum
124
+ Google::Protobuf::FFI.get_subtype_as_enum(self)
125
+ when :message
126
+ Google::Protobuf::FFI.get_subtype_as_message(self)
127
+ else
128
+ nil
129
+ end
130
+ end
131
+ end
132
+
133
+ ##
134
+ # Tests if this field has been set on the argument message.
135
+ #
136
+ # @param msg [Google::Protobuf::Message]
137
+ # @return [Boolean] True iff message has this field set
138
+ # @raise [TypeError] If this field does not exist on the message
139
+ # @raise [ArgumentError] If this field does not track presence
140
+ def has?(msg)
141
+ if msg.class.descriptor != Google::Protobuf::FFI.get_containing_message_def(self)
142
+ raise TypeError.new "has method called on wrong message type"
143
+ end
144
+ unless has_presence?
145
+ raise ArgumentError.new "does not track presence"
146
+ end
147
+
148
+ Google::Protobuf::FFI.get_message_has msg.instance_variable_get(:@msg), self
149
+ end
150
+
151
+ ##
152
+ # Tests if this field tracks presence.
153
+ #
154
+ # @return [Boolean] True iff this field tracks presence
155
+ def has_presence?
156
+ @has_presence ||= Google::Protobuf::FFI.get_has_presence(self)
157
+ end
158
+
159
+ ##
160
+ # Tests if this is a repeated field that uses packed encoding.
161
+ #
162
+ # @return [Boolean] True iff this field is packed
163
+ def is_packed?
164
+ @is_packed ||= Google::Protobuf::FFI.get_is_packed(self)
165
+ end
166
+
167
+ # @param msg [Google::Protobuf::Message]
168
+ def clear(msg)
169
+ if msg.class.descriptor != Google::Protobuf::FFI.get_containing_message_def(self)
170
+ raise TypeError.new "clear method called on wrong message type"
171
+ end
172
+ Google::Protobuf::FFI.clear_message_field msg.instance_variable_get(:@msg), self
173
+ nil
174
+ end
175
+
176
+ ##
177
+ # call-seq:
178
+ # FieldDescriptor.set(message, value)
179
+ #
180
+ # Sets the value corresponding to this field to the given value on the given
181
+ # message. Raises an exception if message is of the wrong type. Performs the
182
+ # ordinary type-checks for field setting.
183
+ #
184
+ # @param msg [Google::Protobuf::Message]
185
+ # @param value [Object]
186
+ def set(msg, value)
187
+ if msg.class.descriptor != Google::Protobuf::FFI.get_containing_message_def(self)
188
+ raise TypeError.new "set method called on wrong message type"
189
+ end
190
+ unless set_value_on_message value, msg.instance_variable_get(:@msg), msg.instance_variable_get(:@arena)
191
+ raise RuntimeError.new "allocation failed"
192
+ end
193
+ nil
194
+ end
195
+
196
+ def map?
197
+ @map ||= Google::Protobuf::FFI.is_map self
198
+ end
199
+
200
+ def repeated?
201
+ @repeated ||= Google::Protobuf::FFI.is_repeated self
202
+ end
203
+
204
+ def sub_message?
205
+ @sub_message ||= Google::Protobuf::FFI.is_sub_message self
206
+ end
207
+
208
+ def wrapper?
209
+ if defined? @wrapper
210
+ @wrapper
211
+ else
212
+ message_descriptor = Google::Protobuf::FFI.get_subtype_as_message(self)
213
+ @wrapper = message_descriptor.nil? ? false : message_descriptor.send(:wrapper?)
214
+ end
215
+ end
216
+
217
+ def options
218
+ @options ||= begin
219
+ size_ptr = ::FFI::MemoryPointer.new(:size_t, 1)
220
+ temporary_arena = Google::Protobuf::FFI.create_arena
221
+ buffer = Google::Protobuf::FFI.field_options(self, size_ptr, temporary_arena)
222
+ opts = Google::Protobuf::FieldOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze)
223
+ opts.clear_features()
224
+ opts.freeze
225
+ end
226
+ end
227
+
228
+ private
229
+
230
+ def initialize(field_def, descriptor_pool)
231
+ @field_def = field_def
232
+ @descriptor_pool = descriptor_pool
233
+ end
234
+
235
+ def self.private_constructor(field_def, descriptor_pool)
236
+ instance = allocate
237
+ instance.send(:initialize, field_def, descriptor_pool)
238
+ instance
239
+ end
240
+
241
+ # TODO Can this be added to the public API?
242
+ def real_containing_oneof
243
+ @real_containing_oneof ||= Google::Protobuf::FFI.real_containing_oneof self
244
+ end
245
+
246
+ # Implementation details below are subject to breaking changes without
247
+ # warning and are intended for use only within the gem.
248
+
249
+ ##
250
+ # Sets the field this FieldDescriptor represents to the given value on the given message.
251
+ # @param value [Object] Value to be set
252
+ # @param msg [::FFI::Pointer] Pointer the the upb_Message
253
+ # @param arena [Arena] Arena of the message that owns msg
254
+ def set_value_on_message(value, msg, arena, wrap: false)
255
+ message_to_alter = msg
256
+ field_def_to_set = self
257
+ if map?
258
+ raise TypeError.new "Expected map" unless value.is_a? Google::Protobuf::Map
259
+ message_descriptor = subtype
260
+
261
+ key_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 1)
262
+ key_field_type = Google::Protobuf::FFI.get_type(key_field_def)
263
+ raise TypeError.new "Map key type does not match field's key type" unless key_field_type == value.send(:key_type)
264
+
265
+ value_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 2)
266
+ value_field_type = Google::Protobuf::FFI.get_type(value_field_def)
267
+ raise TypeError.new "Map value type does not match field's value type" unless value_field_type == value.send(:value_type)
268
+
269
+ raise TypeError.new "Map value type has wrong message/enum class" unless value_field_def.subtype == value.send(:descriptor)
270
+
271
+ arena.fuse(value.send(:arena))
272
+ message_value = Google::Protobuf::FFI::MessageValue.new
273
+ message_value[:map_val] = value.send(:map_ptr)
274
+ elsif repeated?
275
+ raise TypeError.new "Expected repeated field array" unless value.is_a? RepeatedField
276
+ raise TypeError.new "Repeated field array has wrong message/enum class" unless value.send(:type) == type
277
+ arena.fuse(value.send(:arena))
278
+ message_value = Google::Protobuf::FFI::MessageValue.new
279
+ message_value[:array_val] = value.send(:array)
280
+ else
281
+ if value.nil? and (sub_message? or !real_containing_oneof.nil?)
282
+ Google::Protobuf::FFI.clear_message_field message_to_alter, field_def_to_set
283
+ return true
284
+ end
285
+ if wrap
286
+ value_field_def = Google::Protobuf::FFI.get_field_by_number subtype, 1
287
+ type_for_conversion = Google::Protobuf::FFI.get_c_type(value_field_def)
288
+ raise RuntimeError.new "Not expecting to get a msg or enum when unwrapping" if [:enum, :message].include? type_for_conversion
289
+ message_value = convert_ruby_to_upb(value, arena, type_for_conversion, nil)
290
+ message_to_alter = Google::Protobuf::FFI.get_mutable_message(msg, self, arena)[:msg]
291
+ field_def_to_set = value_field_def
292
+ else
293
+ message_value = convert_ruby_to_upb(value, arena, c_type, subtype)
294
+ end
295
+ end
296
+ Google::Protobuf::FFI.set_message_field message_to_alter, field_def_to_set, message_value, arena
297
+ end
298
+
299
+ def c_type
300
+ @c_type ||= Google::Protobuf::FFI.get_c_type(self)
301
+ end
302
+ end
303
+
304
+ class FFI
305
+ # MessageDef
306
+ attach_function :get_field_by_index, :upb_MessageDef_Field, [Descriptor, :int], FieldDescriptor
307
+ attach_function :get_field_by_name, :upb_MessageDef_FindFieldByNameWithSize,[Descriptor, :string, :size_t], FieldDescriptor
308
+ attach_function :get_field_by_number, :upb_MessageDef_FindFieldByNumber, [Descriptor, :uint32_t], FieldDescriptor
309
+
310
+ # FieldDescriptor
311
+ attach_function :field_options, :FieldDescriptor_serialized_options, [FieldDescriptor, :pointer, Internal::Arena], :pointer
312
+ attach_function :get_containing_message_def, :upb_FieldDef_ContainingType, [FieldDescriptor], Descriptor
313
+ attach_function :get_c_type, :upb_FieldDef_CType, [FieldDescriptor], CType
314
+ attach_function :get_default, :upb_FieldDef_Default, [FieldDescriptor], MessageValue.by_value
315
+ attach_function :get_subtype_as_enum, :upb_FieldDef_EnumSubDef, [FieldDescriptor], EnumDescriptor
316
+ attach_function :get_has_presence, :upb_FieldDef_HasPresence, [FieldDescriptor], :bool
317
+ attach_function :get_is_packed, :upb_FieldDef_IsPacked, [FieldDescriptor], :bool
318
+ attach_function :is_map, :upb_FieldDef_IsMap, [FieldDescriptor], :bool
319
+ attach_function :is_repeated, :upb_FieldDef_IsRepeated, [FieldDescriptor], :bool
320
+ attach_function :is_sub_message, :upb_FieldDef_IsSubMessage, [FieldDescriptor], :bool
321
+ attach_function :get_json_name, :upb_FieldDef_JsonName, [FieldDescriptor], :string
322
+ attach_function :get_label, :upb_FieldDef_Label, [FieldDescriptor], Label
323
+ attach_function :get_subtype_as_message, :upb_FieldDef_MessageSubDef, [FieldDescriptor], Descriptor
324
+ attach_function :get_full_name, :upb_FieldDef_Name, [FieldDescriptor], :string
325
+ attach_function :get_number, :upb_FieldDef_Number, [FieldDescriptor], :uint32_t
326
+ attach_function :get_type, :upb_FieldDef_Type, [FieldDescriptor], FieldType
327
+ attach_function :file_def_by_raw_field_def, :upb_FieldDef_File, [:pointer], :FileDef
328
+ end
329
+ end
330
+ end
@@ -0,0 +1,49 @@
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
+ # FileDescriptor
12
+ attach_function :file_def_name, :upb_FileDef_Name, [:FileDef], :string
13
+ attach_function :file_def_pool, :upb_FileDef_Pool, [:FileDef], :DefPool
14
+ attach_function :file_options, :FileDescriptor_serialized_options, [:FileDef, :pointer, Internal::Arena], :pointer
15
+ end
16
+
17
+ class FileDescriptor
18
+ attr :descriptor_pool, :file_def
19
+
20
+ def initialize(file_def, descriptor_pool)
21
+ @descriptor_pool = descriptor_pool
22
+ @file_def = file_def
23
+ end
24
+
25
+ def to_s
26
+ inspect
27
+ end
28
+
29
+ def inspect
30
+ "#{self.class.name}: #{name}"
31
+ end
32
+
33
+ def name
34
+ Google::Protobuf::FFI.file_def_name(@file_def)
35
+ end
36
+
37
+ def options
38
+ @options ||= begin
39
+ size_ptr = ::FFI::MemoryPointer.new(:size_t, 1)
40
+ temporary_arena = Google::Protobuf::FFI.create_arena
41
+ buffer = Google::Protobuf::FFI.file_options(@file_def, size_ptr, temporary_arena)
42
+ opts = Google::Protobuf::FileOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze)
43
+ opts.clear_features()
44
+ opts.freeze
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,60 @@
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
+ ##
9
+ # Implementation details below are subject to breaking changes without
10
+ # warning and are intended for use only within the gem.
11
+ module Google
12
+ module Protobuf
13
+ module Internal
14
+ class Arena
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
+
22
+ # @param value [Arena] Arena to convert to an FFI native type
23
+ # @param _ [Object] Unused
24
+ def to_native(value, _)
25
+ value.instance_variable_get(:@arena) || ::FFI::Pointer::NULL
26
+ end
27
+
28
+ ##
29
+ # @param value [::FFI::Pointer] Arena pointer to be wrapped
30
+ # @param _ [Object] Unused
31
+ def from_native(value, _)
32
+ new(value)
33
+ end
34
+ end
35
+
36
+ def initialize(pointer)
37
+ @arena = ::FFI::AutoPointer.new(pointer, Google::Protobuf::FFI.method(:free_arena))
38
+ @pinned_messages = []
39
+ end
40
+
41
+ def fuse(other_arena)
42
+ return if other_arena == self
43
+ unless Google::Protobuf::FFI.fuse_arena(self, other_arena)
44
+ raise RuntimeError.new "Unable to fuse arenas. This should never happen since Ruby does not use initial blocks"
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ class FFI
51
+ # Arena
52
+ attach_function :create_arena, :Arena_create, [], Internal::Arena
53
+ attach_function :fuse_arena, :upb_Arena_Fuse, [Internal::Arena, Internal::Arena], :bool
54
+ # Argument takes a :pointer rather than a typed Arena here due to
55
+ # implementation details of FFI::AutoPointer.
56
+ attach_function :free_arena, :upb_Arena_Free, [:pointer], :void
57
+ attach_function :arena_malloc, :upb_Arena_Malloc, [Internal::Arena, :size_t], :pointer
58
+ end
59
+ end
60
+ end