google-protobuf 4.27.5-arm64-darwin → 4.28.0-arm64-darwin
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 +37 -13
- data/ext/google/protobuf_c/map.c +72 -20
- data/ext/google/protobuf_c/map.h +6 -2
- data/ext/google/protobuf_c/message.c +74 -35
- data/ext/google/protobuf_c/message.h +1 -1
- data/ext/google/protobuf_c/protobuf.c +11 -9
- data/ext/google/protobuf_c/protobuf.h +3 -7
- data/ext/google/protobuf_c/repeated_field.c +61 -17
- data/ext/google/protobuf_c/repeated_field.h +5 -1
- data/ext/google/protobuf_c/ruby-upb.c +570 -275
- data/ext/google/protobuf_c/ruby-upb.h +1341 -584
- data/lib/google/3.0/protobuf_c.bundle +0 -0
- data/lib/google/3.1/protobuf_c.bundle +0 -0
- data/lib/google/3.2/protobuf_c.bundle +0 -0
- data/lib/google/3.3/protobuf_c.bundle +0 -0
- data/lib/google/protobuf/descriptor_pb.rb +1 -1
- data/lib/google/protobuf/ffi/descriptor.rb +1 -2
- data/lib/google/protobuf/ffi/internal/arena.rb +0 -6
- data/lib/google/protobuf/ffi/internal/convert.rb +13 -6
- data/lib/google/protobuf/ffi/map.rb +45 -21
- data/lib/google/protobuf/ffi/message.rb +182 -60
- data/lib/google/protobuf/ffi/repeated_field.rb +42 -16
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1063401cc02d9b397e7fb45ac63ad76ad9d68fcee1c0faf150ed5b38df713f61
|
4
|
+
data.tar.gz: f77beee0f039a5a96fbc4dbdb68e535b4cae664e6885c5d2ae5ba7ac4b86e161
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49add2971fc1a9060219f884dc3bb48ac02766cf843680c42fe6cc71141665363f9ebce62a3e171370235bece4afaaf2afef01f34a4f1052b5b94a0348deb472
|
7
|
+
data.tar.gz: fef8d4892bd5ccafd203d98d3588c8a10b315d3f026668821a4a35ee539fcfd3f8076d14c0f1275967a94b7a6aec7bb3b1e6c8965d5ddcf1a0bad54e24dc8924
|
@@ -104,6 +104,41 @@ unknownval:
|
|
104
104
|
rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
|
105
105
|
}
|
106
106
|
|
107
|
+
VALUE Convert_CheckStringUtf8(VALUE str) {
|
108
|
+
VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding());
|
109
|
+
|
110
|
+
if (rb_obj_encoding(str) == utf8) {
|
111
|
+
// Note: Just because a string is marked as having UTF-8 encoding does
|
112
|
+
// not mean that it is *valid* UTF-8. We have to check separately
|
113
|
+
// whether it is valid.
|
114
|
+
if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
|
115
|
+
// TODO: For now
|
116
|
+
// we only warn for this case. We will remove the warning and throw an
|
117
|
+
// exception below in the 30.x release
|
118
|
+
|
119
|
+
rb_warn(
|
120
|
+
"String is invalid UTF-8. This will be an error in a future "
|
121
|
+
"version.");
|
122
|
+
// VALUE exc = rb_const_get_at(
|
123
|
+
// rb_cEncoding, rb_intern("InvalidByteSequenceError"));
|
124
|
+
// rb_raise(exc, "String is invalid UTF-8");
|
125
|
+
}
|
126
|
+
} else {
|
127
|
+
// Note: this will not duplicate underlying string data unless
|
128
|
+
// necessary.
|
129
|
+
//
|
130
|
+
// This will throw an exception if the conversion cannot be performed:
|
131
|
+
// - Encoding::UndefinedConversionError if certain characters cannot be
|
132
|
+
// converted to UTF-8.
|
133
|
+
// - Encoding::InvalidByteSequenceError if certain characters were invalid
|
134
|
+
// in the source encoding.
|
135
|
+
str = rb_str_encode(str, utf8, 0, Qnil);
|
136
|
+
PBRUBY_ASSERT(rb_enc_str_coderange(str) != ENC_CODERANGE_BROKEN);
|
137
|
+
}
|
138
|
+
|
139
|
+
return str;
|
140
|
+
}
|
141
|
+
|
107
142
|
upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name,
|
108
143
|
TypeInfo type_info, upb_Arena* arena) {
|
109
144
|
upb_MessageValue ret;
|
@@ -137,8 +172,7 @@ upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name,
|
|
137
172
|
}
|
138
173
|
break;
|
139
174
|
}
|
140
|
-
case kUpb_CType_String:
|
141
|
-
VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding());
|
175
|
+
case kUpb_CType_String:
|
142
176
|
if (rb_obj_class(value) == rb_cSymbol) {
|
143
177
|
value = rb_funcall(value, rb_intern("to_s"), 0);
|
144
178
|
} else if (!rb_obj_is_kind_of(value, rb_cString)) {
|
@@ -147,19 +181,9 @@ upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name,
|
|
147
181
|
rb_class2name(CLASS_OF(value)));
|
148
182
|
}
|
149
183
|
|
150
|
-
|
151
|
-
// Note: this will not duplicate underlying string data unless
|
152
|
-
// necessary.
|
153
|
-
value = rb_str_encode(value, utf8, 0, Qnil);
|
154
|
-
|
155
|
-
if (rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
|
156
|
-
rb_raise(rb_eEncodingError, "String is invalid UTF-8");
|
157
|
-
}
|
158
|
-
}
|
159
|
-
|
184
|
+
value = Convert_CheckStringUtf8(value);
|
160
185
|
ret.str_val = Convert_StringData(value, arena);
|
161
186
|
break;
|
162
|
-
}
|
163
187
|
case kUpb_CType_Bytes: {
|
164
188
|
VALUE bytes = rb_enc_from_encoding(rb_ascii8bit_encoding());
|
165
189
|
if (rb_obj_class(value) != rb_cString) {
|
data/ext/google/protobuf_c/map.c
CHANGED
@@ -63,9 +63,10 @@ static VALUE Map_alloc(VALUE klass) {
|
|
63
63
|
return TypedData_Wrap_Struct(klass, &Map_type, self);
|
64
64
|
}
|
65
65
|
|
66
|
-
VALUE Map_GetRubyWrapper(upb_Map* map, upb_CType key_type,
|
67
|
-
VALUE arena) {
|
66
|
+
VALUE Map_GetRubyWrapper(const upb_Map* map, upb_CType key_type,
|
67
|
+
TypeInfo value_type, VALUE arena) {
|
68
68
|
PBRUBY_ASSERT(map);
|
69
|
+
PBRUBY_ASSERT(arena != Qnil);
|
69
70
|
|
70
71
|
VALUE val = ObjectCache_Get(map);
|
71
72
|
|
@@ -83,7 +84,6 @@ VALUE Map_GetRubyWrapper(upb_Map* map, upb_CType key_type, TypeInfo value_type,
|
|
83
84
|
}
|
84
85
|
return ObjectCache_TryAdd(map, val);
|
85
86
|
}
|
86
|
-
|
87
87
|
return val;
|
88
88
|
}
|
89
89
|
|
@@ -105,8 +105,9 @@ static TypeInfo Map_keyinfo(Map* self) {
|
|
105
105
|
}
|
106
106
|
|
107
107
|
static upb_Map* Map_GetMutable(VALUE _self) {
|
108
|
-
|
109
|
-
|
108
|
+
const upb_Map* map = ruby_to_Map(_self)->map;
|
109
|
+
Protobuf_CheckNotFrozen(_self, upb_Map_IsFrozen(map));
|
110
|
+
return (upb_Map*)map;
|
110
111
|
}
|
111
112
|
|
112
113
|
VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type,
|
@@ -439,14 +440,14 @@ static VALUE Map_has_key(VALUE _self, VALUE key) {
|
|
439
440
|
* nil if none was present. Throws an exception if the key is of the wrong type.
|
440
441
|
*/
|
441
442
|
static VALUE Map_delete(VALUE _self, VALUE key) {
|
443
|
+
upb_Map* map = Map_GetMutable(_self);
|
442
444
|
Map* self = ruby_to_Map(_self);
|
443
|
-
rb_check_frozen(_self);
|
444
445
|
|
445
446
|
upb_MessageValue key_upb =
|
446
447
|
Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
|
447
448
|
upb_MessageValue val_upb;
|
448
449
|
|
449
|
-
if (upb_Map_Delete(
|
450
|
+
if (upb_Map_Delete(map, key_upb, &val_upb)) {
|
450
451
|
return Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
|
451
452
|
} else {
|
452
453
|
return Qnil;
|
@@ -560,29 +561,79 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
|
|
560
561
|
|
561
562
|
/*
|
562
563
|
* call-seq:
|
563
|
-
*
|
564
|
+
* Map.frozen? => bool
|
565
|
+
*
|
566
|
+
* Returns true if the map is frozen in either Ruby or the underlying
|
567
|
+
* representation. Freezes the Ruby map object if it is not already frozen in
|
568
|
+
* Ruby but it is frozen in the underlying representation.
|
569
|
+
*/
|
570
|
+
VALUE Map_frozen(VALUE _self) {
|
571
|
+
Map* self = ruby_to_Map(_self);
|
572
|
+
if (!upb_Map_IsFrozen(self->map)) {
|
573
|
+
PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
|
574
|
+
return Qfalse;
|
575
|
+
}
|
576
|
+
|
577
|
+
// Lazily freeze the Ruby wrapper.
|
578
|
+
if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
|
579
|
+
return Qtrue;
|
580
|
+
}
|
581
|
+
|
582
|
+
/*
|
583
|
+
* call-seq:
|
584
|
+
* Map.freeze => self
|
564
585
|
*
|
565
|
-
* Freezes the
|
566
|
-
*
|
586
|
+
* Freezes the map object. We have to intercept this so we can freeze the
|
587
|
+
* underlying representation, not just the Ruby wrapper.
|
567
588
|
*/
|
568
589
|
VALUE Map_freeze(VALUE _self) {
|
569
590
|
Map* self = ruby_to_Map(_self);
|
591
|
+
if (RB_OBJ_FROZEN(_self)) {
|
592
|
+
PBRUBY_ASSERT(upb_Map_IsFrozen(self->map));
|
593
|
+
return _self;
|
594
|
+
}
|
595
|
+
|
596
|
+
if (!upb_Map_IsFrozen(self->map)) {
|
597
|
+
if (self->value_type_info.type == kUpb_CType_Message) {
|
598
|
+
upb_Map_Freeze(
|
599
|
+
Map_GetMutable(_self),
|
600
|
+
upb_MessageDef_MiniTable(self->value_type_info.def.msgdef));
|
601
|
+
} else {
|
602
|
+
upb_Map_Freeze(Map_GetMutable(_self), NULL);
|
603
|
+
}
|
604
|
+
}
|
570
605
|
|
571
|
-
if (RB_OBJ_FROZEN(_self)) return _self;
|
572
|
-
Arena_Pin(self->arena, _self);
|
573
606
|
RB_OBJ_FREEZE(_self);
|
574
607
|
|
575
|
-
|
576
|
-
|
577
|
-
|
608
|
+
return _self;
|
609
|
+
}
|
610
|
+
|
611
|
+
VALUE Map_EmptyFrozen(const upb_FieldDef* f) {
|
612
|
+
PBRUBY_ASSERT(upb_FieldDef_IsMap(f));
|
613
|
+
VALUE val = ObjectCache_Get(f);
|
578
614
|
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
615
|
+
if (val == Qnil) {
|
616
|
+
const upb_FieldDef* key_f = map_field_key(f);
|
617
|
+
const upb_FieldDef* val_f = map_field_value(f);
|
618
|
+
upb_CType key_type = upb_FieldDef_CType(key_f);
|
619
|
+
TypeInfo value_type_info = TypeInfo_get(val_f);
|
620
|
+
val = Map_alloc(cMap);
|
621
|
+
Map* self;
|
622
|
+
TypedData_Get_Struct(val, Map, &Map_type, self);
|
623
|
+
self->arena = Arena_new();
|
624
|
+
self->map =
|
625
|
+
upb_Map_New(Arena_get(self->arena), key_type, value_type_info.type);
|
626
|
+
self->key_type = key_type;
|
627
|
+
self->value_type_info = value_type_info;
|
628
|
+
if (self->value_type_info.type == kUpb_CType_Message) {
|
629
|
+
const upb_MessageDef* val_m = value_type_info.def.msgdef;
|
630
|
+
self->value_type_class = Descriptor_DefToClass(val_m);
|
583
631
|
}
|
632
|
+
return ObjectCache_TryAdd(f, Map_freeze(val));
|
584
633
|
}
|
585
|
-
|
634
|
+
PBRUBY_ASSERT(RB_OBJ_FROZEN(val));
|
635
|
+
PBRUBY_ASSERT(upb_Map_IsFrozen(ruby_to_Map(val)->map));
|
636
|
+
return val;
|
586
637
|
}
|
587
638
|
|
588
639
|
/*
|
@@ -671,6 +722,7 @@ void Map_register(VALUE module) {
|
|
671
722
|
rb_define_method(klass, "clone", Map_dup, 0);
|
672
723
|
rb_define_method(klass, "==", Map_eq, 1);
|
673
724
|
rb_define_method(klass, "freeze", Map_freeze, 0);
|
725
|
+
rb_define_method(klass, "frozen?", Map_frozen, 0);
|
674
726
|
rb_define_method(klass, "hash", Map_hash, 0);
|
675
727
|
rb_define_method(klass, "to_h", Map_to_h, 0);
|
676
728
|
rb_define_method(klass, "inspect", Map_inspect, 0);
|
data/ext/google/protobuf_c/map.h
CHANGED
@@ -11,10 +11,14 @@
|
|
11
11
|
#include "protobuf.h"
|
12
12
|
#include "ruby-upb.h"
|
13
13
|
|
14
|
+
// Returns a frozen sentinel Ruby wrapper object for an empty upb_Map with the
|
15
|
+
// key and value types specified by the field. Creates one if it doesn't exist.
|
16
|
+
VALUE Map_EmptyFrozen(const upb_FieldDef* f);
|
17
|
+
|
14
18
|
// Returns a Ruby wrapper object for the given map, which will be created if
|
15
19
|
// one does not exist already.
|
16
|
-
VALUE Map_GetRubyWrapper(upb_Map *map, upb_CType key_type,
|
17
|
-
VALUE arena);
|
20
|
+
VALUE Map_GetRubyWrapper(const upb_Map *map, upb_CType key_type,
|
21
|
+
TypeInfo value_type, VALUE arena);
|
18
22
|
|
19
23
|
// Gets the underlying upb_Map for this Ruby map object, which must have
|
20
24
|
// key/value type that match |field|. If this is not a map or the type doesn't
|
@@ -80,11 +80,13 @@ const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) {
|
|
80
80
|
}
|
81
81
|
|
82
82
|
upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
|
83
|
-
|
84
|
-
|
83
|
+
const upb_Message* upb_msg = Message_Get(msg_rb, m);
|
84
|
+
Protobuf_CheckNotFrozen(msg_rb, upb_Message_IsFrozen(upb_msg));
|
85
|
+
return (upb_Message*)upb_msg;
|
85
86
|
}
|
86
87
|
|
87
|
-
void Message_InitPtr(VALUE self_, upb_Message* msg, VALUE arena) {
|
88
|
+
void Message_InitPtr(VALUE self_, const upb_Message* msg, VALUE arena) {
|
89
|
+
PBRUBY_ASSERT(arena != Qnil);
|
88
90
|
Message* self = ruby_to_Message(self_);
|
89
91
|
self->msg = msg;
|
90
92
|
RB_OBJ_WRITE(self_, &self->arena, arena);
|
@@ -105,7 +107,7 @@ void Message_CheckClass(VALUE klass) {
|
|
105
107
|
}
|
106
108
|
}
|
107
109
|
|
108
|
-
VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
110
|
+
VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m,
|
109
111
|
VALUE arena) {
|
110
112
|
if (msg == NULL) return Qnil;
|
111
113
|
|
@@ -116,7 +118,6 @@ VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
|
116
118
|
val = Message_alloc(klass);
|
117
119
|
Message_InitPtr(val, msg, arena);
|
118
120
|
}
|
119
|
-
|
120
121
|
return val;
|
121
122
|
}
|
122
123
|
|
@@ -248,7 +249,7 @@ static int extract_method_call(VALUE method_name, Message* self,
|
|
248
249
|
static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
|
249
250
|
int accessor_type) {
|
250
251
|
Message* self = ruby_to_Message(_self);
|
251
|
-
const upb_FieldDef* oneof_field =
|
252
|
+
const upb_FieldDef* oneof_field = upb_Message_WhichOneofByDef(self->msg, o);
|
252
253
|
|
253
254
|
switch (accessor_type) {
|
254
255
|
case METHOD_PRESENCE:
|
@@ -288,13 +289,42 @@ static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
|
|
288
289
|
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
289
290
|
}
|
290
291
|
|
292
|
+
VALUE Message_getfield_frozen(const upb_Message* msg, const upb_FieldDef* f,
|
293
|
+
VALUE arena) {
|
294
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
|
295
|
+
if (upb_FieldDef_IsMap(f)) {
|
296
|
+
if (msgval.map_val == NULL) {
|
297
|
+
return Map_EmptyFrozen(f);
|
298
|
+
}
|
299
|
+
const upb_FieldDef* key_f = map_field_key(f);
|
300
|
+
const upb_FieldDef* val_f = map_field_value(f);
|
301
|
+
upb_CType key_type = upb_FieldDef_CType(key_f);
|
302
|
+
TypeInfo value_type_info = TypeInfo_get(val_f);
|
303
|
+
return Map_GetRubyWrapper(msgval.map_val, key_type, value_type_info, arena);
|
304
|
+
}
|
305
|
+
if (upb_FieldDef_IsRepeated(f)) {
|
306
|
+
if (msgval.array_val == NULL) {
|
307
|
+
return RepeatedField_EmptyFrozen(f);
|
308
|
+
}
|
309
|
+
return RepeatedField_GetRubyWrapper(msgval.array_val, TypeInfo_get(f),
|
310
|
+
arena);
|
311
|
+
}
|
312
|
+
VALUE ret;
|
313
|
+
if (upb_FieldDef_IsSubMessage(f)) {
|
314
|
+
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
315
|
+
ret = Message_GetRubyWrapper(msgval.msg_val, m, arena);
|
316
|
+
} else {
|
317
|
+
ret = Convert_UpbToRuby(msgval, TypeInfo_get(f), Qnil);
|
318
|
+
}
|
319
|
+
return ret;
|
320
|
+
}
|
321
|
+
|
291
322
|
VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
292
323
|
Message* self = ruby_to_Message(_self);
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
upb_Message* msg = (upb_Message*)self->msg;
|
324
|
+
if (upb_Message_IsFrozen(self->msg)) {
|
325
|
+
return Message_getfield_frozen(self->msg, f, self->arena);
|
326
|
+
}
|
327
|
+
upb_Message* msg = Message_GetMutable(_self, NULL);
|
298
328
|
upb_Arena* arena = Arena_get(self->arena);
|
299
329
|
if (upb_FieldDef_IsMap(f)) {
|
300
330
|
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
@@ -307,12 +337,12 @@ VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
|
307
337
|
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
308
338
|
return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
|
309
339
|
} else if (upb_FieldDef_IsSubMessage(f)) {
|
310
|
-
if (!upb_Message_HasFieldByDef(
|
340
|
+
if (!upb_Message_HasFieldByDef(msg, f)) return Qnil;
|
311
341
|
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
312
342
|
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
313
343
|
return Message_GetRubyWrapper(submsg, m, self->arena);
|
314
344
|
} else {
|
315
|
-
upb_MessageValue msgval = upb_Message_GetFieldByDef(
|
345
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
|
316
346
|
return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
|
317
347
|
}
|
318
348
|
}
|
@@ -436,7 +466,6 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
436
466
|
if (argc != 2) {
|
437
467
|
rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
|
438
468
|
}
|
439
|
-
rb_check_frozen(_self);
|
440
469
|
break;
|
441
470
|
default:
|
442
471
|
if (argc != 1) {
|
@@ -812,33 +841,42 @@ static VALUE Message_to_h(VALUE _self) {
|
|
812
841
|
|
813
842
|
/*
|
814
843
|
* call-seq:
|
815
|
-
* Message.
|
844
|
+
* Message.frozen? => bool
|
816
845
|
*
|
817
|
-
*
|
818
|
-
* Ruby object
|
846
|
+
* Returns true if the message is frozen in either Ruby or the underlying
|
847
|
+
* representation. Freezes the Ruby message object if it is not already frozen
|
848
|
+
* in Ruby but it is frozen in the underlying representation.
|
819
849
|
*/
|
820
|
-
VALUE
|
850
|
+
VALUE Message_frozen(VALUE _self) {
|
821
851
|
Message* self = ruby_to_Message(_self);
|
852
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
853
|
+
PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
|
854
|
+
return Qfalse;
|
855
|
+
}
|
822
856
|
|
823
|
-
|
824
|
-
|
825
|
-
|
857
|
+
// Lazily freeze the Ruby wrapper.
|
858
|
+
if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
|
859
|
+
return Qtrue;
|
860
|
+
}
|
826
861
|
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
}
|
840
|
-
}
|
862
|
+
/*
|
863
|
+
* call-seq:
|
864
|
+
* Message.freeze => self
|
865
|
+
*
|
866
|
+
* Freezes the message object. We have to intercept this so we can freeze the
|
867
|
+
* underlying representation, not just the Ruby wrapper.
|
868
|
+
*/
|
869
|
+
VALUE Message_freeze(VALUE _self) {
|
870
|
+
Message* self = ruby_to_Message(_self);
|
871
|
+
if (RB_OBJ_FROZEN(_self)) {
|
872
|
+
PBRUBY_ASSERT(upb_Message_IsFrozen(self->msg));
|
873
|
+
return _self;
|
841
874
|
}
|
875
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
876
|
+
upb_Message_Freeze(Message_GetMutable(_self, NULL),
|
877
|
+
upb_MessageDef_MiniTable(self->msgdef));
|
878
|
+
}
|
879
|
+
RB_OBJ_FREEZE(_self);
|
842
880
|
return _self;
|
843
881
|
}
|
844
882
|
|
@@ -1352,6 +1390,7 @@ static void Message_define_class(VALUE klass) {
|
|
1352
1390
|
rb_define_method(klass, "==", Message_eq, 1);
|
1353
1391
|
rb_define_method(klass, "eql?", Message_eq, 1);
|
1354
1392
|
rb_define_method(klass, "freeze", Message_freeze, 0);
|
1393
|
+
rb_define_method(klass, "frozen?", Message_frozen, 0);
|
1355
1394
|
rb_define_method(klass, "hash", Message_hash, 0);
|
1356
1395
|
rb_define_method(klass, "to_h", Message_to_h, 0);
|
1357
1396
|
rb_define_method(klass, "inspect", Message_inspect, 0);
|
@@ -36,7 +36,7 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
36
36
|
|
37
37
|
// Gets or constructs a Ruby wrapper object for the given message. The wrapper
|
38
38
|
// object will reference |arena| and ensure that it outlives this object.
|
39
|
-
VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
39
|
+
VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m,
|
40
40
|
VALUE arena);
|
41
41
|
|
42
42
|
// Gets the given field from this message.
|
@@ -221,15 +221,6 @@ void Arena_fuse(VALUE _arena, upb_Arena *other) {
|
|
221
221
|
|
222
222
|
VALUE Arena_new() { return Arena_alloc(cArena); }
|
223
223
|
|
224
|
-
void Arena_Pin(VALUE _arena, VALUE obj) {
|
225
|
-
Arena *arena;
|
226
|
-
TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
|
227
|
-
if (arena->pinned_objs == Qnil) {
|
228
|
-
RB_OBJ_WRITE(_arena, &arena->pinned_objs, rb_ary_new());
|
229
|
-
}
|
230
|
-
rb_ary_push(arena->pinned_objs, obj);
|
231
|
-
}
|
232
|
-
|
233
224
|
void Arena_register(VALUE module) {
|
234
225
|
VALUE internal = rb_define_module_under(module, "Internal");
|
235
226
|
VALUE klass = rb_define_class_under(internal, "Arena", rb_cObject);
|
@@ -354,3 +345,14 @@ __attribute__((visibility("default"))) void Init_protobuf_c() {
|
|
354
345
|
rb_define_singleton_method(protobuf, "deep_copy", Google_Protobuf_deep_copy,
|
355
346
|
1);
|
356
347
|
}
|
348
|
+
|
349
|
+
// -----------------------------------------------------------------------------
|
350
|
+
// Utilities
|
351
|
+
// -----------------------------------------------------------------------------
|
352
|
+
|
353
|
+
// Raises a Ruby error if val is frozen in Ruby or UPB.
|
354
|
+
void Protobuf_CheckNotFrozen(VALUE val, bool upb_frozen) {
|
355
|
+
if (RB_UNLIKELY(rb_obj_frozen_p(val)||upb_frozen)) {
|
356
|
+
rb_error_frozen_object(val);
|
357
|
+
}
|
358
|
+
}
|
@@ -50,13 +50,6 @@ upb_Arena* Arena_get(VALUE arena);
|
|
50
50
|
// possible.
|
51
51
|
void Arena_fuse(VALUE arena, upb_Arena* other);
|
52
52
|
|
53
|
-
// Pins this Ruby object to the lifetime of this arena, so that as long as the
|
54
|
-
// arena is alive this object will not be collected.
|
55
|
-
//
|
56
|
-
// We use this to guarantee that the "frozen" bit on the object will be
|
57
|
-
// remembered, even if the user drops their reference to this precise object.
|
58
|
-
void Arena_Pin(VALUE arena, VALUE obj);
|
59
|
-
|
60
53
|
// -----------------------------------------------------------------------------
|
61
54
|
// ObjectCache
|
62
55
|
// -----------------------------------------------------------------------------
|
@@ -105,6 +98,9 @@ extern VALUE cTypeError;
|
|
105
98
|
rb_bug("Assertion failed at %s:%d, expr: %s", __FILE__, __LINE__, #expr)
|
106
99
|
#endif
|
107
100
|
|
101
|
+
// Raises a Ruby error if val is frozen in Ruby or upb_frozen is true.
|
102
|
+
void Protobuf_CheckNotFrozen(VALUE val, bool upb_frozen);
|
103
|
+
|
108
104
|
#define PBRUBY_MAX(x, y) (((x) > (y)) ? (x) : (y))
|
109
105
|
|
110
106
|
#define UPB_UNUSED(var) (void)var
|
@@ -44,8 +44,9 @@ static RepeatedField* ruby_to_RepeatedField(VALUE _self) {
|
|
44
44
|
}
|
45
45
|
|
46
46
|
static upb_Array* RepeatedField_GetMutable(VALUE _self) {
|
47
|
-
|
48
|
-
|
47
|
+
const upb_Array* array = ruby_to_RepeatedField(_self)->array;
|
48
|
+
Protobuf_CheckNotFrozen(_self, upb_Array_IsFrozen(array));
|
49
|
+
return (upb_Array*)array;
|
49
50
|
}
|
50
51
|
|
51
52
|
VALUE RepeatedField_alloc(VALUE klass) {
|
@@ -56,9 +57,32 @@ VALUE RepeatedField_alloc(VALUE klass) {
|
|
56
57
|
return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
|
57
58
|
}
|
58
59
|
|
59
|
-
VALUE
|
60
|
+
VALUE RepeatedField_EmptyFrozen(const upb_FieldDef* f) {
|
61
|
+
PBRUBY_ASSERT(upb_FieldDef_IsRepeated(f));
|
62
|
+
VALUE val = ObjectCache_Get(f);
|
63
|
+
|
64
|
+
if (val == Qnil) {
|
65
|
+
val = RepeatedField_alloc(cRepeatedField);
|
66
|
+
RepeatedField* self;
|
67
|
+
TypedData_Get_Struct(val, RepeatedField, &RepeatedField_type, self);
|
68
|
+
self->arena = Arena_new();
|
69
|
+
TypeInfo type_info = TypeInfo_get(f);
|
70
|
+
self->array = upb_Array_New(Arena_get(self->arena), type_info.type);
|
71
|
+
self->type_info = type_info;
|
72
|
+
if (self->type_info.type == kUpb_CType_Message) {
|
73
|
+
self->type_class = Descriptor_DefToClass(type_info.def.msgdef);
|
74
|
+
}
|
75
|
+
val = ObjectCache_TryAdd(f, RepeatedField_freeze(val));
|
76
|
+
}
|
77
|
+
PBRUBY_ASSERT(RB_OBJ_FROZEN(val));
|
78
|
+
PBRUBY_ASSERT(upb_Array_IsFrozen(ruby_to_RepeatedField(val)->array));
|
79
|
+
return val;
|
80
|
+
}
|
81
|
+
|
82
|
+
VALUE RepeatedField_GetRubyWrapper(const upb_Array* array, TypeInfo type_info,
|
60
83
|
VALUE arena) {
|
61
84
|
PBRUBY_ASSERT(array);
|
85
|
+
PBRUBY_ASSERT(arena != Qnil);
|
62
86
|
VALUE val = ObjectCache_Get(array);
|
63
87
|
|
64
88
|
if (val == Qnil) {
|
@@ -78,7 +102,6 @@ VALUE RepeatedField_GetRubyWrapper(upb_Array* array, TypeInfo type_info,
|
|
78
102
|
PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.def.msgdef ==
|
79
103
|
type_info.def.msgdef);
|
80
104
|
PBRUBY_ASSERT(ruby_to_RepeatedField(val)->array == array);
|
81
|
-
|
82
105
|
return val;
|
83
106
|
}
|
84
107
|
|
@@ -471,29 +494,49 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
|
|
471
494
|
return Qtrue;
|
472
495
|
}
|
473
496
|
|
497
|
+
/*
|
498
|
+
* call-seq:
|
499
|
+
* RepeatedField.frozen? => bool
|
500
|
+
*
|
501
|
+
* Returns true if the repeated field is frozen in either Ruby or the underlying
|
502
|
+
* representation. Freezes the Ruby repeated field object if it is not already
|
503
|
+
* frozen in Ruby but it is frozen in the underlying representation.
|
504
|
+
*/
|
505
|
+
VALUE RepeatedField_frozen(VALUE _self) {
|
506
|
+
RepeatedField* self = ruby_to_RepeatedField(_self);
|
507
|
+
if (!upb_Array_IsFrozen(self->array)) {
|
508
|
+
PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
|
509
|
+
return Qfalse;
|
510
|
+
}
|
511
|
+
|
512
|
+
// Lazily freeze the Ruby wrapper.
|
513
|
+
if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
|
514
|
+
return Qtrue;
|
515
|
+
}
|
516
|
+
|
474
517
|
/*
|
475
518
|
* call-seq:
|
476
519
|
* RepeatedField.freeze => self
|
477
520
|
*
|
478
|
-
* Freezes the repeated field. We have to intercept this so we can
|
479
|
-
*
|
521
|
+
* Freezes the repeated field object. We have to intercept this so we can freeze
|
522
|
+
* the underlying representation, not just the Ruby wrapper.
|
480
523
|
*/
|
481
524
|
VALUE RepeatedField_freeze(VALUE _self) {
|
482
525
|
RepeatedField* self = ruby_to_RepeatedField(_self);
|
526
|
+
if (RB_OBJ_FROZEN(_self)) {
|
527
|
+
PBRUBY_ASSERT(upb_Array_IsFrozen(self->array));
|
528
|
+
return _self;
|
529
|
+
}
|
483
530
|
|
484
|
-
if (
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
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);
|
531
|
+
if (!upb_Array_IsFrozen(self->array)) {
|
532
|
+
if (self->type_info.type == kUpb_CType_Message) {
|
533
|
+
upb_Array_Freeze(RepeatedField_GetMutable(_self),
|
534
|
+
upb_MessageDef_MiniTable(self->type_info.def.msgdef));
|
535
|
+
} else {
|
536
|
+
upb_Array_Freeze(RepeatedField_GetMutable(_self), NULL);
|
495
537
|
}
|
496
538
|
}
|
539
|
+
RB_OBJ_FREEZE(_self);
|
497
540
|
return _self;
|
498
541
|
}
|
499
542
|
|
@@ -640,6 +683,7 @@ void RepeatedField_register(VALUE module) {
|
|
640
683
|
rb_define_method(klass, "==", RepeatedField_eq, 1);
|
641
684
|
rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
|
642
685
|
rb_define_method(klass, "freeze", RepeatedField_freeze, 0);
|
686
|
+
rb_define_method(klass, "frozen?", RepeatedField_frozen, 0);
|
643
687
|
rb_define_method(klass, "hash", RepeatedField_hash, 0);
|
644
688
|
rb_define_method(klass, "+", RepeatedField_plus, 1);
|
645
689
|
rb_define_method(klass, "concat", RepeatedField_concat, 1);
|
@@ -11,9 +11,13 @@
|
|
11
11
|
#include "protobuf.h"
|
12
12
|
#include "ruby-upb.h"
|
13
13
|
|
14
|
+
// Returns a frozen sentinel Ruby wrapper object for an empty upb_Array of the
|
15
|
+
// type specified by the field. Creates one if it doesn't exist.
|
16
|
+
VALUE RepeatedField_EmptyFrozen(const upb_FieldDef* f);
|
17
|
+
|
14
18
|
// Returns a Ruby wrapper object for the given upb_Array, which will be created
|
15
19
|
// if one does not exist already.
|
16
|
-
VALUE RepeatedField_GetRubyWrapper(upb_Array* msg, TypeInfo type_info,
|
20
|
+
VALUE RepeatedField_GetRubyWrapper(const upb_Array* msg, TypeInfo type_info,
|
17
21
|
VALUE arena);
|
18
22
|
|
19
23
|
// Gets the underlying upb_Array for this Ruby RepeatedField object, which must
|