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,407 @@
|
|
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
|
+
# Map
|
12
|
+
attach_function :map_clear, :upb_Map_Clear, [:Map], :void
|
13
|
+
attach_function :map_delete, :upb_Map_Delete, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool
|
14
|
+
attach_function :map_get, :upb_Map_Get, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool
|
15
|
+
attach_function :create_map, :upb_Map_New, [Internal::Arena, CType, CType], :Map
|
16
|
+
attach_function :map_size, :upb_Map_Size, [:Map], :size_t
|
17
|
+
attach_function :map_set, :upb_Map_Set, [:Map, MessageValue.by_value, MessageValue.by_value, Internal::Arena], :bool
|
18
|
+
|
19
|
+
# MapIterator
|
20
|
+
attach_function :map_next, :upb_MapIterator_Next, [:Map, :pointer], :bool
|
21
|
+
attach_function :map_done, :upb_MapIterator_Done, [:Map, :size_t], :bool
|
22
|
+
attach_function :map_key, :upb_MapIterator_Key, [:Map, :size_t], MessageValue.by_value
|
23
|
+
attach_function :map_value, :upb_MapIterator_Value, [:Map, :size_t], MessageValue.by_value
|
24
|
+
end
|
25
|
+
class Map
|
26
|
+
include Enumerable
|
27
|
+
##
|
28
|
+
# call-seq:
|
29
|
+
# Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
|
30
|
+
# => new map
|
31
|
+
#
|
32
|
+
# Allocates a new Map container. This constructor may be called with 2, 3, or 4
|
33
|
+
# arguments. The first two arguments are always present and are symbols (taking
|
34
|
+
# on the same values as field-type symbols in message descriptors) that
|
35
|
+
# indicate the type of the map key and value fields.
|
36
|
+
#
|
37
|
+
# The supported key types are: :int32, :int64, :uint32, :uint64, :bool,
|
38
|
+
# :string, :bytes.
|
39
|
+
#
|
40
|
+
# The supported value types are: :int32, :int64, :uint32, :uint64, :bool,
|
41
|
+
# :string, :bytes, :enum, :message.
|
42
|
+
#
|
43
|
+
# The third argument, value_typeclass, must be present if value_type is :enum
|
44
|
+
# or :message. As in RepeatedField#new, this argument must be a message class
|
45
|
+
# (for :message) or enum module (for :enum).
|
46
|
+
#
|
47
|
+
# The last argument, if present, provides initial content for map. Note that
|
48
|
+
# this may be an ordinary Ruby hashmap or another Map instance with identical
|
49
|
+
# key and value types. Also note that this argument may be present whether or
|
50
|
+
# not value_typeclass is present (and it is unambiguously separate from
|
51
|
+
# value_typeclass because value_typeclass's presence is strictly determined by
|
52
|
+
# value_type). The contents of this initial hashmap or Map instance are
|
53
|
+
# shallow-copied into the new Map: the original map is unmodified, but
|
54
|
+
# references to underlying objects will be shared if the value type is a
|
55
|
+
# message type.
|
56
|
+
def self.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
|
57
|
+
instance = allocate
|
58
|
+
# TODO This argument mangling doesn't agree with the type signature,
|
59
|
+
# but does align with the text of the comments and is required to make unit tests pass.
|
60
|
+
if init_hashmap.empty? and ![:enum, :message].include?(value_type)
|
61
|
+
init_hashmap = value_typeclass
|
62
|
+
value_typeclass = nil
|
63
|
+
end
|
64
|
+
instance.send(:initialize, key_type, value_type, value_type_class: value_typeclass, initial_values: init_hashmap)
|
65
|
+
instance
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# call-seq:
|
70
|
+
# Map.keys => [list_of_keys]
|
71
|
+
#
|
72
|
+
# Returns the list of keys contained in the map, in unspecified order.
|
73
|
+
def keys
|
74
|
+
return_value = []
|
75
|
+
internal_iterator do |iterator|
|
76
|
+
key_message_value = Google::Protobuf::FFI.map_key(@map_ptr, iterator)
|
77
|
+
return_value << convert_upb_to_ruby(key_message_value, key_type)
|
78
|
+
end
|
79
|
+
return_value
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# call-seq:
|
84
|
+
# Map.values => [list_of_values]
|
85
|
+
#
|
86
|
+
# Returns the list of values contained in the map, in unspecified order.
|
87
|
+
def values
|
88
|
+
return_value = []
|
89
|
+
internal_iterator do |iterator|
|
90
|
+
value_message_value = Google::Protobuf::FFI.map_value(@map_ptr, iterator)
|
91
|
+
return_value << convert_upb_to_ruby(value_message_value, value_type, descriptor, arena)
|
92
|
+
end
|
93
|
+
return_value
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# call-seq:
|
98
|
+
# Map.[](key) => value
|
99
|
+
#
|
100
|
+
# Accesses the element at the given key. Throws an exception if the key type is
|
101
|
+
# incorrect. Returns nil when the key is not present in the map.
|
102
|
+
def [](key)
|
103
|
+
value = Google::Protobuf::FFI::MessageValue.new
|
104
|
+
key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
|
105
|
+
if Google::Protobuf::FFI.map_get(@map_ptr, key_message_value, value)
|
106
|
+
convert_upb_to_ruby(value, value_type, descriptor, arena)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# call-seq:
|
112
|
+
# Map.[]=(key, value) => value
|
113
|
+
#
|
114
|
+
# Inserts or overwrites the value at the given key with the given new value.
|
115
|
+
# Throws an exception if the key type is incorrect. Returns the new value that
|
116
|
+
# was just inserted.
|
117
|
+
def []=(key, value)
|
118
|
+
raise FrozenError.new "can't modify frozen #{self.class}" if frozen?
|
119
|
+
key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
|
120
|
+
value_message_value = convert_ruby_to_upb(value, arena, value_type, descriptor)
|
121
|
+
Google::Protobuf::FFI.map_set(@map_ptr, key_message_value, value_message_value, arena)
|
122
|
+
value
|
123
|
+
end
|
124
|
+
|
125
|
+
def has_key?(key)
|
126
|
+
key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
|
127
|
+
Google::Protobuf::FFI.map_get(@map_ptr, key_message_value, nil)
|
128
|
+
end
|
129
|
+
|
130
|
+
##
|
131
|
+
# call-seq:
|
132
|
+
# Map.delete(key) => old_value
|
133
|
+
#
|
134
|
+
# Deletes the value at the given key, if any, returning either the old value or
|
135
|
+
# nil if none was present. Throws an exception if the key is of the wrong type.
|
136
|
+
def delete(key)
|
137
|
+
raise FrozenError.new "can't modify frozen #{self.class}" if frozen?
|
138
|
+
value = Google::Protobuf::FFI::MessageValue.new
|
139
|
+
key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
|
140
|
+
if Google::Protobuf::FFI.map_delete(@map_ptr, key_message_value, value)
|
141
|
+
convert_upb_to_ruby(value, value_type, descriptor, arena)
|
142
|
+
else
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def clear
|
148
|
+
raise FrozenError.new "can't modify frozen #{self.class}" if frozen?
|
149
|
+
Google::Protobuf::FFI.map_clear(@map_ptr)
|
150
|
+
nil
|
151
|
+
end
|
152
|
+
|
153
|
+
def length
|
154
|
+
Google::Protobuf::FFI.map_size(@map_ptr)
|
155
|
+
end
|
156
|
+
alias size length
|
157
|
+
|
158
|
+
##
|
159
|
+
# call-seq:
|
160
|
+
# Map.dup => new_map
|
161
|
+
#
|
162
|
+
# Duplicates this map with a shallow copy. References to all non-primitive
|
163
|
+
# element objects (e.g., submessages) are shared.
|
164
|
+
def dup
|
165
|
+
internal_dup
|
166
|
+
end
|
167
|
+
alias clone dup
|
168
|
+
|
169
|
+
##
|
170
|
+
# call-seq:
|
171
|
+
# Map.==(other) => boolean
|
172
|
+
#
|
173
|
+
# Compares this map to another. Maps are equal if they have identical key sets,
|
174
|
+
# and for each key, the values in both maps compare equal. Elements are
|
175
|
+
# compared as per normal Ruby semantics, by calling their :== methods (or
|
176
|
+
# performing a more efficient comparison for primitive types).
|
177
|
+
#
|
178
|
+
# Maps with dissimilar key types or value types/typeclasses are never equal,
|
179
|
+
# even if value comparison (for example, between integers and floats) would
|
180
|
+
# have otherwise indicated that every element has equal value.
|
181
|
+
def ==(other)
|
182
|
+
if other.is_a? Hash
|
183
|
+
other = self.class.send(:private_constructor, key_type, value_type, descriptor, initial_values: other)
|
184
|
+
elsif !other.is_a? Google::Protobuf::Map
|
185
|
+
return false
|
186
|
+
end
|
187
|
+
|
188
|
+
return true if object_id == other.object_id
|
189
|
+
return false if key_type != other.send(:key_type) or value_type != other.send(:value_type) or descriptor != other.send(:descriptor) or length != other.length
|
190
|
+
other_map_ptr = other.send(:map_ptr)
|
191
|
+
each_msg_val do |key_message_value, value_message_value|
|
192
|
+
other_value = Google::Protobuf::FFI::MessageValue.new
|
193
|
+
return false unless Google::Protobuf::FFI.map_get(other_map_ptr, key_message_value, other_value)
|
194
|
+
return false unless Google::Protobuf::FFI.message_value_equal(value_message_value, other_value, value_type, descriptor)
|
195
|
+
end
|
196
|
+
true
|
197
|
+
end
|
198
|
+
|
199
|
+
def hash
|
200
|
+
return_value = 0
|
201
|
+
each_msg_val do |key_message_value, value_message_value|
|
202
|
+
return_value = Google::Protobuf::FFI.message_value_hash(key_message_value, key_type, nil, return_value)
|
203
|
+
return_value = Google::Protobuf::FFI.message_value_hash(value_message_value, value_type, descriptor, return_value)
|
204
|
+
end
|
205
|
+
return_value
|
206
|
+
end
|
207
|
+
|
208
|
+
##
|
209
|
+
# call-seq:
|
210
|
+
# Map.to_h => {}
|
211
|
+
#
|
212
|
+
# Returns a Ruby Hash object containing all the values within the map
|
213
|
+
def to_h
|
214
|
+
return {} if map_ptr.nil? or map_ptr.null?
|
215
|
+
return_value = {}
|
216
|
+
each_msg_val do |key_message_value, value_message_value|
|
217
|
+
hash_key = convert_upb_to_ruby(key_message_value, key_type)
|
218
|
+
hash_value = scalar_create_hash(value_message_value, value_type, msg_or_enum_descriptor: descriptor)
|
219
|
+
return_value[hash_key] = hash_value
|
220
|
+
end
|
221
|
+
return_value
|
222
|
+
end
|
223
|
+
|
224
|
+
def inspect
|
225
|
+
key_value_pairs = []
|
226
|
+
each_msg_val do |key_message_value, value_message_value|
|
227
|
+
key_string = convert_upb_to_ruby(key_message_value, key_type).inspect
|
228
|
+
if value_type == :message
|
229
|
+
sub_msg_descriptor = Google::Protobuf::FFI.get_subtype_as_message(descriptor)
|
230
|
+
value_string = sub_msg_descriptor.msgclass.send(:inspect_internal, value_message_value[:msg_val])
|
231
|
+
else
|
232
|
+
value_string = convert_upb_to_ruby(value_message_value, value_type, descriptor).inspect
|
233
|
+
end
|
234
|
+
key_value_pairs << "#{key_string}=>#{value_string}"
|
235
|
+
end
|
236
|
+
"{#{key_value_pairs.join(", ")}}"
|
237
|
+
end
|
238
|
+
|
239
|
+
##
|
240
|
+
# call-seq:
|
241
|
+
# Map.merge(other_map) => map
|
242
|
+
#
|
243
|
+
# Copies key/value pairs from other_map into a copy of this map. If a key is
|
244
|
+
# set in other_map and this map, the value from other_map overwrites the value
|
245
|
+
# in the new copy of this map. Returns the new copy of this map with merged
|
246
|
+
# contents.
|
247
|
+
def merge(other)
|
248
|
+
internal_merge(other)
|
249
|
+
end
|
250
|
+
|
251
|
+
##
|
252
|
+
# call-seq:
|
253
|
+
# Map.each(&block)
|
254
|
+
#
|
255
|
+
# Invokes &block on each |key, value| pair in the map, in unspecified order.
|
256
|
+
# Note that Map also includes Enumerable; map thus acts like a normal Ruby
|
257
|
+
# sequence.
|
258
|
+
def each &block
|
259
|
+
each_msg_val do |key_message_value, value_message_value|
|
260
|
+
key_value = convert_upb_to_ruby(key_message_value, key_type)
|
261
|
+
value_value = convert_upb_to_ruby(value_message_value, value_type, descriptor, arena)
|
262
|
+
yield key_value, value_value
|
263
|
+
end
|
264
|
+
nil
|
265
|
+
end
|
266
|
+
|
267
|
+
private
|
268
|
+
attr :arena, :map_ptr, :key_type, :value_type, :descriptor, :name
|
269
|
+
|
270
|
+
include Google::Protobuf::Internal::Convert
|
271
|
+
|
272
|
+
def internal_deep_freeze
|
273
|
+
freeze
|
274
|
+
if value_type == :message
|
275
|
+
internal_iterator do |iterator|
|
276
|
+
value_message_value = Google::Protobuf::FFI.map_value(@map_ptr, iterator)
|
277
|
+
convert_upb_to_ruby(value_message_value, value_type, descriptor, arena).send :internal_deep_freeze
|
278
|
+
end
|
279
|
+
end
|
280
|
+
self
|
281
|
+
end
|
282
|
+
|
283
|
+
def internal_iterator
|
284
|
+
iter = ::FFI::MemoryPointer.new(:size_t, 1)
|
285
|
+
iter.write(:size_t, Google::Protobuf::FFI::Upb_Map_Begin)
|
286
|
+
while Google::Protobuf::FFI.map_next(@map_ptr, iter) do
|
287
|
+
iter_size_t = iter.read(:size_t)
|
288
|
+
yield iter_size_t
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def each_msg_val &block
|
293
|
+
internal_iterator do |iterator|
|
294
|
+
key_message_value = Google::Protobuf::FFI.map_key(@map_ptr, iterator)
|
295
|
+
value_message_value = Google::Protobuf::FFI.map_value(@map_ptr, iterator)
|
296
|
+
yield key_message_value, value_message_value
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def internal_dup
|
301
|
+
instance = self.class.send(:private_constructor, key_type, value_type, descriptor, arena: arena)
|
302
|
+
new_map_ptr = instance.send(:map_ptr)
|
303
|
+
each_msg_val do |key_message_value, value_message_value|
|
304
|
+
Google::Protobuf::FFI.map_set(new_map_ptr, key_message_value, value_message_value, arena)
|
305
|
+
end
|
306
|
+
instance
|
307
|
+
end
|
308
|
+
|
309
|
+
def internal_merge_into_self(other)
|
310
|
+
case other
|
311
|
+
when Hash
|
312
|
+
other.each do |key, value|
|
313
|
+
key_message_value = convert_ruby_to_upb(key, arena, key_type, nil)
|
314
|
+
value_message_value = convert_ruby_to_upb(value, arena, value_type, descriptor)
|
315
|
+
Google::Protobuf::FFI.map_set(@map_ptr, key_message_value, value_message_value, arena)
|
316
|
+
end
|
317
|
+
when Google::Protobuf::Map
|
318
|
+
unless key_type == other.send(:key_type) and value_type == other.send(:value_type) and descriptor == other.descriptor
|
319
|
+
raise ArgumentError.new "Attempt to merge Map with mismatching types" #TODO Improve error message by adding type information
|
320
|
+
end
|
321
|
+
arena.fuse(other.send(:arena))
|
322
|
+
iter = ::FFI::MemoryPointer.new(:size_t, 1)
|
323
|
+
iter.write(:size_t, Google::Protobuf::FFI::Upb_Map_Begin)
|
324
|
+
other.send(:each_msg_val) do |key_message_value, value_message_value|
|
325
|
+
Google::Protobuf::FFI.map_set(@map_ptr, key_message_value, value_message_value, arena)
|
326
|
+
end
|
327
|
+
else
|
328
|
+
raise ArgumentError.new "Unknown type merging into Map" #TODO improve this error message by including type information
|
329
|
+
end
|
330
|
+
self
|
331
|
+
end
|
332
|
+
|
333
|
+
def internal_merge(other)
|
334
|
+
internal_dup.internal_merge_into_self(other)
|
335
|
+
end
|
336
|
+
|
337
|
+
def initialize(key_type, value_type, value_type_class: nil, initial_values: nil, arena: nil, map: nil, descriptor: nil, name: nil)
|
338
|
+
@name = name || 'Map'
|
339
|
+
|
340
|
+
unless [:int32, :int64, :uint32, :uint64, :bool, :string, :bytes].include? key_type
|
341
|
+
raise ArgumentError.new "Invalid key type for map." #TODO improve error message to include what type was passed
|
342
|
+
end
|
343
|
+
@key_type = key_type
|
344
|
+
|
345
|
+
unless [:int32, :int64, :uint32, :uint64, :bool, :string, :bytes, :enum, :message].include? value_type
|
346
|
+
raise ArgumentError.new "Invalid value type for map." #TODO improve error message to include what type was passed
|
347
|
+
end
|
348
|
+
@value_type = value_type
|
349
|
+
|
350
|
+
if !descriptor.nil?
|
351
|
+
raise ArgumentError "Expected descriptor to be a Descriptor or EnumDescriptor" unless [EnumDescriptor, Descriptor].include? descriptor.class
|
352
|
+
@descriptor = descriptor
|
353
|
+
elsif [:message, :enum].include? value_type
|
354
|
+
raise ArgumentError.new "Expected at least 3 arguments for message/enum." if value_type_class.nil?
|
355
|
+
descriptor = value_type_class.respond_to?(:descriptor) ? value_type_class.descriptor : nil
|
356
|
+
raise ArgumentError.new "Type class #{value_type_class} has no descriptor. Please pass a class or enum as returned by the DescriptorPool." if descriptor.nil?
|
357
|
+
@descriptor = descriptor
|
358
|
+
else
|
359
|
+
@descriptor = nil
|
360
|
+
end
|
361
|
+
|
362
|
+
@arena = arena || Google::Protobuf::FFI.create_arena
|
363
|
+
@map_ptr = map || Google::Protobuf::FFI.create_map(@arena, @key_type, @value_type)
|
364
|
+
|
365
|
+
internal_merge_into_self(initial_values) unless initial_values.nil?
|
366
|
+
|
367
|
+
# Should always be the last expression of the initializer to avoid
|
368
|
+
# leaking references to this object before construction is complete.
|
369
|
+
OBJECT_CACHE.try_add(@map_ptr.address, self)
|
370
|
+
end
|
371
|
+
|
372
|
+
# @param field [FieldDescriptor] Descriptor of the field where the RepeatedField will be assigned
|
373
|
+
# @param values [Hash|Map] Initial value; may be nil or empty
|
374
|
+
# @param arena [Arena] Owning message's arena
|
375
|
+
def self.construct_for_field(field, arena, value: nil, map: nil)
|
376
|
+
raise ArgumentError.new "Expected Hash object as initializer value for map field '#{field.name}' (given #{value.class})." unless value.nil? or value.is_a? Hash
|
377
|
+
instance = allocate
|
378
|
+
raise ArgumentError.new "Expected field with type :message, instead got #{field.class}" unless field.type == :message
|
379
|
+
message_descriptor = field.send(:subtype)
|
380
|
+
key_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 1)
|
381
|
+
key_field_type = Google::Protobuf::FFI.get_type(key_field_def)
|
382
|
+
|
383
|
+
value_field_def = Google::Protobuf::FFI.get_field_by_number(message_descriptor, 2)
|
384
|
+
value_field_type = Google::Protobuf::FFI.get_type(value_field_def)
|
385
|
+
instance.send(:initialize, key_field_type, value_field_type, initial_values: value, name: field.name, arena: arena, map: map, descriptor: value_field_def.subtype)
|
386
|
+
instance
|
387
|
+
end
|
388
|
+
|
389
|
+
def self.private_constructor(key_type, value_type, descriptor, initial_values: nil, arena: nil)
|
390
|
+
instance = allocate
|
391
|
+
instance.send(:initialize, key_type, value_type, descriptor: descriptor, initial_values: initial_values, arena: arena)
|
392
|
+
instance
|
393
|
+
end
|
394
|
+
|
395
|
+
extend Google::Protobuf::Internal::Convert
|
396
|
+
|
397
|
+
def self.deep_copy(map)
|
398
|
+
instance = allocate
|
399
|
+
instance.send(:initialize, map.send(:key_type), map.send(:value_type), descriptor: map.send(:descriptor))
|
400
|
+
map.send(:each_msg_val) do |key_message_value, value_message_value|
|
401
|
+
Google::Protobuf::FFI.map_set(instance.send(:map_ptr), key_message_value, message_value_deep_copy(value_message_value, map.send(:value_type), map.send(:descriptor), instance.send(:arena)), instance.send(:arena))
|
402
|
+
end
|
403
|
+
instance
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|