google-protobuf 3.21.2 → 4.29.1

Sign up to get free protection for your applications and to get access to all the features.
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