google-protobuf 3.22.5 → 3.25.5
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.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/Rakefile +3 -0
- data/ext/google/protobuf_c/convert.c +23 -70
- data/ext/google/protobuf_c/convert.h +3 -28
- data/ext/google/protobuf_c/defs.c +175 -52
- data/ext/google/protobuf_c/defs.h +3 -28
- data/ext/google/protobuf_c/extconf.rb +2 -1
- data/ext/google/protobuf_c/glue.c +56 -0
- data/ext/google/protobuf_c/map.c +27 -28
- data/ext/google/protobuf_c/map.h +6 -28
- data/ext/google/protobuf_c/message.c +83 -83
- data/ext/google/protobuf_c/message.h +10 -28
- data/ext/google/protobuf_c/protobuf.c +39 -176
- data/ext/google/protobuf_c/protobuf.h +24 -32
- data/ext/google/protobuf_c/repeated_field.c +28 -29
- data/ext/google/protobuf_c/repeated_field.h +6 -28
- data/ext/google/protobuf_c/ruby-upb.c +2982 -2494
- data/ext/google/protobuf_c/ruby-upb.h +5838 -3467
- data/ext/google/protobuf_c/shared_convert.c +64 -0
- data/ext/google/protobuf_c/shared_convert.h +26 -0
- data/ext/google/protobuf_c/shared_message.c +65 -0
- data/ext/google/protobuf_c/shared_message.h +25 -0
- data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
- data/lib/google/protobuf/any_pb.rb +24 -5
- data/lib/google/protobuf/api_pb.rb +26 -23
- data/lib/google/protobuf/descriptor_pb.rb +40 -252
- data/lib/google/protobuf/duration_pb.rb +24 -5
- data/lib/google/protobuf/empty_pb.rb +24 -3
- data/lib/google/protobuf/ffi/descriptor.rb +165 -0
- data/lib/google/protobuf/ffi/descriptor_pool.rb +75 -0
- data/lib/google/protobuf/ffi/enum_descriptor.rb +171 -0
- data/lib/google/protobuf/ffi/ffi.rb +213 -0
- data/lib/google/protobuf/ffi/field_descriptor.rb +319 -0
- data/lib/google/protobuf/ffi/file_descriptor.rb +59 -0
- data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
- data/lib/google/protobuf/ffi/internal/convert.rb +305 -0
- data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
- data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
- data/lib/google/protobuf/ffi/map.rb +407 -0
- data/lib/google/protobuf/ffi/message.rb +662 -0
- data/lib/google/protobuf/ffi/object_cache.rb +30 -0
- data/lib/google/protobuf/ffi/oneof_descriptor.rb +95 -0
- data/lib/google/protobuf/ffi/repeated_field.rb +383 -0
- data/lib/google/protobuf/field_mask_pb.rb +24 -4
- data/lib/google/protobuf/message_exts.rb +3 -26
- data/lib/google/protobuf/object_cache.rb +97 -0
- data/lib/google/protobuf/plugin_pb.rb +25 -28
- data/lib/google/protobuf/repeated_field.rb +3 -26
- data/lib/google/protobuf/source_context_pb.rb +24 -4
- data/lib/google/protobuf/struct_pb.rb +24 -20
- data/lib/google/protobuf/timestamp_pb.rb +24 -5
- data/lib/google/protobuf/type_pb.rb +26 -68
- data/lib/google/protobuf/well_known_types.rb +5 -34
- data/lib/google/protobuf/wrappers_pb.rb +24 -28
- data/lib/google/protobuf.rb +27 -45
- data/lib/google/protobuf_ffi.rb +50 -0
- data/lib/google/protobuf_native.rb +20 -0
- data/lib/google/tasks/ffi.rake +102 -0
- metadata +72 -4
@@ -0,0 +1,30 @@
|
|
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
|
+
private
|
11
|
+
|
12
|
+
SIZEOF_LONG = ::FFI::MemoryPointer.new(:long).size
|
13
|
+
SIZEOF_VALUE = ::FFI::Pointer::SIZE
|
14
|
+
|
15
|
+
def self.interpreter_supports_non_finalized_keys_in_weak_map?
|
16
|
+
! defined? JRUBY_VERSION
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.cache_implementation
|
20
|
+
if interpreter_supports_non_finalized_keys_in_weak_map? and SIZEOF_LONG >= SIZEOF_VALUE
|
21
|
+
Google::Protobuf::ObjectCache
|
22
|
+
else
|
23
|
+
Google::Protobuf::LegacyObjectCache
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
public
|
28
|
+
OBJECT_CACHE = cache_implementation.new
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,95 @@
|
|
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 OneofDescriptor
|
11
|
+
attr :descriptor_pool, :oneof_def
|
12
|
+
include Enumerable
|
13
|
+
|
14
|
+
# FFI Interface methods and setup
|
15
|
+
extend ::FFI::DataConverter
|
16
|
+
native_type ::FFI::Type::POINTER
|
17
|
+
|
18
|
+
class << self
|
19
|
+
prepend Google::Protobuf::Internal::TypeSafety
|
20
|
+
include Google::Protobuf::Internal::PointerHelper
|
21
|
+
|
22
|
+
# @param value [OneofDescriptor] FieldDescriptor to convert to an FFI native type
|
23
|
+
# @param _ [Object] Unused
|
24
|
+
def to_native(value, _ = nil)
|
25
|
+
value.instance_variable_get(:@oneof_def) || ::FFI::Pointer::NULL
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# @param oneof_def [::FFI::Pointer] OneofDef pointer to be wrapped
|
30
|
+
# @param _ [Object] Unused
|
31
|
+
def from_native(oneof_def, _ = nil)
|
32
|
+
return nil if oneof_def.nil? or oneof_def.null?
|
33
|
+
message_descriptor = Google::Protobuf::FFI.get_oneof_containing_type oneof_def
|
34
|
+
raise RuntimeError.new "Message Descriptor is nil" if message_descriptor.nil?
|
35
|
+
file_def = Google::Protobuf::FFI.get_message_file_def message_descriptor.to_native
|
36
|
+
descriptor_from_file_def(file_def, oneof_def)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.new(*arguments, &block)
|
41
|
+
raise "OneofDescriptor objects may not be created from Ruby."
|
42
|
+
end
|
43
|
+
|
44
|
+
def name
|
45
|
+
Google::Protobuf::FFI.get_oneof_name(self)
|
46
|
+
end
|
47
|
+
|
48
|
+
def each &block
|
49
|
+
n = Google::Protobuf::FFI.get_oneof_field_count(self)
|
50
|
+
0.upto(n-1) do |i|
|
51
|
+
yield(Google::Protobuf::FFI.get_oneof_field_by_index(self, i))
|
52
|
+
end
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def options
|
57
|
+
@options ||= begin
|
58
|
+
size_ptr = ::FFI::MemoryPointer.new(:size_t, 1)
|
59
|
+
temporary_arena = Google::Protobuf::FFI.create_arena
|
60
|
+
buffer = Google::Protobuf::FFI.oneof_options(self, size_ptr, temporary_arena)
|
61
|
+
Google::Protobuf::OneofOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze).send(:internal_deep_freeze)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def initialize(oneof_def, descriptor_pool)
|
68
|
+
@descriptor_pool = descriptor_pool
|
69
|
+
@oneof_def = oneof_def
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.private_constructor(oneof_def, descriptor_pool)
|
73
|
+
instance = allocate
|
74
|
+
instance.send(:initialize, oneof_def, descriptor_pool)
|
75
|
+
instance
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class FFI
|
80
|
+
# MessageDef
|
81
|
+
attach_function :get_oneof_by_name, :upb_MessageDef_FindOneofByNameWithSize, [Descriptor, :string, :size_t], OneofDescriptor
|
82
|
+
attach_function :get_oneof_by_index, :upb_MessageDef_Oneof, [Descriptor, :int], OneofDescriptor
|
83
|
+
|
84
|
+
# OneofDescriptor
|
85
|
+
attach_function :get_oneof_name, :upb_OneofDef_Name, [OneofDescriptor], :string
|
86
|
+
attach_function :get_oneof_field_count, :upb_OneofDef_FieldCount, [OneofDescriptor], :int
|
87
|
+
attach_function :get_oneof_field_by_index, :upb_OneofDef_Field, [OneofDescriptor, :int], FieldDescriptor
|
88
|
+
attach_function :get_oneof_containing_type,:upb_OneofDef_ContainingType, [:pointer], Descriptor
|
89
|
+
attach_function :oneof_options, :OneOfDescriptor_serialized_options, [OneofDescriptor, :pointer, Internal::Arena], :pointer
|
90
|
+
|
91
|
+
# FieldDescriptor
|
92
|
+
attach_function :real_containing_oneof, :upb_FieldDef_RealContainingOneof, [FieldDescriptor], OneofDescriptor
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,383 @@
|
|
1
|
+
# Protocol Buffers - Google's data interchange format
|
2
|
+
# Copyright 2008 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
|
+
# This class makes RepeatedField act (almost-) like a Ruby Array.
|
10
|
+
# It has convenience methods that extend the core C or Java based
|
11
|
+
# methods.
|
12
|
+
#
|
13
|
+
# This is a best-effort to mirror Array behavior. Two comments:
|
14
|
+
# 1) patches always welcome :)
|
15
|
+
# 2) if performance is an issue, feel free to rewrite the method
|
16
|
+
# in C. The source code has plenty of examples
|
17
|
+
#
|
18
|
+
# KNOWN ISSUES
|
19
|
+
# - #[]= doesn't allow less used approaches such as `arr[1, 2] = 'fizz'`
|
20
|
+
# - #concat should return the orig array
|
21
|
+
# - #push should accept multiple arguments and push them all at the same time
|
22
|
+
#
|
23
|
+
module Google
|
24
|
+
module Protobuf
|
25
|
+
class FFI
|
26
|
+
# Array
|
27
|
+
attach_function :append_array, :upb_Array_Append, [:Array, MessageValue.by_value, Internal::Arena], :bool
|
28
|
+
attach_function :get_msgval_at,:upb_Array_Get, [:Array, :size_t], MessageValue.by_value
|
29
|
+
attach_function :create_array, :upb_Array_New, [Internal::Arena, CType], :Array
|
30
|
+
attach_function :array_resize, :upb_Array_Resize, [:Array, :size_t, Internal::Arena], :bool
|
31
|
+
attach_function :array_set, :upb_Array_Set, [:Array, :size_t, MessageValue.by_value], :void
|
32
|
+
attach_function :array_size, :upb_Array_Size, [:Array], :size_t
|
33
|
+
end
|
34
|
+
|
35
|
+
class RepeatedField
|
36
|
+
include Enumerable
|
37
|
+
|
38
|
+
##
|
39
|
+
# call-seq:
|
40
|
+
# RepeatedField.new(type, type_class = nil, initial_values = [])
|
41
|
+
#
|
42
|
+
# Creates a new repeated field. The provided type must be a Ruby symbol, and
|
43
|
+
# an take on the same values as those accepted by FieldDescriptor#type=. If
|
44
|
+
# the type is :message or :enum, type_class must be non-nil, and must be the
|
45
|
+
# Ruby class or module returned by Descriptor#msgclass or
|
46
|
+
# EnumDescriptor#enummodule, respectively. An initial list of elements may also
|
47
|
+
# be provided.
|
48
|
+
def self.new(type, type_class = nil, initial_values = [])
|
49
|
+
instance = allocate
|
50
|
+
# TODO This argument mangling doesn't agree with the type signature in the comments
|
51
|
+
# but is required to make unit tests pass;
|
52
|
+
if type_class.is_a?(Enumerable) and initial_values.empty? and ![:enum, :message].include?(type)
|
53
|
+
initial_values = type_class
|
54
|
+
type_class = nil
|
55
|
+
end
|
56
|
+
instance.send(:initialize, type, type_class: type_class, initial_values: initial_values)
|
57
|
+
instance
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# call-seq:
|
62
|
+
# RepeatedField.each(&block)
|
63
|
+
#
|
64
|
+
# Invokes the block once for each element of the repeated field. RepeatedField
|
65
|
+
# also includes Enumerable; combined with this method, the repeated field thus
|
66
|
+
# acts like an ordinary Ruby sequence.
|
67
|
+
def each &block
|
68
|
+
each_msg_val do |element|
|
69
|
+
yield(convert_upb_to_ruby(element, type, descriptor, arena))
|
70
|
+
end
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def [](*args)
|
75
|
+
count = length
|
76
|
+
if args.size < 1
|
77
|
+
raise ArgumentError.new "Index or range is a required argument."
|
78
|
+
end
|
79
|
+
if args[0].is_a? Range
|
80
|
+
if args.size > 1
|
81
|
+
raise ArgumentError.new "Expected 1 when passing Range argument, but got #{args.size}"
|
82
|
+
end
|
83
|
+
range = args[0]
|
84
|
+
# Handle begin-less and/or endless ranges, when supported.
|
85
|
+
index_of_first = range.respond_to?(:begin) ? range.begin : range.last
|
86
|
+
index_of_first = 0 if index_of_first.nil?
|
87
|
+
end_of_range = range.respond_to?(:end) ? range.end : range.last
|
88
|
+
index_of_last = end_of_range.nil? ? -1 : end_of_range
|
89
|
+
|
90
|
+
if index_of_last < 0
|
91
|
+
index_of_last += count
|
92
|
+
end
|
93
|
+
unless range.exclude_end? and !end_of_range.nil?
|
94
|
+
index_of_last += 1
|
95
|
+
end
|
96
|
+
index_of_first += count if index_of_first < 0
|
97
|
+
length = index_of_last - index_of_first
|
98
|
+
return [] if length.zero?
|
99
|
+
elsif args[0].is_a? Integer
|
100
|
+
index_of_first = args[0]
|
101
|
+
index_of_first += count if index_of_first < 0
|
102
|
+
if args.size > 2
|
103
|
+
raise ArgumentError.new "Expected 1 or 2 arguments, but got #{args.size}"
|
104
|
+
end
|
105
|
+
if args.size == 1 # No length specified, return one element
|
106
|
+
if array.null? or index_of_first < 0 or index_of_first >= count
|
107
|
+
return nil
|
108
|
+
else
|
109
|
+
return convert_upb_to_ruby(Google::Protobuf::FFI.get_msgval_at(array, index_of_first), type, descriptor, arena)
|
110
|
+
end
|
111
|
+
else
|
112
|
+
length = [args[1],count].min
|
113
|
+
end
|
114
|
+
else
|
115
|
+
raise NotImplementedError
|
116
|
+
end
|
117
|
+
|
118
|
+
if array.null? or index_of_first < 0 or index_of_first >= count
|
119
|
+
nil
|
120
|
+
else
|
121
|
+
if index_of_first + length > count
|
122
|
+
length = count - index_of_first
|
123
|
+
end
|
124
|
+
if length < 0
|
125
|
+
nil
|
126
|
+
else
|
127
|
+
subarray(index_of_first, length)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
alias at []
|
132
|
+
|
133
|
+
|
134
|
+
def []=(index, value)
|
135
|
+
raise FrozenError if frozen?
|
136
|
+
count = length
|
137
|
+
index += count if index < 0
|
138
|
+
return nil if index < 0
|
139
|
+
if index >= count
|
140
|
+
resize(index+1)
|
141
|
+
empty_message_value = Google::Protobuf::FFI::MessageValue.new # Implicitly clear
|
142
|
+
count.upto(index-1) do |i|
|
143
|
+
Google::Protobuf::FFI.array_set(array, i, empty_message_value)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
Google::Protobuf::FFI.array_set(array, index, convert_ruby_to_upb(value, arena, type, descriptor))
|
147
|
+
nil
|
148
|
+
end
|
149
|
+
|
150
|
+
def push(*elements)
|
151
|
+
raise FrozenError if frozen?
|
152
|
+
internal_push(*elements)
|
153
|
+
end
|
154
|
+
|
155
|
+
def <<(element)
|
156
|
+
raise FrozenError if frozen?
|
157
|
+
push element
|
158
|
+
end
|
159
|
+
|
160
|
+
def replace(replacements)
|
161
|
+
raise FrozenError if frozen?
|
162
|
+
clear
|
163
|
+
push(*replacements)
|
164
|
+
end
|
165
|
+
|
166
|
+
def clear
|
167
|
+
raise FrozenError if frozen?
|
168
|
+
resize 0
|
169
|
+
self
|
170
|
+
end
|
171
|
+
|
172
|
+
def length
|
173
|
+
array.null? ? 0 : Google::Protobuf::FFI.array_size(array)
|
174
|
+
end
|
175
|
+
alias size :length
|
176
|
+
|
177
|
+
def dup
|
178
|
+
instance = self.class.allocate
|
179
|
+
instance.send(:initialize, type, descriptor: descriptor, arena: arena)
|
180
|
+
each_msg_val do |element|
|
181
|
+
instance.send(:append_msg_val, element)
|
182
|
+
end
|
183
|
+
instance
|
184
|
+
end
|
185
|
+
alias clone dup
|
186
|
+
|
187
|
+
def ==(other)
|
188
|
+
return true if other.object_id == object_id
|
189
|
+
if other.is_a? RepeatedField
|
190
|
+
return false unless other.length == length
|
191
|
+
each_msg_val_with_index do |msg_val, i|
|
192
|
+
other_msg_val = Google::Protobuf::FFI.get_msgval_at(other.send(:array), i)
|
193
|
+
unless Google::Protobuf::FFI.message_value_equal(msg_val, other_msg_val, type, descriptor)
|
194
|
+
return false
|
195
|
+
end
|
196
|
+
end
|
197
|
+
return true
|
198
|
+
elsif other.is_a? Enumerable
|
199
|
+
return to_ary == other.to_a
|
200
|
+
end
|
201
|
+
false
|
202
|
+
end
|
203
|
+
|
204
|
+
##
|
205
|
+
# call-seq:
|
206
|
+
# RepeatedField.to_ary => array
|
207
|
+
#
|
208
|
+
# Used when converted implicitly into array, e.g. compared to an Array.
|
209
|
+
# Also called as a fallback of Object#to_a
|
210
|
+
def to_ary
|
211
|
+
return_value = []
|
212
|
+
each do |element|
|
213
|
+
return_value << element
|
214
|
+
end
|
215
|
+
return_value
|
216
|
+
end
|
217
|
+
|
218
|
+
def hash
|
219
|
+
return_value = 0
|
220
|
+
each_msg_val do |msg_val|
|
221
|
+
return_value = Google::Protobuf::FFI.message_value_hash(msg_val, type, descriptor, return_value)
|
222
|
+
end
|
223
|
+
return_value
|
224
|
+
end
|
225
|
+
|
226
|
+
def +(other)
|
227
|
+
if other.is_a? RepeatedField
|
228
|
+
if type != other.instance_variable_get(:@type) or descriptor != other.instance_variable_get(:@descriptor)
|
229
|
+
raise ArgumentError.new "Attempt to append RepeatedField with different element type."
|
230
|
+
end
|
231
|
+
fuse_arena(other.send(:arena))
|
232
|
+
super_set = dup
|
233
|
+
other.send(:each_msg_val) do |msg_val|
|
234
|
+
super_set.send(:append_msg_val, msg_val)
|
235
|
+
end
|
236
|
+
super_set
|
237
|
+
elsif other.is_a? Enumerable
|
238
|
+
super_set = dup
|
239
|
+
super_set.push(*other.to_a)
|
240
|
+
else
|
241
|
+
raise ArgumentError.new "Unknown type appending to RepeatedField"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def concat(other)
|
246
|
+
raise ArgumentError.new "Expected Enumerable, but got #{other.class}" unless other.is_a? Enumerable
|
247
|
+
push(*other.to_a)
|
248
|
+
end
|
249
|
+
|
250
|
+
private
|
251
|
+
include Google::Protobuf::Internal::Convert
|
252
|
+
|
253
|
+
attr :name, :arena, :array, :type, :descriptor
|
254
|
+
|
255
|
+
def internal_deep_freeze
|
256
|
+
freeze
|
257
|
+
if type == :message
|
258
|
+
each do |element|
|
259
|
+
element.send :internal_deep_freeze
|
260
|
+
end
|
261
|
+
end
|
262
|
+
self
|
263
|
+
end
|
264
|
+
|
265
|
+
def internal_push(*elements)
|
266
|
+
elements.each do |element|
|
267
|
+
append_msg_val convert_ruby_to_upb(element, arena, type, descriptor)
|
268
|
+
end
|
269
|
+
self
|
270
|
+
end
|
271
|
+
|
272
|
+
def pop_one
|
273
|
+
raise FrozenError if frozen?
|
274
|
+
count = length
|
275
|
+
return nil if length.zero?
|
276
|
+
last_element = Google::Protobuf::FFI.get_msgval_at(array, count-1)
|
277
|
+
return_value = convert_upb_to_ruby(last_element, type, descriptor, arena)
|
278
|
+
resize(count-1)
|
279
|
+
return_value
|
280
|
+
end
|
281
|
+
|
282
|
+
def subarray(start, length)
|
283
|
+
return_result = []
|
284
|
+
(start..(start + length - 1)).each do |i|
|
285
|
+
element = Google::Protobuf::FFI.get_msgval_at(array, i)
|
286
|
+
return_result << convert_upb_to_ruby(element, type, descriptor, arena)
|
287
|
+
end
|
288
|
+
return_result
|
289
|
+
end
|
290
|
+
|
291
|
+
def each_msg_val_with_index &block
|
292
|
+
n = array.null? ? 0 : Google::Protobuf::FFI.array_size(array)
|
293
|
+
0.upto(n-1) do |i|
|
294
|
+
yield Google::Protobuf::FFI.get_msgval_at(array, i), i
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def each_msg_val &block
|
299
|
+
each_msg_val_with_index do |msg_val, _|
|
300
|
+
yield msg_val
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# @param msg_val [Google::Protobuf::FFI::MessageValue] Value to append
|
305
|
+
def append_msg_val(msg_val)
|
306
|
+
unless Google::Protobuf::FFI.append_array(array, msg_val, arena)
|
307
|
+
raise NoMemoryError.new "Could not allocate room for #{msg_val} in Arena"
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
# @param new_size [Integer] New size of the array
|
312
|
+
def resize(new_size)
|
313
|
+
unless Google::Protobuf::FFI.array_resize(array, new_size, arena)
|
314
|
+
raise NoMemoryError.new "Array resize to #{new_size} failed!"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def initialize(type, type_class: nil, initial_values: nil, name: nil, arena: nil, array: nil, descriptor: nil)
|
319
|
+
@name = name || 'RepeatedField'
|
320
|
+
raise ArgumentError.new "Expected argument type to be a Symbol" unless type.is_a? Symbol
|
321
|
+
field_number = Google::Protobuf::FFI::FieldType[type]
|
322
|
+
raise ArgumentError.new "Unsupported type '#{type}'" if field_number.nil?
|
323
|
+
if !descriptor.nil?
|
324
|
+
@descriptor = descriptor
|
325
|
+
elsif [:message, :enum].include? type
|
326
|
+
raise ArgumentError.new "Expected at least 2 arguments for message/enum." if type_class.nil?
|
327
|
+
descriptor = type_class.respond_to?(:descriptor) ? type_class.descriptor : nil
|
328
|
+
raise ArgumentError.new "Type class #{type_class} has no descriptor. Please pass a class or enum as returned by the DescriptorPool." if descriptor.nil?
|
329
|
+
@descriptor = descriptor
|
330
|
+
else
|
331
|
+
@descriptor = nil
|
332
|
+
end
|
333
|
+
@type = type
|
334
|
+
|
335
|
+
@arena = arena || Google::Protobuf::FFI.create_arena
|
336
|
+
@array = array || Google::Protobuf::FFI.create_array(@arena, @type)
|
337
|
+
unless initial_values.nil?
|
338
|
+
unless initial_values.is_a? Enumerable
|
339
|
+
raise ArgumentError.new "Expected array as initializer value for repeated field '#{name}' (given #{initial_values.class})."
|
340
|
+
end
|
341
|
+
internal_push(*initial_values)
|
342
|
+
end
|
343
|
+
|
344
|
+
# Should always be the last expression of the initializer to avoid
|
345
|
+
# leaking references to this object before construction is complete.
|
346
|
+
OBJECT_CACHE.try_add(@array.address, self)
|
347
|
+
end
|
348
|
+
|
349
|
+
# @param field [FieldDescriptor] Descriptor of the field where the RepeatedField will be assigned
|
350
|
+
# @param values [Enumerable] Initial values; may be nil or empty
|
351
|
+
# @param arena [Arena] Owning message's arena
|
352
|
+
def self.construct_for_field(field, arena, values: nil, array: nil)
|
353
|
+
instance = allocate
|
354
|
+
options = {initial_values: values, name: field.name, arena: arena, array: array}
|
355
|
+
if [:enum, :message].include? field.type
|
356
|
+
options[:descriptor] = field.subtype
|
357
|
+
end
|
358
|
+
instance.send(:initialize, field.type, **options)
|
359
|
+
instance
|
360
|
+
end
|
361
|
+
|
362
|
+
def fuse_arena(arena)
|
363
|
+
arena.fuse(arena)
|
364
|
+
end
|
365
|
+
|
366
|
+
extend Google::Protobuf::Internal::Convert
|
367
|
+
|
368
|
+
def self.deep_copy(repeated_field)
|
369
|
+
instance = allocate
|
370
|
+
instance.send(:initialize, repeated_field.send(:type), descriptor: repeated_field.send(:descriptor))
|
371
|
+
instance.send(:resize, repeated_field.length)
|
372
|
+
new_array = instance.send(:array)
|
373
|
+
repeated_field.send(:each_msg_val_with_index) do |element, i|
|
374
|
+
Google::Protobuf::FFI.array_set(new_array, i, message_value_deep_copy(element, repeated_field.send(:type), repeated_field.send(:descriptor), instance.send(:arena)))
|
375
|
+
end
|
376
|
+
instance
|
377
|
+
end
|
378
|
+
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
require 'google/protobuf/repeated_field'
|
@@ -1,14 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
3
|
# source: google/protobuf/field_mask.proto
|
3
4
|
|
4
5
|
require 'google/protobuf'
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
|
8
|
+
descriptor_data = "\n google/protobuf/field_mask.proto\x12\x0fgoogle.protobuf\"\x1a\n\tFieldMask\x12\r\n\x05paths\x18\x01 \x03(\tB\x85\x01\n\x13\x63om.google.protobufB\x0e\x46ieldMaskProtoP\x01Z2google.golang.org/protobuf/types/known/fieldmaskpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3"
|
9
|
+
|
10
|
+
pool = Google::Protobuf::DescriptorPool.generated_pool
|
11
|
+
|
12
|
+
begin
|
13
|
+
pool.add_serialized_file(descriptor_data)
|
14
|
+
rescue TypeError
|
15
|
+
# Compatibility code: will be removed in the next major version.
|
16
|
+
require 'google/protobuf/descriptor_pb'
|
17
|
+
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
|
18
|
+
parsed.clear_dependency
|
19
|
+
serialized = parsed.class.encode(parsed)
|
20
|
+
file = pool.add_serialized_file(serialized)
|
21
|
+
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
|
22
|
+
imports = [
|
23
|
+
]
|
24
|
+
imports.each do |type_name, expected_filename|
|
25
|
+
import_file = pool.lookup(type_name).file_descriptor
|
26
|
+
if import_file.name != expected_filename
|
27
|
+
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
|
10
28
|
end
|
11
29
|
end
|
30
|
+
warn "Each proto file must use a consistent fully-qualified name."
|
31
|
+
warn "This will become an error in the next major version."
|
12
32
|
end
|
13
33
|
|
14
34
|
module Google
|
@@ -1,32 +1,9 @@
|
|
1
1
|
# Protocol Buffers - Google's data interchange format
|
2
2
|
# Copyright 2008 Google Inc. All rights reserved.
|
3
|
-
# https://developers.google.com/protocol-buffers/
|
4
3
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# * Redistributions of source code must retain the above copyright
|
10
|
-
# notice, this list of conditions and the following disclaimer.
|
11
|
-
# * Redistributions in binary form must reproduce the above
|
12
|
-
# copyright notice, this list of conditions and the following disclaimer
|
13
|
-
# in the documentation and/or other materials provided with the
|
14
|
-
# distribution.
|
15
|
-
# * Neither the name of Google Inc. nor the names of its
|
16
|
-
# contributors may be used to endorse or promote products derived from
|
17
|
-
# this software without specific prior written permission.
|
18
|
-
#
|
19
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
20
|
-
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
21
|
-
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
-
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
-
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
-
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
25
|
-
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
26
|
-
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
27
|
-
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28
|
-
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
-
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
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
|
30
7
|
|
31
8
|
module Google
|
32
9
|
module Protobuf
|
@@ -0,0 +1,97 @@
|
|
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
|