google-protobuf 3.15.7 → 3.19.0
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/convert.c +4 -5
- data/ext/google/protobuf_c/defs.c +41 -1314
- data/ext/google/protobuf_c/map.c +8 -3
- data/ext/google/protobuf_c/map.h +2 -1
- data/ext/google/protobuf_c/message.c +17 -7
- data/ext/google/protobuf_c/protobuf.c +29 -10
- data/ext/google/protobuf_c/protobuf.h +4 -0
- data/ext/google/protobuf_c/repeated_field.c +5 -3
- data/ext/google/protobuf_c/repeated_field.h +2 -1
- data/ext/google/protobuf_c/ruby-upb.c +1356 -1099
- data/ext/google/protobuf_c/ruby-upb.h +705 -453
- data/lib/google/protobuf/api_pb.rb +1 -0
- data/lib/google/protobuf/descriptor_dsl.rb +458 -0
- data/lib/google/protobuf/descriptor_pb.rb +268 -0
- data/lib/google/protobuf/type_pb.rb +1 -0
- data/lib/google/protobuf/well_known_types.rb +5 -0
- data/lib/google/protobuf.rb +1 -69
- data/tests/basic.rb +36 -0
- data/tests/stress.rb +1 -1
- metadata +6 -19
- data/ext/google/protobuf_c/third_party/wyhash/wyhash.h +0 -145
data/ext/google/protobuf_c/map.c
CHANGED
@@ -167,7 +167,8 @@ VALUE Map_deep_copy(VALUE obj) {
|
|
167
167
|
new_arena_rb);
|
168
168
|
}
|
169
169
|
|
170
|
-
const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef
|
170
|
+
const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
|
171
|
+
upb_arena* arena) {
|
171
172
|
const upb_fielddef* key_field = map_field_key(field);
|
172
173
|
const upb_fielddef* value_field = map_field_value(field);
|
173
174
|
TypeInfo value_type_info = TypeInfo_get(value_field);
|
@@ -189,6 +190,7 @@ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef *field) {
|
|
189
190
|
rb_raise(cTypeError, "Map value type has wrong message/enum class");
|
190
191
|
}
|
191
192
|
|
193
|
+
Arena_fuse(self->arena, arena);
|
192
194
|
return self->map;
|
193
195
|
}
|
194
196
|
|
@@ -236,7 +238,7 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
|
|
236
238
|
upb_msg *self_msg = Map_GetMutable(_self);
|
237
239
|
size_t iter = UPB_MAP_BEGIN;
|
238
240
|
|
239
|
-
|
241
|
+
Arena_fuse(other->arena, arena);
|
240
242
|
|
241
243
|
if (self->key_type != other->key_type ||
|
242
244
|
self->value_type_info.type != other->value_type_info.type ||
|
@@ -511,7 +513,7 @@ static VALUE Map_dup(VALUE _self) {
|
|
511
513
|
upb_arena *arena = Arena_get(new_self->arena);
|
512
514
|
upb_map *new_map = Map_GetMutable(new_map_rb);
|
513
515
|
|
514
|
-
|
516
|
+
Arena_fuse(self->arena, arena);
|
515
517
|
|
516
518
|
while (upb_mapiter_next(self->map, &iter)) {
|
517
519
|
upb_msgval key = upb_mapiter_key(self->map, iter);
|
@@ -678,7 +680,10 @@ void Map_register(VALUE module) {
|
|
678
680
|
rb_define_method(klass, "delete", Map_delete, 1);
|
679
681
|
rb_define_method(klass, "clear", Map_clear, 0);
|
680
682
|
rb_define_method(klass, "length", Map_length, 0);
|
683
|
+
rb_define_method(klass, "size", Map_length, 0);
|
681
684
|
rb_define_method(klass, "dup", Map_dup, 0);
|
685
|
+
// Also define #clone so that we don't inherit Object#clone.
|
686
|
+
rb_define_method(klass, "clone", Map_dup, 0);
|
682
687
|
rb_define_method(klass, "==", Map_eq, 1);
|
683
688
|
rb_define_method(klass, "freeze", Map_freeze, 0);
|
684
689
|
rb_define_method(klass, "hash", Map_hash, 0);
|
data/ext/google/protobuf_c/map.h
CHANGED
@@ -44,7 +44,8 @@ VALUE Map_GetRubyWrapper(upb_map *map, upb_fieldtype_t key_type,
|
|
44
44
|
// Gets the underlying upb_map for this Ruby map object, which must have
|
45
45
|
// key/value type that match |field|. If this is not a map or the type doesn't
|
46
46
|
// match, raises an exception.
|
47
|
-
const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field
|
47
|
+
const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field,
|
48
|
+
upb_arena *arena);
|
48
49
|
|
49
50
|
// Implements #inspect for this map by appending its contents to |b|.
|
50
51
|
void Map_Inspect(StringBuilder *b, const upb_map *map, upb_fieldtype_t key_type,
|
@@ -35,7 +35,6 @@
|
|
35
35
|
#include "map.h"
|
36
36
|
#include "protobuf.h"
|
37
37
|
#include "repeated_field.h"
|
38
|
-
#include "third_party/wyhash/wyhash.h"
|
39
38
|
|
40
39
|
static VALUE cParseError = Qnil;
|
41
40
|
static ID descriptor_instancevar_interned;
|
@@ -277,9 +276,9 @@ static void Message_setfield(upb_msg* msg, const upb_fielddef* f, VALUE val,
|
|
277
276
|
upb_arena* arena) {
|
278
277
|
upb_msgval msgval;
|
279
278
|
if (upb_fielddef_ismap(f)) {
|
280
|
-
msgval.map_val = Map_GetUpbMap(val, f);
|
279
|
+
msgval.map_val = Map_GetUpbMap(val, f, arena);
|
281
280
|
} else if (upb_fielddef_isseq(f)) {
|
282
|
-
msgval.array_val = RepeatedField_GetUpbArray(val, f);
|
281
|
+
msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
|
283
282
|
} else {
|
284
283
|
if (val == Qnil &&
|
285
284
|
(upb_fielddef_issubmsg(f) || upb_fielddef_realcontainingoneof(f))) {
|
@@ -660,7 +659,7 @@ static VALUE Message_dup(VALUE _self) {
|
|
660
659
|
// TODO(copy unknown fields?)
|
661
660
|
// TODO(use official upb msg copy function)
|
662
661
|
memcpy((upb_msg*)new_msg_self->msg, self->msg, size);
|
663
|
-
|
662
|
+
Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
|
664
663
|
return new_msg;
|
665
664
|
}
|
666
665
|
|
@@ -717,7 +716,7 @@ uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) {
|
|
717
716
|
&size);
|
718
717
|
|
719
718
|
if (data) {
|
720
|
-
uint64_t ret =
|
719
|
+
uint64_t ret = Wyhash(data, size, seed, kWyhashSalt);
|
721
720
|
upb_arena_free(arena);
|
722
721
|
return ret;
|
723
722
|
} else {
|
@@ -734,7 +733,10 @@ uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) {
|
|
734
733
|
*/
|
735
734
|
static VALUE Message_hash(VALUE _self) {
|
736
735
|
Message* self = ruby_to_Message(_self);
|
737
|
-
|
736
|
+
uint64_t hash_value = Message_Hash(self->msg, self->msgdef, 0);
|
737
|
+
// RUBY_FIXNUM_MAX should be one less than a power of 2.
|
738
|
+
assert((RUBY_FIXNUM_MAX & (RUBY_FIXNUM_MAX + 1)) == 0);
|
739
|
+
return INT2FIX(hash_value & RUBY_FIXNUM_MAX);
|
738
740
|
}
|
739
741
|
|
740
742
|
/*
|
@@ -791,6 +793,14 @@ static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) {
|
|
791
793
|
VALUE msg_value;
|
792
794
|
VALUE msg_key;
|
793
795
|
|
796
|
+
if (!is_proto2 && upb_fielddef_issubmsg(field) &&
|
797
|
+
!upb_fielddef_isseq(field) && !upb_msg_has(msg, field)) {
|
798
|
+
// TODO: Legacy behavior, remove when we fix the is_proto2 differences.
|
799
|
+
msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
|
800
|
+
rb_hash_aset(hash, msg_key, Qnil);
|
801
|
+
continue;
|
802
|
+
}
|
803
|
+
|
794
804
|
// Do not include fields that are not present (oneof or optional fields).
|
795
805
|
if (is_proto2 && upb_fielddef_haspresence(field) &&
|
796
806
|
!upb_msg_has(msg, field)) {
|
@@ -1303,7 +1313,7 @@ const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
|
|
1303
1313
|
}
|
1304
1314
|
|
1305
1315
|
Message* self = ruby_to_Message(value);
|
1306
|
-
|
1316
|
+
Arena_fuse(self->arena, arena);
|
1307
1317
|
|
1308
1318
|
return self->msg;
|
1309
1319
|
}
|
@@ -37,7 +37,7 @@
|
|
37
37
|
#include "message.h"
|
38
38
|
#include "repeated_field.h"
|
39
39
|
|
40
|
-
VALUE
|
40
|
+
VALUE cParseError;
|
41
41
|
VALUE cTypeError;
|
42
42
|
|
43
43
|
const upb_fielddef* map_field_key(const upb_fielddef* field) {
|
@@ -180,6 +180,7 @@ static void Arena_mark(void *data) {
|
|
180
180
|
static void Arena_free(void *data) {
|
181
181
|
Arena *arena = data;
|
182
182
|
upb_arena_free(arena->arena);
|
183
|
+
xfree(arena);
|
183
184
|
}
|
184
185
|
|
185
186
|
static VALUE cArena;
|
@@ -203,6 +204,16 @@ upb_arena *Arena_get(VALUE _arena) {
|
|
203
204
|
return arena->arena;
|
204
205
|
}
|
205
206
|
|
207
|
+
void Arena_fuse(VALUE _arena, upb_arena *other) {
|
208
|
+
Arena *arena;
|
209
|
+
TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
|
210
|
+
if (!upb_arena_fuse(arena->arena, other)) {
|
211
|
+
rb_raise(rb_eRuntimeError,
|
212
|
+
"Unable to fuse arenas. This should never happen since Ruby does "
|
213
|
+
"not use initial blocks");
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
206
217
|
VALUE Arena_new() {
|
207
218
|
return Arena_alloc(cArena);
|
208
219
|
}
|
@@ -237,8 +248,16 @@ void Arena_register(VALUE module) {
|
|
237
248
|
// We use WeakMap for the cache. For Ruby <2.7 we also need a secondary Hash
|
238
249
|
// to store WeakMap keys because Ruby <2.7 WeakMap doesn't allow non-finalizable
|
239
250
|
// keys.
|
240
|
-
|
241
|
-
|
251
|
+
//
|
252
|
+
// We also need the secondary Hash if sizeof(long) < sizeof(VALUE), because this
|
253
|
+
// means it may not be possible to fit a pointer into a Fixnum. Keys are
|
254
|
+
// pointers, and if they fit into a Fixnum, Ruby doesn't collect them, but if
|
255
|
+
// they overflow and require allocating a Bignum, they could get collected
|
256
|
+
// prematurely, thus removing the cache entry. This happens on 64-bit Windows,
|
257
|
+
// on which pointers are 64 bits but longs are 32 bits. In this case, we enable
|
258
|
+
// the secondary Hash to hold the keys and prevent them from being collected.
|
259
|
+
|
260
|
+
#if RUBY_API_VERSION_CODE >= 20700 && SIZEOF_LONG >= SIZEOF_VALUE
|
242
261
|
#define USE_SECONDARY_MAP 0
|
243
262
|
#else
|
244
263
|
#define USE_SECONDARY_MAP 1
|
@@ -325,7 +344,7 @@ static VALUE SecondaryMap_Get(VALUE key, bool create) {
|
|
325
344
|
VALUE ret = rb_hash_lookup(secondary_map, key);
|
326
345
|
if (ret == Qnil && create) {
|
327
346
|
SecondaryMap_MaybeGC();
|
328
|
-
ret =
|
347
|
+
ret = rb_class_new_instance(0, NULL, rb_cObject);
|
329
348
|
rb_hash_aset(secondary_map, key, ret);
|
330
349
|
}
|
331
350
|
return ret;
|
@@ -335,11 +354,9 @@ static VALUE SecondaryMap_Get(VALUE key, bool create) {
|
|
335
354
|
|
336
355
|
// Requires: secondary_map_mutex is held by this thread iff create == true.
|
337
356
|
static VALUE ObjectCache_GetKey(const void* key, bool create) {
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
PBRUBY_ASSERT((key_int & 3) == 0);
|
342
|
-
VALUE ret = LL2NUM(key_int >> 2);
|
357
|
+
VALUE key_val = (VALUE)key;
|
358
|
+
PBRUBY_ASSERT((key_val & 3) == 0);
|
359
|
+
VALUE ret = LL2NUM(key_val >> 2);
|
343
360
|
#if USE_SECONDARY_MAP
|
344
361
|
ret = SecondaryMap_Get(ret, create);
|
345
362
|
#endif
|
@@ -441,8 +458,10 @@ void Init_protobuf_c() {
|
|
441
458
|
Map_register(protobuf);
|
442
459
|
Message_register(protobuf);
|
443
460
|
|
444
|
-
|
461
|
+
cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
|
462
|
+
rb_gc_register_mark_object(cParseError);
|
445
463
|
cTypeError = rb_const_get(protobuf, rb_intern("TypeError"));
|
464
|
+
rb_gc_register_mark_object(cTypeError);
|
446
465
|
|
447
466
|
rb_define_singleton_method(protobuf, "discard_unknown",
|
448
467
|
Google_Protobuf_discard_unknown, 1);
|
@@ -55,6 +55,10 @@ const upb_fielddef* map_field_value(const upb_fielddef* field);
|
|
55
55
|
VALUE Arena_new();
|
56
56
|
upb_arena *Arena_get(VALUE arena);
|
57
57
|
|
58
|
+
// Fuses this arena to another, throwing a Ruby exception if this is not
|
59
|
+
// possible.
|
60
|
+
void Arena_fuse(VALUE arena, upb_arena *other);
|
61
|
+
|
58
62
|
// Pins this Ruby object to the lifetime of this arena, so that as long as the
|
59
63
|
// arena is alive this object will not be collected.
|
60
64
|
//
|
@@ -34,7 +34,6 @@
|
|
34
34
|
#include "defs.h"
|
35
35
|
#include "message.h"
|
36
36
|
#include "protobuf.h"
|
37
|
-
#include "third_party/wyhash/wyhash.h"
|
38
37
|
|
39
38
|
// -----------------------------------------------------------------------------
|
40
39
|
// Repeated field container type.
|
@@ -149,7 +148,8 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
|
|
149
148
|
return new_rptfield;
|
150
149
|
}
|
151
150
|
|
152
|
-
const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef
|
151
|
+
const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef* field,
|
152
|
+
upb_arena* arena) {
|
153
153
|
RepeatedField* self;
|
154
154
|
TypeInfo type_info = TypeInfo_get(field);
|
155
155
|
|
@@ -167,6 +167,7 @@ const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef *field)
|
|
167
167
|
rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
|
168
168
|
}
|
169
169
|
|
170
|
+
Arena_fuse(self->arena, arena);
|
170
171
|
return self->array;
|
171
172
|
}
|
172
173
|
|
@@ -412,7 +413,7 @@ static VALUE RepeatedField_dup(VALUE _self) {
|
|
412
413
|
int size = upb_array_size(self->array);
|
413
414
|
int i;
|
414
415
|
|
415
|
-
|
416
|
+
Arena_fuse(self->arena, arena);
|
416
417
|
|
417
418
|
for (i = 0; i < size; i++) {
|
418
419
|
upb_msgval msgval = upb_array_get(self->array, i);
|
@@ -550,6 +551,7 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
|
|
550
551
|
RepeatedField* dupped = ruby_to_RepeatedField(dupped_);
|
551
552
|
upb_array *dupped_array = RepeatedField_GetMutable(dupped_);
|
552
553
|
upb_arena* arena = Arena_get(dupped->arena);
|
554
|
+
Arena_fuse(list_rptfield->arena, arena);
|
553
555
|
int size = upb_array_size(list_rptfield->array);
|
554
556
|
int i;
|
555
557
|
|
@@ -44,7 +44,8 @@ VALUE RepeatedField_GetRubyWrapper(upb_array* msg, TypeInfo type_info,
|
|
44
44
|
// Gets the underlying upb_array for this Ruby RepeatedField object, which must
|
45
45
|
// have a type that matches |f|. If this is not a repeated field or the type
|
46
46
|
// doesn't match, raises an exception.
|
47
|
-
const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f
|
47
|
+
const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f,
|
48
|
+
upb_arena* arena);
|
48
49
|
|
49
50
|
// Implements #inspect for this repeated field by appending its contents to |b|.
|
50
51
|
void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,
|