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
@@ -1,465 +0,0 @@
1
- #!/usr/bin/ruby
2
- #
3
- # Code that implements the DSL for defining proto messages.
4
-
5
- # Suppress warning: loading in progress, circular require considered harmful.
6
- # This circular require is intentional to avoid missing dependency.
7
- begin
8
- old_verbose, $VERBOSE = $VERBOSE, nil
9
- require 'google/protobuf/descriptor_pb'
10
- ensure
11
- $VERBOSE = old_verbose
12
- end
13
-
14
- module Google
15
- module Protobuf
16
- module Internal
17
- class AtomicCounter
18
- def initialize
19
- @n = 0
20
- @mu = Mutex.new
21
- end
22
-
23
- def get_and_increment
24
- n = @n
25
- @mu.synchronize {
26
- @n += 1
27
- }
28
- return n
29
- end
30
- end
31
-
32
- class Builder
33
- @@file_number = AtomicCounter.new
34
-
35
- def initialize(pool)
36
- @pool = pool
37
- @default_file = nil # Constructed lazily
38
- end
39
-
40
- def add_file(name, options={}, &block)
41
- builder = FileBuilder.new(@pool, name, options)
42
- builder.instance_eval(&block)
43
- internal_add_file(builder)
44
- end
45
-
46
- def add_message(name, &block)
47
- internal_default_file.add_message(name, &block)
48
- end
49
-
50
- def add_enum(name, &block)
51
- internal_default_file.add_enum(name, &block)
52
- end
53
-
54
- # ---- Internal methods, not part of the DSL ----
55
-
56
- def build
57
- if @default_file
58
- internal_add_file(@default_file)
59
- end
60
- end
61
-
62
- private def internal_add_file(file_builder)
63
- proto = file_builder.build
64
- serialized = Google::Protobuf::FileDescriptorProto.encode(proto)
65
- @pool.add_serialized_file(serialized)
66
- end
67
-
68
- private def internal_default_file
69
- number = @@file_number.get_and_increment
70
- filename = "ruby_default_file#{number}.proto"
71
- @default_file ||= FileBuilder.new(@pool, filename)
72
- end
73
- end
74
-
75
- class FileBuilder
76
- def initialize(pool, name, options={})
77
- @pool = pool
78
- @file_proto = Google::Protobuf::FileDescriptorProto.new(
79
- name: name,
80
- syntax: options.fetch(:syntax, "proto3")
81
- )
82
- end
83
-
84
- def add_message(name, &block)
85
- builder = MessageBuilder.new(name, self, @file_proto)
86
- builder.instance_eval(&block)
87
- builder.internal_add_synthetic_oneofs
88
- end
89
-
90
- def add_enum(name, &block)
91
- EnumBuilder.new(name, @file_proto).instance_eval(&block)
92
- end
93
-
94
- # ---- Internal methods, not part of the DSL ----
95
-
96
- # These methods fix up the file descriptor to account for differences
97
- # between the DSL and FileDescriptorProto.
98
-
99
- # The DSL can omit a package name; here we infer what the package is if
100
- # was not specified.
101
- def infer_package(names)
102
- # Package is longest common prefix ending in '.', if any.
103
- if not names.empty?
104
- min, max = names.minmax
105
- last_common_dot = nil
106
- min.size.times { |i|
107
- if min[i] != max[i] then break end
108
- if min[i] == "." then last_common_dot = i end
109
- }
110
- if last_common_dot
111
- return min.slice(0, last_common_dot)
112
- end
113
- end
114
-
115
- nil
116
- end
117
-
118
- def rewrite_enum_default(field)
119
- if field.type != :TYPE_ENUM or !field.has_default_value? or !field.has_type_name?
120
- return
121
- end
122
-
123
- value = field.default_value
124
- type_name = field.type_name
125
-
126
- if value.empty? or value[0].ord < "0".ord or value[0].ord > "9".ord
127
- return
128
- end
129
-
130
- if type_name.empty? || type_name[0] != "."
131
- return
132
- end
133
-
134
- type_name = type_name[1..-1]
135
- as_int = Integer(value) rescue return
136
-
137
- enum_desc = @pool.lookup(type_name)
138
- if enum_desc.is_a?(Google::Protobuf::EnumDescriptor)
139
- # Enum was defined in a previous file.
140
- name = enum_desc.lookup_value(as_int)
141
- if name
142
- # Update the default value in the proto.
143
- field.default_value = name
144
- end
145
- else
146
- # See if enum was defined in this file.
147
- @file_proto.enum_type.each { |enum_proto|
148
- if enum_proto.name == type_name
149
- enum_proto.value.each { |enum_value_proto|
150
- if enum_value_proto.number == as_int
151
- # Update the default value in the proto.
152
- field.default_value = enum_value_proto.name
153
- return
154
- end
155
- }
156
- # We found the right enum, but no value matched.
157
- return
158
- end
159
- }
160
- end
161
- end
162
-
163
- # Historically we allowed enum defaults to be specified as a number.
164
- # In retrospect this was a mistake as descriptors require defaults to
165
- # be specified as a label. This can make a difference if multiple
166
- # labels have the same number.
167
- #
168
- # Here we do a pass over all enum defaults and rewrite numeric defaults
169
- # by looking up their labels. This is complicated by the fact that the
170
- # enum definition can live in either the symtab or the file_proto.
171
- #
172
- # We take advantage of the fact that this is called *before* enums or
173
- # messages are nested in other messages, so we only have to iterate
174
- # one level deep.
175
- def rewrite_enum_defaults
176
- @file_proto.message_type.each { |msg|
177
- msg.field.each { |field|
178
- rewrite_enum_default(field)
179
- }
180
- }
181
- end
182
-
183
- # We have to do some relatively complicated logic here for backward
184
- # compatibility.
185
- #
186
- # In descriptor.proto, messages are nested inside other messages if that is
187
- # what the original .proto file looks like. For example, suppose we have this
188
- # foo.proto:
189
- #
190
- # package foo;
191
- # message Bar {
192
- # message Baz {}
193
- # }
194
- #
195
- # The descriptor for this must look like this:
196
- #
197
- # file {
198
- # name: "test.proto"
199
- # package: "foo"
200
- # message_type {
201
- # name: "Bar"
202
- # nested_type {
203
- # name: "Baz"
204
- # }
205
- # }
206
- # }
207
- #
208
- # However, the Ruby generated code has always generated messages in a flat,
209
- # non-nested way:
210
- #
211
- # Google::Protobuf::DescriptorPool.generated_pool.build do
212
- # add_message "foo.Bar" do
213
- # end
214
- # add_message "foo.Bar.Baz" do
215
- # end
216
- # end
217
- #
218
- # Here we need to do a translation where we turn this generated code into the
219
- # above descriptor. We need to infer that "foo" is the package name, and not
220
- # a message itself. */
221
-
222
- def split_parent_name(msg_or_enum)
223
- name = msg_or_enum.name
224
- idx = name.rindex(?.)
225
- if idx
226
- return name[0...idx], name[idx+1..-1]
227
- else
228
- return nil, name
229
- end
230
- end
231
-
232
- def get_parent_msg(msgs_by_name, name, parent_name)
233
- parent_msg = msgs_by_name[parent_name]
234
- if parent_msg.nil?
235
- raise "To define name #{name}, there must be a message named #{parent_name} to enclose it"
236
- end
237
- return parent_msg
238
- end
239
-
240
- def fix_nesting
241
- # Calculate and update package.
242
- msgs_by_name = @file_proto.message_type.map { |msg| [msg.name, msg] }.to_h
243
- enum_names = @file_proto.enum_type.map { |enum_proto| enum_proto.name }
244
-
245
- package = infer_package(msgs_by_name.keys + enum_names)
246
- if package
247
- @file_proto.package = package
248
- end
249
-
250
- # Update nesting based on package.
251
- final_msgs = Google::Protobuf::RepeatedField.new(:message, Google::Protobuf::DescriptorProto)
252
- final_enums = Google::Protobuf::RepeatedField.new(:message, Google::Protobuf::EnumDescriptorProto)
253
-
254
- # Note: We don't iterate over msgs_by_name.values because we want to
255
- # preserve order as listed in the DSL.
256
- @file_proto.message_type.each { |msg|
257
- parent_name, msg.name = split_parent_name(msg)
258
- if parent_name == package
259
- final_msgs << msg
260
- else
261
- get_parent_msg(msgs_by_name, msg.name, parent_name).nested_type << msg
262
- end
263
- }
264
-
265
- @file_proto.enum_type.each { |enum|
266
- parent_name, enum.name = split_parent_name(enum)
267
- if parent_name == package
268
- final_enums << enum
269
- else
270
- get_parent_msg(msgs_by_name, enum.name, parent_name).enum_type << enum
271
- end
272
- }
273
-
274
- @file_proto.message_type = final_msgs
275
- @file_proto.enum_type = final_enums
276
- end
277
-
278
- def internal_file_proto
279
- @file_proto
280
- end
281
-
282
- def build
283
- rewrite_enum_defaults
284
- fix_nesting
285
- return @file_proto
286
- end
287
- end
288
-
289
- class MessageBuilder
290
- def initialize(name, file_builder, file_proto)
291
- @file_builder = file_builder
292
- @msg_proto = Google::Protobuf::DescriptorProto.new(
293
- :name => name
294
- )
295
- file_proto.message_type << @msg_proto
296
- end
297
-
298
- def optional(name, type, number, type_class=nil, options=nil)
299
- internal_add_field(:LABEL_OPTIONAL, name, type, number, type_class, options)
300
- end
301
-
302
- def proto3_optional(name, type, number, type_class=nil, options=nil)
303
- internal_add_field(:LABEL_OPTIONAL, name, type, number, type_class, options,
304
- proto3_optional: true)
305
- end
306
-
307
- def required(name, type, number, type_class=nil, options=nil)
308
- internal_add_field(:LABEL_REQUIRED, name, type, number, type_class, options)
309
- end
310
-
311
- def repeated(name, type, number, type_class = nil, options=nil)
312
- internal_add_field(:LABEL_REPEATED, name, type, number, type_class, options)
313
- end
314
-
315
- def oneof(name, &block)
316
- OneofBuilder.new(name, self).instance_eval(&block)
317
- end
318
-
319
- # Defines a new map field on this message type with the given key and
320
- # value types, tag number, and type class (for message and enum value
321
- # types). The key type must be :int32/:uint32/:int64/:uint64, :bool, or
322
- # :string. The value type type must be a Ruby symbol (as accepted by
323
- # FieldDescriptor#type=) and the type_class must be a string, if
324
- # present (as accepted by FieldDescriptor#submsg_name=).
325
- def map(name, key_type, value_type, number, value_type_class = nil)
326
- if key_type == :float or key_type == :double or key_type == :enum or
327
- key_type == :message
328
- raise ArgError, "Not an acceptable key type: " + key_type
329
- end
330
- entry_name = "#{@msg_proto.name}_MapEntry_#{name}"
331
-
332
- @file_builder.add_message entry_name do
333
- optional :key, key_type, 1
334
- optional :value, value_type, 2, value_type_class
335
- end
336
- options = @file_builder.internal_file_proto.message_type.last.options ||= MessageOptions.new
337
- options.map_entry = true
338
- repeated name, :message, number, entry_name
339
- end
340
-
341
- # ---- Internal methods, not part of the DSL ----
342
-
343
- def internal_add_synthetic_oneofs
344
- # We have to build a set of all names, to ensure that synthetic oneofs
345
- # are not creating conflicts
346
- names = {}
347
- @msg_proto.field.each { |field| names[field.name] = true }
348
- @msg_proto.oneof_decl.each { |oneof| names[oneof.name] = true }
349
-
350
- @msg_proto.field.each { |field|
351
- if field.proto3_optional
352
- # Prepend '_' until we are no longer conflicting.
353
- oneof_name = field.name
354
- while names[oneof_name]
355
- oneof_name = "_" + oneof_name
356
- end
357
- names[oneof_name] = true
358
- field.oneof_index = @msg_proto.oneof_decl.size
359
- @msg_proto.oneof_decl << Google::Protobuf::OneofDescriptorProto.new(
360
- name: oneof_name
361
- )
362
- end
363
- }
364
- end
365
-
366
- def internal_add_field(label, name, type, number, type_class, options,
367
- oneof_index: nil, proto3_optional: false)
368
- # Allow passing either:
369
- # - (name, type, number, options) or
370
- # - (name, type, number, type_class, options)
371
- if options.nil? and type_class.instance_of?(Hash)
372
- options = type_class;
373
- type_class = nil;
374
- end
375
-
376
- field_proto = Google::Protobuf::FieldDescriptorProto.new(
377
- :label => label,
378
- :name => name,
379
- :type => ("TYPE_" + type.to_s.upcase).to_sym,
380
- :number => number
381
- )
382
-
383
- if type_class
384
- # Make it an absolute type name by prepending a dot.
385
- field_proto.type_name = "." + type_class
386
- end
387
-
388
- if oneof_index
389
- field_proto.oneof_index = oneof_index
390
- end
391
-
392
- if proto3_optional
393
- field_proto.proto3_optional = true
394
- end
395
-
396
- if options
397
- if options.key?(:default)
398
- default = options[:default]
399
- if !default.instance_of?(String)
400
- # Call #to_s since all defaults are strings in the descriptor.
401
- default = default.to_s
402
- end
403
- # XXX: we should be C-escaping bytes defaults.
404
- field_proto.default_value = default.dup.force_encoding("UTF-8")
405
- end
406
- if options.key?(:json_name)
407
- field_proto.json_name = options[:json_name]
408
- end
409
- end
410
-
411
- @msg_proto.field << field_proto
412
- end
413
-
414
- def internal_msg_proto
415
- @msg_proto
416
- end
417
- end
418
-
419
- class OneofBuilder
420
- def initialize(name, msg_builder)
421
- @msg_builder = msg_builder
422
- oneof_proto = Google::Protobuf::OneofDescriptorProto.new(
423
- :name => name
424
- )
425
- msg_proto = msg_builder.internal_msg_proto
426
- @oneof_index = msg_proto.oneof_decl.size
427
- msg_proto.oneof_decl << oneof_proto
428
- end
429
-
430
- def optional(name, type, number, type_class=nil, options=nil)
431
- @msg_builder.internal_add_field(
432
- :LABEL_OPTIONAL, name, type, number, type_class, options,
433
- oneof_index: @oneof_index)
434
- end
435
- end
436
-
437
- class EnumBuilder
438
- def initialize(name, file_proto)
439
- @enum_proto = Google::Protobuf::EnumDescriptorProto.new(
440
- :name => name
441
- )
442
- file_proto.enum_type << @enum_proto
443
- end
444
-
445
- def value(name, number)
446
- enum_value_proto = Google::Protobuf::EnumValueDescriptorProto.new(
447
- name: name,
448
- number: number
449
- )
450
- @enum_proto.value << enum_value_proto
451
- end
452
- end
453
-
454
- end
455
-
456
- # Re-open the class (the rest of the class is implemented in C)
457
- class DescriptorPool
458
- def build(&block)
459
- builder = Internal::Builder.new(self)
460
- builder.instance_eval(&block)
461
- builder.build
462
- end
463
- end
464
- end
465
- end