google-protobuf 3.15.7 → 3.19.0
Sign up to get free protection for your applications and to get access to all the features.
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,
|