google-protobuf 3.23.3 → 4.27.1
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.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/Rakefile +3 -0
- data/ext/google/protobuf_c/convert.c +28 -72
- data/ext/google/protobuf_c/convert.h +3 -28
- data/ext/google/protobuf_c/defs.c +512 -60
- 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 +72 -0
- data/ext/google/protobuf_c/map.c +28 -36
- data/ext/google/protobuf_c/map.h +6 -28
- data/ext/google/protobuf_c/message.c +88 -143
- data/ext/google/protobuf_c/message.h +10 -32
- data/ext/google/protobuf_c/protobuf.c +49 -175
- data/ext/google/protobuf_c/protobuf.h +24 -32
- data/ext/google/protobuf_c/repeated_field.c +23 -33
- data/ext/google/protobuf_c/repeated_field.h +6 -28
- data/ext/google/protobuf_c/ruby-upb.c +13046 -10690
- data/ext/google/protobuf_c/ruby-upb.h +8405 -5836
- data/ext/google/protobuf_c/shared_convert.c +69 -0
- data/ext/google/protobuf_c/shared_convert.h +26 -0
- data/ext/google/protobuf_c/shared_message.c +37 -0
- data/ext/google/protobuf_c/shared_message.h +21 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +467 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -8
- data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
- data/lib/google/protobuf/any_pb.rb +1 -22
- data/lib/google/protobuf/api_pb.rb +1 -24
- data/lib/google/protobuf/descriptor_pb.rb +14 -23
- data/lib/google/protobuf/duration_pb.rb +1 -22
- data/lib/google/protobuf/empty_pb.rb +1 -22
- data/lib/google/protobuf/ffi/descriptor.rb +166 -0
- data/lib/google/protobuf/ffi/descriptor_pool.rb +77 -0
- data/lib/google/protobuf/ffi/enum_descriptor.rb +173 -0
- data/lib/google/protobuf/ffi/ffi.rb +210 -0
- data/lib/google/protobuf/ffi/field_descriptor.rb +330 -0
- data/lib/google/protobuf/ffi/file_descriptor.rb +49 -0
- data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
- data/lib/google/protobuf/ffi/internal/convert.rb +289 -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 +409 -0
- data/lib/google/protobuf/ffi/message.rb +659 -0
- data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
- data/lib/google/protobuf/ffi/object_cache.rb +30 -0
- data/lib/google/protobuf/ffi/oneof_descriptor.rb +97 -0
- data/lib/google/protobuf/ffi/repeated_field.rb +385 -0
- data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
- data/lib/google/protobuf/field_mask_pb.rb +1 -22
- data/lib/google/protobuf/internal/object_cache.rb +99 -0
- data/lib/google/protobuf/message_exts.rb +3 -26
- data/lib/google/protobuf/plugin_pb.rb +2 -24
- data/lib/google/protobuf/repeated_field.rb +7 -31
- data/lib/google/protobuf/source_context_pb.rb +1 -22
- data/lib/google/protobuf/struct_pb.rb +1 -22
- data/lib/google/protobuf/timestamp_pb.rb +1 -22
- data/lib/google/protobuf/type_pb.rb +1 -24
- data/lib/google/protobuf/well_known_types.rb +5 -34
- data/lib/google/protobuf/wrappers_pb.rb +1 -22
- data/lib/google/protobuf.rb +27 -45
- data/lib/google/protobuf_ffi.rb +51 -0
- data/lib/google/protobuf_native.rb +19 -0
- data/lib/google/tasks/ffi.rake +100 -0
- metadata +89 -8
- data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
- data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
- data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
- data/lib/google/protobuf/descriptor_dsl.rb +0 -465
@@ -1,32 +1,9 @@
|
|
1
1
|
// Protocol Buffers - Google's data interchange format
|
2
2
|
// Copyright 2014 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
|
#include "protobuf.h"
|
32
9
|
|
@@ -187,15 +164,28 @@ static void Arena_free(void *data) {
|
|
187
164
|
xfree(arena);
|
188
165
|
}
|
189
166
|
|
167
|
+
static size_t Arena_memsize(const void *data) {
|
168
|
+
const Arena *arena = data;
|
169
|
+
size_t fused_count;
|
170
|
+
size_t memsize = upb_Arena_SpaceAllocated(arena->arena, &fused_count);
|
171
|
+
if (fused_count > 1) {
|
172
|
+
// If other arena were fused we attribute an equal
|
173
|
+
// share of memory usage to each one.
|
174
|
+
memsize /= fused_count;
|
175
|
+
}
|
176
|
+
return memsize + sizeof(Arena);
|
177
|
+
}
|
178
|
+
|
190
179
|
static VALUE cArena;
|
191
180
|
|
192
181
|
const rb_data_type_t Arena_type = {
|
193
182
|
"Google::Protobuf::Internal::Arena",
|
194
|
-
{Arena_mark, Arena_free,
|
183
|
+
{Arena_mark, Arena_free, Arena_memsize},
|
195
184
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
196
185
|
};
|
197
186
|
|
198
|
-
static void*
|
187
|
+
static void *ruby_upb_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
|
188
|
+
size_t size) {
|
199
189
|
if (size == 0) {
|
200
190
|
xfree(ptr);
|
201
191
|
return NULL;
|
@@ -252,164 +242,49 @@ void Arena_register(VALUE module) {
|
|
252
242
|
// Object Cache
|
253
243
|
// -----------------------------------------------------------------------------
|
254
244
|
|
255
|
-
// A pointer -> Ruby Object cache that keeps references to Ruby wrapper
|
256
|
-
// objects. This allows us to look up any Ruby wrapper object by the address
|
257
|
-
// of the object it is wrapping. That way we can avoid ever creating two
|
258
|
-
// different wrapper objects for the same C object, which saves memory and
|
259
|
-
// preserves object identity.
|
260
|
-
//
|
261
|
-
// We use WeakMap for the cache. For Ruby <2.7 we also need a secondary Hash
|
262
|
-
// to store WeakMap keys because Ruby <2.7 WeakMap doesn't allow non-finalizable
|
263
|
-
// keys.
|
264
|
-
//
|
265
|
-
// We also need the secondary Hash if sizeof(long) < sizeof(VALUE), because this
|
266
|
-
// means it may not be possible to fit a pointer into a Fixnum. Keys are
|
267
|
-
// pointers, and if they fit into a Fixnum, Ruby doesn't collect them, but if
|
268
|
-
// they overflow and require allocating a Bignum, they could get collected
|
269
|
-
// prematurely, thus removing the cache entry. This happens on 64-bit Windows,
|
270
|
-
// on which pointers are 64 bits but longs are 32 bits. In this case, we enable
|
271
|
-
// the secondary Hash to hold the keys and prevent them from being collected.
|
272
|
-
|
273
|
-
#if RUBY_API_VERSION_CODE >= 20700 && SIZEOF_LONG >= SIZEOF_VALUE
|
274
|
-
#define USE_SECONDARY_MAP 0
|
275
|
-
#else
|
276
|
-
#define USE_SECONDARY_MAP 1
|
277
|
-
#endif
|
278
|
-
|
279
|
-
#if USE_SECONDARY_MAP
|
280
|
-
|
281
|
-
// Maps Numeric -> Object. The object is then used as a key into the WeakMap.
|
282
|
-
// This is needed for Ruby <2.7 where a number cannot be a key to WeakMap.
|
283
|
-
// The object is used only for its identity; it does not contain any data.
|
284
|
-
VALUE secondary_map = Qnil;
|
285
|
-
|
286
|
-
// Mutations to the map are under a mutex, because SeconaryMap_MaybeGC()
|
287
|
-
// iterates over the map which cannot happen in parallel with insertions, or
|
288
|
-
// Ruby will throw:
|
289
|
-
// can't add a new key into hash during iteration (RuntimeError)
|
290
|
-
VALUE secondary_map_mutex = Qnil;
|
291
|
-
|
292
|
-
// Lambda that will GC entries from the secondary map that are no longer present
|
293
|
-
// in the primary map.
|
294
|
-
VALUE gc_secondary_map_lambda = Qnil;
|
295
|
-
ID length;
|
296
|
-
|
297
|
-
extern VALUE weak_obj_cache;
|
298
|
-
|
299
|
-
static void SecondaryMap_Init() {
|
300
|
-
rb_gc_register_address(&secondary_map);
|
301
|
-
rb_gc_register_address(&gc_secondary_map_lambda);
|
302
|
-
rb_gc_register_address(&secondary_map_mutex);
|
303
|
-
secondary_map = rb_hash_new();
|
304
|
-
gc_secondary_map_lambda = rb_eval_string(
|
305
|
-
"->(secondary, weak) {\n"
|
306
|
-
" secondary.delete_if { |k, v| !weak.key?(v) }\n"
|
307
|
-
"}\n");
|
308
|
-
secondary_map_mutex = rb_mutex_new();
|
309
|
-
length = rb_intern("length");
|
310
|
-
}
|
311
|
-
|
312
|
-
// The secondary map is a regular Hash, and will never shrink on its own.
|
313
|
-
// The main object cache is a WeakMap that will automatically remove entries
|
314
|
-
// when the target object is no longer reachable, but unless we manually
|
315
|
-
// remove the corresponding entries from the secondary map, it will grow
|
316
|
-
// without bound.
|
317
|
-
//
|
318
|
-
// To avoid this unbounded growth we periodically remove entries from the
|
319
|
-
// secondary map that are no longer present in the WeakMap. The logic of
|
320
|
-
// how often to perform this GC is an artbirary tuning parameter that
|
321
|
-
// represents a straightforward CPU/memory tradeoff.
|
322
|
-
//
|
323
|
-
// Requires: secondary_map_mutex is held.
|
324
|
-
static void SecondaryMap_MaybeGC() {
|
325
|
-
PBRUBY_ASSERT(rb_mutex_locked_p(secondary_map_mutex) == Qtrue);
|
326
|
-
size_t weak_len = NUM2ULL(rb_funcall(weak_obj_cache, length, 0));
|
327
|
-
size_t secondary_len = RHASH_SIZE(secondary_map);
|
328
|
-
if (secondary_len < weak_len) {
|
329
|
-
// Logically this case should not be possible: a valid entry cannot exist in
|
330
|
-
// the weak table unless there is a corresponding entry in the secondary
|
331
|
-
// table. It should *always* be the case that secondary_len >= weak_len.
|
332
|
-
//
|
333
|
-
// However ObjectSpace::WeakMap#length (and therefore weak_len) is
|
334
|
-
// unreliable: it overreports its true length by including non-live objects.
|
335
|
-
// However these non-live objects are not yielded in iteration, so we may
|
336
|
-
// have previously deleted them from the secondary map in a previous
|
337
|
-
// invocation of SecondaryMap_MaybeGC().
|
338
|
-
//
|
339
|
-
// In this case, we can't measure any waste, so we just return.
|
340
|
-
return;
|
341
|
-
}
|
342
|
-
size_t waste = secondary_len - weak_len;
|
343
|
-
// GC if we could remove at least 2000 entries or 20% of the table size
|
344
|
-
// (whichever is greater). Since the cost of the GC pass is O(N), we
|
345
|
-
// want to make sure that we condition this on overall table size, to
|
346
|
-
// avoid O(N^2) CPU costs.
|
347
|
-
size_t threshold = PBRUBY_MAX(secondary_len * 0.2, 2000);
|
348
|
-
if (waste > threshold) {
|
349
|
-
rb_funcall(gc_secondary_map_lambda, rb_intern("call"), 2, secondary_map,
|
350
|
-
weak_obj_cache);
|
351
|
-
}
|
352
|
-
}
|
353
|
-
|
354
|
-
// Requires: secondary_map_mutex is held by this thread iff create == true.
|
355
|
-
static VALUE SecondaryMap_Get(VALUE key, bool create) {
|
356
|
-
PBRUBY_ASSERT(!create || rb_mutex_locked_p(secondary_map_mutex) == Qtrue);
|
357
|
-
VALUE ret = rb_hash_lookup(secondary_map, key);
|
358
|
-
if (ret == Qnil && create) {
|
359
|
-
SecondaryMap_MaybeGC();
|
360
|
-
ret = rb_class_new_instance(0, NULL, rb_cObject);
|
361
|
-
rb_hash_aset(secondary_map, key, ret);
|
362
|
-
}
|
363
|
-
return ret;
|
364
|
-
}
|
365
|
-
|
366
|
-
#endif
|
367
|
-
|
368
|
-
// Requires: secondary_map_mutex is held by this thread iff create == true.
|
369
|
-
static VALUE ObjectCache_GetKey(const void *key, bool create) {
|
370
|
-
VALUE key_val = (VALUE)key;
|
371
|
-
PBRUBY_ASSERT((key_val & 3) == 0);
|
372
|
-
VALUE ret = LL2NUM(key_val >> 2);
|
373
|
-
#if USE_SECONDARY_MAP
|
374
|
-
ret = SecondaryMap_Get(ret, create);
|
375
|
-
#endif
|
376
|
-
return ret;
|
377
|
-
}
|
378
|
-
|
379
245
|
// Public ObjectCache API.
|
380
246
|
|
381
247
|
VALUE weak_obj_cache = Qnil;
|
382
248
|
ID item_get;
|
383
|
-
ID
|
249
|
+
ID item_try_add;
|
250
|
+
|
251
|
+
static void ObjectCache_Init(VALUE protobuf) {
|
252
|
+
item_get = rb_intern("get");
|
253
|
+
item_try_add = rb_intern("try_add");
|
384
254
|
|
385
|
-
static void ObjectCache_Init() {
|
386
255
|
rb_gc_register_address(&weak_obj_cache);
|
387
|
-
VALUE
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
SecondaryMap_Init();
|
256
|
+
VALUE internal = rb_const_get(protobuf, rb_intern("Internal"));
|
257
|
+
#if SIZEOF_LONG >= SIZEOF_VALUE
|
258
|
+
VALUE cache_class = rb_const_get(internal, rb_intern("ObjectCache"));
|
259
|
+
#else
|
260
|
+
VALUE cache_class = rb_const_get(internal, rb_intern("LegacyObjectCache"));
|
393
261
|
#endif
|
262
|
+
|
263
|
+
weak_obj_cache = rb_class_new_instance(0, NULL, cache_class);
|
264
|
+
rb_const_set(internal, rb_intern("OBJECT_CACHE"), weak_obj_cache);
|
265
|
+
rb_const_set(internal, rb_intern("SIZEOF_LONG"), INT2NUM(SIZEOF_LONG));
|
266
|
+
rb_const_set(internal, rb_intern("SIZEOF_VALUE"), INT2NUM(SIZEOF_VALUE));
|
394
267
|
}
|
395
268
|
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
VALUE
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
269
|
+
static VALUE ObjectCache_GetKey(const void *key) {
|
270
|
+
VALUE key_val = (VALUE)key;
|
271
|
+
PBRUBY_ASSERT((key_val & 3) == 0);
|
272
|
+
// Ensure the key can be stored as a Fixnum since 1 bit is needed for
|
273
|
+
// FIXNUM_FLAG and 1 bit is needed for the sign bit.
|
274
|
+
VALUE new_key = LL2NUM(key_val >> 2);
|
275
|
+
PBRUBY_ASSERT(FIXNUM_P(new_key));
|
276
|
+
return new_key;
|
277
|
+
}
|
278
|
+
|
279
|
+
VALUE ObjectCache_TryAdd(const void *key, VALUE val) {
|
280
|
+
VALUE key_val = ObjectCache_GetKey(key);
|
281
|
+
return rb_funcall(weak_obj_cache, item_try_add, 2, key_val, val);
|
407
282
|
}
|
408
283
|
|
409
284
|
// Returns the cached object for this key, if any. Otherwise returns Qnil.
|
410
285
|
VALUE ObjectCache_Get(const void *key) {
|
411
|
-
VALUE
|
412
|
-
return rb_funcall(weak_obj_cache, item_get, 1,
|
286
|
+
VALUE key_val = ObjectCache_GetKey(key);
|
287
|
+
return rb_funcall(weak_obj_cache, item_get, 1, key_val);
|
413
288
|
}
|
414
289
|
|
415
290
|
/*
|
@@ -459,11 +334,10 @@ VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
|
|
459
334
|
// This must be named "Init_protobuf_c" because the Ruby module is named
|
460
335
|
// "protobuf_c" -- the VM looks for this symbol in our .so.
|
461
336
|
__attribute__((visibility("default"))) void Init_protobuf_c() {
|
462
|
-
ObjectCache_Init();
|
463
|
-
|
464
337
|
VALUE google = rb_define_module("Google");
|
465
338
|
VALUE protobuf = rb_define_module_under(google, "Protobuf");
|
466
339
|
|
340
|
+
ObjectCache_Init(protobuf);
|
467
341
|
Arena_register(protobuf);
|
468
342
|
Defs_register(protobuf);
|
469
343
|
RepeatedField_register(protobuf);
|
@@ -1,38 +1,29 @@
|
|
1
1
|
// Protocol Buffers - Google's data interchange format
|
2
2
|
// Copyright 2014 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
|
#ifndef __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
|
32
9
|
#define __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
|
33
10
|
|
11
|
+
// Ruby 3+ defines NDEBUG itself, see: https://bugs.ruby-lang.org/issues/18777
|
12
|
+
#ifdef NDEBUG
|
13
|
+
#include <ruby.h>
|
14
|
+
#else
|
15
|
+
#include <ruby.h>
|
16
|
+
#undef NDEBUG
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#include <ruby/version.h>
|
20
|
+
|
21
|
+
#if RUBY_API_VERSION_CODE < 20700
|
22
|
+
#error Protobuf requires Ruby >= 2.7
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#include <assert.h> // Must be included after the NDEBUG logic above.
|
34
26
|
#include <ruby/encoding.h>
|
35
|
-
#include <ruby/ruby.h>
|
36
27
|
#include <ruby/vm.h>
|
37
28
|
|
38
29
|
#include "defs.h"
|
@@ -76,10 +67,9 @@ void Arena_Pin(VALUE arena, VALUE obj);
|
|
76
67
|
// being collected (though in Ruby <2.7 is it effectively strong, due to
|
77
68
|
// implementation limitations).
|
78
69
|
|
79
|
-
//
|
80
|
-
//
|
81
|
-
|
82
|
-
void ObjectCache_Add(const void* key, VALUE val);
|
70
|
+
// Tries to add a new entry to the cache, returning the newly installed value or
|
71
|
+
// the pre-existing entry.
|
72
|
+
VALUE ObjectCache_TryAdd(const void* key, VALUE val);
|
83
73
|
|
84
74
|
// Returns the cached object for this key, if any. Otherwise returns Qnil.
|
85
75
|
VALUE ObjectCache_Get(const void* key);
|
@@ -110,7 +100,9 @@ extern VALUE cTypeError;
|
|
110
100
|
do { \
|
111
101
|
} while (false && (expr))
|
112
102
|
#else
|
113
|
-
#define PBRUBY_ASSERT(expr)
|
103
|
+
#define PBRUBY_ASSERT(expr) \
|
104
|
+
if (!(expr)) \
|
105
|
+
rb_bug("Assertion failed at %s:%d, expr: %s", __FILE__, __LINE__, #expr)
|
114
106
|
#endif
|
115
107
|
|
116
108
|
#define PBRUBY_MAX(x, y) (((x) > (y)) ? (x) : (y))
|
@@ -1,32 +1,9 @@
|
|
1
1
|
// Protocol Buffers - Google's data interchange format
|
2
2
|
// Copyright 2014 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
|
#include "repeated_field.h"
|
32
9
|
|
@@ -87,7 +64,6 @@ VALUE RepeatedField_GetRubyWrapper(upb_Array* array, TypeInfo type_info,
|
|
87
64
|
if (val == Qnil) {
|
88
65
|
val = RepeatedField_alloc(cRepeatedField);
|
89
66
|
RepeatedField* self;
|
90
|
-
ObjectCache_Add(array, val);
|
91
67
|
TypedData_Get_Struct(val, RepeatedField, &RepeatedField_type, self);
|
92
68
|
self->array = array;
|
93
69
|
self->arena = arena;
|
@@ -95,11 +71,14 @@ VALUE RepeatedField_GetRubyWrapper(upb_Array* array, TypeInfo type_info,
|
|
95
71
|
if (self->type_info.type == kUpb_CType_Message) {
|
96
72
|
self->type_class = Descriptor_DefToClass(type_info.def.msgdef);
|
97
73
|
}
|
74
|
+
val = ObjectCache_TryAdd(array, val);
|
98
75
|
}
|
99
76
|
|
100
77
|
PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.type == type_info.type);
|
101
78
|
PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.def.msgdef ==
|
102
79
|
type_info.def.msgdef);
|
80
|
+
PBRUBY_ASSERT(ruby_to_RepeatedField(val)->array == array);
|
81
|
+
|
103
82
|
return val;
|
104
83
|
}
|
105
84
|
|
@@ -284,7 +263,7 @@ static VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
|
|
284
263
|
memset(&fill, 0, sizeof(fill));
|
285
264
|
for (int i = size; i < index; i++) {
|
286
265
|
// Fill default values.
|
287
|
-
// TODO
|
266
|
+
// TODO: should this happen at the upb level?
|
288
267
|
upb_Array_Set(array, i, fill);
|
289
268
|
}
|
290
269
|
}
|
@@ -499,11 +478,21 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
|
|
499
478
|
* Freezes the repeated field. We have to intercept this so we can pin the Ruby
|
500
479
|
* object into memory so we don't forget it's frozen.
|
501
480
|
*/
|
502
|
-
|
481
|
+
VALUE RepeatedField_freeze(VALUE _self) {
|
503
482
|
RepeatedField* self = ruby_to_RepeatedField(_self);
|
504
|
-
|
505
|
-
|
506
|
-
|
483
|
+
|
484
|
+
if (RB_OBJ_FROZEN(_self)) return _self;
|
485
|
+
Arena_Pin(self->arena, _self);
|
486
|
+
RB_OBJ_FREEZE(_self);
|
487
|
+
|
488
|
+
if (self->type_info.type == kUpb_CType_Message) {
|
489
|
+
int size = upb_Array_Size(self->array);
|
490
|
+
int i;
|
491
|
+
for (i = 0; i < size; i++) {
|
492
|
+
upb_MessageValue msgval = upb_Array_Get(self->array, i);
|
493
|
+
VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
|
494
|
+
Message_freeze(val);
|
495
|
+
}
|
507
496
|
}
|
508
497
|
return _self;
|
509
498
|
}
|
@@ -613,7 +602,8 @@ VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) {
|
|
613
602
|
|
614
603
|
self->type_info = TypeInfo_FromClass(argc, argv, 0, &self->type_class, &ary);
|
615
604
|
self->array = upb_Array_New(arena, self->type_info.type);
|
616
|
-
|
605
|
+
VALUE stored_val = ObjectCache_TryAdd(self->array, _self);
|
606
|
+
PBRUBY_ASSERT(stored_val == _self);
|
617
607
|
|
618
608
|
if (ary != Qnil) {
|
619
609
|
if (!RB_TYPE_P(ary, T_ARRAY)) {
|
@@ -1,38 +1,13 @@
|
|
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
|
#ifndef RUBY_PROTOBUF_REPEATED_FIELD_H_
|
32
9
|
#define RUBY_PROTOBUF_REPEATED_FIELD_H_
|
33
10
|
|
34
|
-
#include <ruby/ruby.h>
|
35
|
-
|
36
11
|
#include "protobuf.h"
|
37
12
|
#include "ruby-upb.h"
|
38
13
|
|
@@ -60,4 +35,7 @@ extern VALUE cRepeatedField;
|
|
60
35
|
// Call at startup to register all types in this module.
|
61
36
|
void RepeatedField_register(VALUE module);
|
62
37
|
|
38
|
+
// Recursively freeze RepeatedField.
|
39
|
+
VALUE RepeatedField_freeze(VALUE _self);
|
40
|
+
|
63
41
|
#endif // RUBY_PROTOBUF_REPEATED_FIELD_H_
|