google-protobuf 3.25.4 → 4.27.2

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +7 -4
  3. data/ext/google/protobuf_c/defs.c +367 -28
  4. data/ext/google/protobuf_c/extconf.rb +1 -1
  5. data/ext/google/protobuf_c/glue.c +16 -0
  6. data/ext/google/protobuf_c/map.c +12 -19
  7. data/ext/google/protobuf_c/map.h +1 -1
  8. data/ext/google/protobuf_c/message.c +43 -90
  9. data/ext/google/protobuf_c/message.h +1 -5
  10. data/ext/google/protobuf_c/protobuf.c +19 -6
  11. data/ext/google/protobuf_c/repeated_field.c +6 -15
  12. data/ext/google/protobuf_c/repeated_field.h +1 -1
  13. data/ext/google/protobuf_c/ruby-upb.c +12684 -10768
  14. data/ext/google/protobuf_c/ruby-upb.h +6889 -5584
  15. data/ext/google/protobuf_c/shared_convert.c +10 -5
  16. data/ext/google/protobuf_c/shared_convert.h +2 -2
  17. data/ext/google/protobuf_c/shared_message.c +3 -31
  18. data/ext/google/protobuf_c/shared_message.h +0 -4
  19. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +467 -0
  20. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -8
  21. data/lib/google/protobuf/any_pb.rb +1 -22
  22. data/lib/google/protobuf/api_pb.rb +1 -24
  23. data/lib/google/protobuf/descriptor_pb.rb +3 -23
  24. data/lib/google/protobuf/duration_pb.rb +1 -22
  25. data/lib/google/protobuf/empty_pb.rb +1 -22
  26. data/lib/google/protobuf/ffi/descriptor.rb +4 -3
  27. data/lib/google/protobuf/ffi/descriptor_pool.rb +3 -1
  28. data/lib/google/protobuf/ffi/enum_descriptor.rb +3 -1
  29. data/lib/google/protobuf/ffi/ffi.rb +3 -6
  30. data/lib/google/protobuf/ffi/field_descriptor.rb +13 -2
  31. data/lib/google/protobuf/ffi/file_descriptor.rb +3 -13
  32. data/lib/google/protobuf/ffi/internal/convert.rb +8 -24
  33. data/lib/google/protobuf/ffi/map.rb +13 -11
  34. data/lib/google/protobuf/ffi/message.rb +10 -13
  35. data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
  36. data/lib/google/protobuf/ffi/object_cache.rb +3 -3
  37. data/lib/google/protobuf/ffi/oneof_descriptor.rb +3 -1
  38. data/lib/google/protobuf/ffi/repeated_field.rb +12 -10
  39. data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
  40. data/lib/google/protobuf/field_mask_pb.rb +1 -22
  41. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  42. data/lib/google/protobuf/plugin_pb.rb +2 -24
  43. data/lib/google/protobuf/repeated_field.rb +4 -5
  44. data/lib/google/protobuf/source_context_pb.rb +1 -22
  45. data/lib/google/protobuf/struct_pb.rb +1 -22
  46. data/lib/google/protobuf/timestamp_pb.rb +1 -22
  47. data/lib/google/protobuf/type_pb.rb +1 -24
  48. data/lib/google/protobuf/wrappers_pb.rb +1 -22
  49. data/lib/google/protobuf.rb +1 -1
  50. data/lib/google/protobuf_ffi.rb +3 -2
  51. data/lib/google/protobuf_native.rb +0 -1
  52. data/lib/google/tasks/ffi.rake +1 -3
  53. metadata +25 -12
  54. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  55. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  56. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  57. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
  58. data/lib/google/protobuf/object_cache.rb +0 -97
@@ -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
@@ -1,97 +0,0 @@
1
- # Protocol Buffers - Google's data interchange format
2
- # Copyright 2023 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
- # A pointer -> Ruby Object cache that keeps references to Ruby wrapper
11
- # objects. This allows us to look up any Ruby wrapper object by the address
12
- # of the object it is wrapping. That way we can avoid ever creating two
13
- # different wrapper objects for the same C object, which saves memory and
14
- # preserves object identity.
15
- #
16
- # We use WeakMap for the cache. If sizeof(long) > sizeof(VALUE), we also
17
- # need a secondary Hash to store WeakMap keys, because our pointer keys may
18
- # need to be stored as Bignum instead of Fixnum. Since WeakMap is weak for
19
- # both keys and values, a Bignum key will cause the WeakMap entry to be
20
- # collected immediately unless there is another reference to the Bignum.
21
- # This happens on 64-bit Windows, on which pointers are 64 bits but longs
22
- # are 32 bits. In this case, we enable the secondary Hash to hold the keys
23
- # and prevent them from being collected.
24
- class ObjectCache
25
- def initialize
26
- @map = ObjectSpace::WeakMap.new
27
- @mutex = Mutex.new
28
- end
29
-
30
- def get(key)
31
- @map[key]
32
- end
33
-
34
- def try_add(key, value)
35
- @map[key] || @mutex.synchronize do
36
- @map[key] ||= value
37
- end
38
- end
39
- end
40
-
41
- class LegacyObjectCache
42
- def initialize
43
- @secondary_map = {}
44
- @map = ObjectSpace::WeakMap.new
45
- @mutex = Mutex.new
46
- end
47
-
48
- def get(key)
49
- value = if secondary_key = @secondary_map[key]
50
- @map[secondary_key]
51
- else
52
- @mutex.synchronize do
53
- @map[(@secondary_map[key] ||= Object.new)]
54
- end
55
- end
56
-
57
- # GC if we could remove at least 2000 entries or 20% of the table size
58
- # (whichever is greater). Since the cost of the GC pass is O(N), we
59
- # want to make sure that we condition this on overall table size, to
60
- # avoid O(N^2) CPU costs.
61
- cutoff = (@secondary_map.size * 0.2).ceil
62
- cutoff = 2_000 if cutoff < 2_000
63
- if (@secondary_map.size - @map.size) > cutoff
64
- purge
65
- end
66
-
67
- value
68
- end
69
-
70
- def try_add(key, value)
71
- if secondary_key = @secondary_map[key]
72
- if old_value = @map[secondary_key]
73
- return old_value
74
- end
75
- end
76
-
77
- @mutex.synchronize do
78
- secondary_key ||= (@secondary_map[key] ||= Object.new)
79
- @map[secondary_key] ||= value
80
- end
81
- end
82
-
83
- private
84
-
85
- def purge
86
- @mutex.synchronize do
87
- @secondary_map.each do |key, secondary_key|
88
- unless @map.key?(secondary_key)
89
- @secondary_map.delete(key)
90
- end
91
- end
92
- end
93
- nil
94
- end
95
- end
96
- end
97
- end