google-protobuf 3.25.0 → 4.29.2
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/convert.c +46 -18
- data/ext/google/protobuf_c/defs.c +499 -26
- data/ext/google/protobuf_c/extconf.rb +1 -1
- data/ext/google/protobuf_c/glue.c +53 -2
- data/ext/google/protobuf_c/map.c +82 -17
- data/ext/google/protobuf_c/map.h +9 -2
- data/ext/google/protobuf_c/message.c +144 -104
- data/ext/google/protobuf_c/message.h +8 -5
- data/ext/google/protobuf_c/protobuf.c +30 -17
- data/ext/google/protobuf_c/protobuf.h +3 -7
- data/ext/google/protobuf_c/repeated_field.c +64 -10
- data/ext/google/protobuf_c/repeated_field.h +8 -1
- data/ext/google/protobuf_c/ruby-upb.c +13774 -11526
- data/ext/google/protobuf_c/ruby-upb.h +11198 -9048
- data/ext/google/protobuf_c/shared_convert.c +10 -5
- data/ext/google/protobuf_c/shared_convert.h +2 -2
- data/ext/google/protobuf_c/shared_message.c +3 -31
- data/ext/google/protobuf_c/shared_message.h +0 -4
- 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/lib/google/protobuf/any_pb.rb +1 -22
- data/lib/google/protobuf/api_pb.rb +1 -24
- data/lib/google/protobuf/descriptor_pb.rb +3 -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 +13 -2
- data/lib/google/protobuf/ffi/descriptor_pool.rb +16 -9
- data/lib/google/protobuf/ffi/enum_descriptor.rb +13 -1
- data/lib/google/protobuf/ffi/ffi.rb +8 -6
- data/lib/google/protobuf/ffi/field_descriptor.rb +37 -16
- data/lib/google/protobuf/ffi/file_descriptor.rb +13 -12
- data/lib/google/protobuf/ffi/internal/arena.rb +0 -6
- data/lib/google/protobuf/ffi/internal/convert.rb +21 -30
- data/lib/google/protobuf/ffi/map.rb +50 -13
- data/lib/google/protobuf/ffi/message.rb +202 -58
- data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
- data/lib/google/protobuf/ffi/object_cache.rb +3 -3
- data/lib/google/protobuf/ffi/oneof_descriptor.rb +20 -11
- data/lib/google/protobuf/ffi/repeated_field.rb +50 -142
- 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/plugin_pb.rb +2 -24
- data/lib/google/protobuf/repeated_field.rb +4 -5
- 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/wrappers_pb.rb +1 -22
- data/lib/google/protobuf.rb +1 -1
- data/lib/google/protobuf_ffi.rb +3 -2
- data/lib/google/protobuf_native.rb +0 -1
- data/lib/google/tasks/ffi.rake +1 -3
- metadata +25 -12
- 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
- data/lib/google/protobuf/object_cache.rb +0 -97
@@ -44,9 +44,11 @@ static void Message_mark(void* _self) {
|
|
44
44
|
rb_gc_mark(self->arena);
|
45
45
|
}
|
46
46
|
|
47
|
+
static size_t Message_memsize(const void* _self) { return sizeof(Message); }
|
48
|
+
|
47
49
|
static rb_data_type_t Message_type = {
|
48
50
|
"Google::Protobuf::Message",
|
49
|
-
{Message_mark, RUBY_DEFAULT_FREE,
|
51
|
+
{Message_mark, RUBY_DEFAULT_FREE, Message_memsize},
|
50
52
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
51
53
|
};
|
52
54
|
|
@@ -78,11 +80,13 @@ const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) {
|
|
78
80
|
}
|
79
81
|
|
80
82
|
upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
|
81
|
-
|
82
|
-
|
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;
|
83
86
|
}
|
84
87
|
|
85
|
-
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);
|
86
90
|
Message* self = ruby_to_Message(self_);
|
87
91
|
self->msg = msg;
|
88
92
|
RB_OBJ_WRITE(self_, &self->arena, arena);
|
@@ -103,7 +107,7 @@ void Message_CheckClass(VALUE klass) {
|
|
103
107
|
}
|
104
108
|
}
|
105
109
|
|
106
|
-
VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
110
|
+
VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m,
|
107
111
|
VALUE arena) {
|
108
112
|
if (msg == NULL) return Qnil;
|
109
113
|
|
@@ -114,7 +118,6 @@ VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
|
114
118
|
val = Message_alloc(klass);
|
115
119
|
Message_InitPtr(val, msg, arena);
|
116
120
|
}
|
117
|
-
|
118
121
|
return val;
|
119
122
|
}
|
120
123
|
|
@@ -246,7 +249,7 @@ static int extract_method_call(VALUE method_name, Message* self,
|
|
246
249
|
static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
|
247
250
|
int accessor_type) {
|
248
251
|
Message* self = ruby_to_Message(_self);
|
249
|
-
const upb_FieldDef* oneof_field =
|
252
|
+
const upb_FieldDef* oneof_field = upb_Message_WhichOneofByDef(self->msg, o);
|
250
253
|
|
251
254
|
switch (accessor_type) {
|
252
255
|
case METHOD_PRESENCE:
|
@@ -286,13 +289,42 @@ static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
|
|
286
289
|
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
287
290
|
}
|
288
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
|
+
|
289
322
|
VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
290
323
|
Message* self = ruby_to_Message(_self);
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
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);
|
296
328
|
upb_Arena* arena = Arena_get(self->arena);
|
297
329
|
if (upb_FieldDef_IsMap(f)) {
|
298
330
|
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
@@ -305,12 +337,12 @@ VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
|
305
337
|
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
306
338
|
return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
|
307
339
|
} else if (upb_FieldDef_IsSubMessage(f)) {
|
308
|
-
if (!upb_Message_HasFieldByDef(
|
340
|
+
if (!upb_Message_HasFieldByDef(msg, f)) return Qnil;
|
309
341
|
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
310
342
|
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
311
343
|
return Message_GetRubyWrapper(submsg, m, self->arena);
|
312
344
|
} else {
|
313
|
-
upb_MessageValue msgval = upb_Message_GetFieldByDef(
|
345
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
|
314
346
|
return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
|
315
347
|
}
|
316
348
|
}
|
@@ -434,7 +466,6 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
434
466
|
if (argc != 2) {
|
435
467
|
rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
|
436
468
|
}
|
437
|
-
rb_check_frozen(_self);
|
438
469
|
break;
|
439
470
|
default:
|
440
471
|
if (argc != 1) {
|
@@ -488,7 +519,8 @@ static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
488
519
|
k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
|
489
520
|
|
490
521
|
if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
|
491
|
-
upb_MiniTable* t =
|
522
|
+
const upb_MiniTable* t =
|
523
|
+
upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
|
492
524
|
upb_Message* msg = upb_Message_New(t, map_init->arena);
|
493
525
|
Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
|
494
526
|
map_init->arena);
|
@@ -519,7 +551,7 @@ static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
|
|
519
551
|
upb_Arena* arena) {
|
520
552
|
if (info.type == kUpb_CType_Message) {
|
521
553
|
upb_MessageValue msgval;
|
522
|
-
upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
|
554
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
|
523
555
|
upb_Message* msg = upb_Message_New(t, arena);
|
524
556
|
Message_InitFromValue(msg, info.def.msgdef, val, arena);
|
525
557
|
msgval.msg_val = msg;
|
@@ -635,7 +667,7 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
635
667
|
Message* self = ruby_to_Message(_self);
|
636
668
|
VALUE arena_rb = Arena_new();
|
637
669
|
upb_Arena* arena = Arena_get(arena_rb);
|
638
|
-
upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
670
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
639
671
|
upb_Message* msg = upb_Message_New(t, arena);
|
640
672
|
|
641
673
|
Message_InitPtr(_self, msg, arena_rb);
|
@@ -660,28 +692,12 @@ static VALUE Message_dup(VALUE _self) {
|
|
660
692
|
Message* self = ruby_to_Message(_self);
|
661
693
|
VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
|
662
694
|
Message* new_msg_self = ruby_to_Message(new_msg);
|
663
|
-
|
664
|
-
|
665
|
-
// TODO
|
666
|
-
// TODO
|
667
|
-
memcpy((upb_Message*)new_msg_self->msg, self->msg, size);
|
695
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
696
|
+
upb_Message_ShallowCopy((upb_Message*)new_msg_self->msg, self->msg, m);
|
668
697
|
Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
|
669
698
|
return new_msg;
|
670
699
|
}
|
671
700
|
|
672
|
-
// Support function for Message_eq, and also used by other #eq functions.
|
673
|
-
bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
|
674
|
-
const upb_MessageDef* m) {
|
675
|
-
upb_Status status;
|
676
|
-
upb_Status_Clear(&status);
|
677
|
-
bool return_value = shared_Message_Equal(m1, m2, m, &status);
|
678
|
-
if (upb_Status_IsOk(&status)) {
|
679
|
-
return return_value;
|
680
|
-
} else {
|
681
|
-
rb_raise(cParseError, upb_Status_ErrorMessage(&status));
|
682
|
-
}
|
683
|
-
}
|
684
|
-
|
685
701
|
/*
|
686
702
|
* call-seq:
|
687
703
|
* Message.==(other) => boolean
|
@@ -698,7 +714,10 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
|
|
698
714
|
Message* other = ruby_to_Message(_other);
|
699
715
|
assert(self->msgdef == other->msgdef);
|
700
716
|
|
701
|
-
|
717
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
718
|
+
const int options = 0;
|
719
|
+
return upb_Message_IsEqual(self->msg, other->msg, m, options) ? Qtrue
|
720
|
+
: Qfalse;
|
702
721
|
}
|
703
722
|
|
704
723
|
uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
@@ -709,7 +728,8 @@ uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
|
709
728
|
if (upb_Status_IsOk(&status)) {
|
710
729
|
return return_value;
|
711
730
|
} else {
|
712
|
-
rb_raise(cParseError,
|
731
|
+
rb_raise(cParseError, "Message_Hash(): %s",
|
732
|
+
upb_Status_ErrorMessage(&status));
|
713
733
|
}
|
714
734
|
}
|
715
735
|
|
@@ -766,58 +786,34 @@ static VALUE Message_CreateHash(const upb_Message* msg,
|
|
766
786
|
if (!msg) return Qnil;
|
767
787
|
|
768
788
|
VALUE hash = rb_hash_new();
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
// This is unfortunate, we should key behaviors off field attributes (like
|
774
|
-
// whether a field has presence), not proto2 vs. proto3. We should see if we
|
775
|
-
// can change this without breaking users.
|
776
|
-
is_proto2 = upb_MessageDef_Syntax(m) == kUpb_Syntax_Proto2;
|
777
|
-
|
778
|
-
for (int i = 0; i < n; i++) {
|
779
|
-
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
780
|
-
TypeInfo type_info = TypeInfo_get(field);
|
781
|
-
upb_MessageValue msgval;
|
782
|
-
VALUE msg_value;
|
783
|
-
VALUE msg_key;
|
784
|
-
|
785
|
-
if (!is_proto2 && upb_FieldDef_IsSubMessage(field) &&
|
786
|
-
!upb_FieldDef_IsRepeated(field) &&
|
787
|
-
!upb_Message_HasFieldByDef(msg, field)) {
|
788
|
-
// TODO: Legacy behavior, remove when we fix the is_proto2 differences.
|
789
|
-
msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
790
|
-
rb_hash_aset(hash, msg_key, Qnil);
|
791
|
-
continue;
|
792
|
-
}
|
789
|
+
size_t iter = kUpb_Message_Begin;
|
790
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(m));
|
791
|
+
const upb_FieldDef* field;
|
792
|
+
upb_MessageValue val;
|
793
793
|
|
794
|
-
|
795
|
-
if (
|
796
|
-
|
794
|
+
while (upb_Message_Next(msg, m, pool, &field, &val, &iter)) {
|
795
|
+
if (upb_FieldDef_IsExtension(field)) {
|
796
|
+
// TODO: allow extensions once we have decided what naming scheme the
|
797
|
+
// symbol should use. eg. :"[pkg.ext]"
|
797
798
|
continue;
|
798
799
|
}
|
799
800
|
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
// Proto2 omits empty map/repeated filds also.
|
801
|
+
TypeInfo type_info = TypeInfo_get(field);
|
802
|
+
VALUE msg_value;
|
804
803
|
|
805
804
|
if (upb_FieldDef_IsMap(field)) {
|
806
805
|
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
|
807
806
|
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
808
807
|
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
809
808
|
upb_CType key_type = upb_FieldDef_CType(key_f);
|
810
|
-
msg_value = Map_CreateHash(
|
809
|
+
msg_value = Map_CreateHash(val.map_val, key_type, TypeInfo_get(val_f));
|
811
810
|
} else if (upb_FieldDef_IsRepeated(field)) {
|
812
|
-
|
813
|
-
(!msgval.array_val || upb_Array_Size(msgval.array_val) == 0)) {
|
814
|
-
continue;
|
815
|
-
}
|
816
|
-
msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
|
811
|
+
msg_value = RepeatedField_CreateArray(val.array_val, type_info);
|
817
812
|
} else {
|
818
|
-
msg_value = Scalar_CreateHash(
|
813
|
+
msg_value = Scalar_CreateHash(val, type_info);
|
819
814
|
}
|
820
815
|
|
816
|
+
VALUE msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
821
817
|
rb_hash_aset(hash, msg_key, msg_value);
|
822
818
|
}
|
823
819
|
|
@@ -843,19 +839,44 @@ static VALUE Message_to_h(VALUE _self) {
|
|
843
839
|
return Message_CreateHash(self->msg, self->msgdef);
|
844
840
|
}
|
845
841
|
|
842
|
+
/*
|
843
|
+
* call-seq:
|
844
|
+
* Message.frozen? => bool
|
845
|
+
*
|
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.
|
849
|
+
*/
|
850
|
+
VALUE Message_frozen(VALUE _self) {
|
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
|
+
}
|
856
|
+
|
857
|
+
// Lazily freeze the Ruby wrapper.
|
858
|
+
if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
|
859
|
+
return Qtrue;
|
860
|
+
}
|
861
|
+
|
846
862
|
/*
|
847
863
|
* call-seq:
|
848
864
|
* Message.freeze => self
|
849
865
|
*
|
850
|
-
* Freezes the message object. We have to intercept this so we can
|
851
|
-
*
|
866
|
+
* Freezes the message object. We have to intercept this so we can freeze the
|
867
|
+
* underlying representation, not just the Ruby wrapper.
|
852
868
|
*/
|
853
|
-
|
869
|
+
VALUE Message_freeze(VALUE _self) {
|
854
870
|
Message* self = ruby_to_Message(_self);
|
855
|
-
if (
|
856
|
-
|
857
|
-
|
871
|
+
if (RB_OBJ_FROZEN(_self)) {
|
872
|
+
PBRUBY_ASSERT(upb_Message_IsFrozen(self->msg));
|
873
|
+
return _self;
|
858
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);
|
859
880
|
return _self;
|
860
881
|
}
|
861
882
|
|
@@ -911,7 +932,7 @@ static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
|
911
932
|
* MessageClass.decode(data, options) => message
|
912
933
|
*
|
913
934
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
914
|
-
* format) under the
|
935
|
+
* format) under the interpretation given by this message class's definition
|
915
936
|
* and returns a message object with the corresponding field values.
|
916
937
|
* @param options [Hash] options for the decoder
|
917
938
|
* recursion_limit: set to maximum decoding depth for message (default is 64)
|
@@ -942,18 +963,27 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
|
942
963
|
rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
|
943
964
|
}
|
944
965
|
|
966
|
+
return Message_decode_bytes(RSTRING_LEN(data), RSTRING_PTR(data), options,
|
967
|
+
klass, /*freeze*/ false);
|
968
|
+
}
|
969
|
+
|
970
|
+
VALUE Message_decode_bytes(int size, const char* bytes, int options,
|
971
|
+
VALUE klass, bool freeze) {
|
945
972
|
VALUE msg_rb = initialize_rb_class_with_no_args(klass);
|
946
973
|
Message* msg = ruby_to_Message(msg_rb);
|
947
974
|
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
975
|
+
const upb_FileDef* file = upb_MessageDef_File(msg->msgdef);
|
976
|
+
const upb_ExtensionRegistry* extreg =
|
977
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
978
|
+
upb_DecodeStatus status = upb_Decode(bytes, size, (upb_Message*)msg->msg,
|
979
|
+
upb_MessageDef_MiniTable(msg->msgdef),
|
980
|
+
extreg, options, Arena_get(msg->arena));
|
953
981
|
if (status != kUpb_DecodeStatus_Ok) {
|
954
982
|
rb_raise(cParseError, "Error occurred during parsing");
|
955
983
|
}
|
956
|
-
|
984
|
+
if (freeze) {
|
985
|
+
Message_freeze(msg_rb);
|
986
|
+
}
|
957
987
|
return msg_rb;
|
958
988
|
}
|
959
989
|
|
@@ -974,9 +1004,6 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
974
1004
|
int options = 0;
|
975
1005
|
upb_Status status;
|
976
1006
|
|
977
|
-
// TODO: use this message's pool instead.
|
978
|
-
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
979
|
-
|
980
1007
|
if (argc < 1 || argc > 2) {
|
981
1008
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
982
1009
|
}
|
@@ -1010,11 +1037,22 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1010
1037
|
}
|
1011
1038
|
|
1012
1039
|
upb_Status_Clear(&status);
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1040
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
1041
|
+
|
1042
|
+
int result = upb_JsonDecodeDetectingNonconformance(
|
1043
|
+
RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
|
1044
|
+
msg->msgdef, pool, options, Arena_get(msg->arena), &status);
|
1045
|
+
|
1046
|
+
switch (result) {
|
1047
|
+
case kUpb_JsonDecodeResult_Ok:
|
1048
|
+
break;
|
1049
|
+
case kUpb_JsonDecodeResult_OkWithEmptyStringNumerics:
|
1050
|
+
rb_warn("%s", upb_Status_ErrorMessage(&status));
|
1051
|
+
break;
|
1052
|
+
case kUpb_JsonDecodeResult_Error:
|
1053
|
+
rb_raise(cParseError, "Error occurred during parsing: %s",
|
1054
|
+
upb_Status_ErrorMessage(&status));
|
1055
|
+
break;
|
1018
1056
|
}
|
1019
1057
|
|
1020
1058
|
return msg_rb;
|
@@ -1090,9 +1128,6 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1090
1128
|
size_t size;
|
1091
1129
|
upb_Status status;
|
1092
1130
|
|
1093
|
-
// TODO: use this message's pool instead.
|
1094
|
-
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
1095
|
-
|
1096
1131
|
if (argc < 1 || argc > 2) {
|
1097
1132
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
1098
1133
|
}
|
@@ -1127,8 +1162,9 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1127
1162
|
}
|
1128
1163
|
|
1129
1164
|
upb_Status_Clear(&status);
|
1130
|
-
|
1131
|
-
|
1165
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
1166
|
+
size = upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf, sizeof(buf),
|
1167
|
+
&status);
|
1132
1168
|
|
1133
1169
|
if (!upb_Status_IsOk(&status)) {
|
1134
1170
|
rb_raise(cParseError, "Error occurred during encoding: %s",
|
@@ -1138,7 +1174,7 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1138
1174
|
VALUE ret;
|
1139
1175
|
if (size >= sizeof(buf)) {
|
1140
1176
|
char* buf2 = malloc(size + 1);
|
1141
|
-
upb_JsonEncode(msg->msg, msg->msgdef,
|
1177
|
+
upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf2, size + 1,
|
1142
1178
|
&status);
|
1143
1179
|
ret = rb_str_new(buf2, size);
|
1144
1180
|
free(buf2);
|
@@ -1271,9 +1307,12 @@ upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
|
1271
1307
|
upb_Message* new_msg = upb_Message_New(layout, arena);
|
1272
1308
|
char* data;
|
1273
1309
|
|
1310
|
+
const upb_FileDef* file = upb_MessageDef_File(m);
|
1311
|
+
const upb_ExtensionRegistry* extreg =
|
1312
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
1274
1313
|
if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
|
1275
1314
|
kUpb_EncodeStatus_Ok ||
|
1276
|
-
upb_Decode(data, size, new_msg, layout,
|
1315
|
+
upb_Decode(data, size, new_msg, layout, extreg, 0, arena) !=
|
1277
1316
|
kUpb_DecodeStatus_Ok) {
|
1278
1317
|
upb_Arena_Free(tmp_arena);
|
1279
1318
|
rb_raise(cParseError, "Error occurred copying proto");
|
@@ -1361,6 +1400,7 @@ static void Message_define_class(VALUE klass) {
|
|
1361
1400
|
rb_define_method(klass, "==", Message_eq, 1);
|
1362
1401
|
rb_define_method(klass, "eql?", Message_eq, 1);
|
1363
1402
|
rb_define_method(klass, "freeze", Message_freeze, 0);
|
1403
|
+
rb_define_method(klass, "frozen?", Message_frozen, 0);
|
1364
1404
|
rb_define_method(klass, "hash", Message_hash, 0);
|
1365
1405
|
rb_define_method(klass, "to_h", Message_to_h, 0);
|
1366
1406
|
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.
|
@@ -54,10 +54,6 @@ uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
|
54
54
|
upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
55
55
|
upb_Arena* arena);
|
56
56
|
|
57
|
-
// Returns true if these two messages are equal.
|
58
|
-
bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
|
59
|
-
const upb_MessageDef* m);
|
60
|
-
|
61
57
|
// Checks that this Ruby object is a message, and raises an exception if not.
|
62
58
|
void Message_CheckClass(VALUE klass);
|
63
59
|
|
@@ -73,6 +69,13 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc);
|
|
73
69
|
// module.
|
74
70
|
VALUE MessageOrEnum_GetDescriptor(VALUE klass);
|
75
71
|
|
72
|
+
// Decodes a Message from a byte sequence.
|
73
|
+
VALUE Message_decode_bytes(int size, const char* bytes, int options,
|
74
|
+
VALUE klass, bool freeze);
|
75
|
+
|
76
|
+
// Recursively freeze message
|
77
|
+
VALUE Message_freeze(VALUE _self);
|
78
|
+
|
76
79
|
// Call at startup to register all types in this module.
|
77
80
|
void Message_register(VALUE protobuf);
|
78
81
|
|
@@ -7,8 +7,6 @@
|
|
7
7
|
|
8
8
|
#include "protobuf.h"
|
9
9
|
|
10
|
-
#include <ruby/version.h>
|
11
|
-
|
12
10
|
#include "defs.h"
|
13
11
|
#include "map.h"
|
14
12
|
#include "message.h"
|
@@ -164,11 +162,23 @@ static void Arena_free(void *data) {
|
|
164
162
|
xfree(arena);
|
165
163
|
}
|
166
164
|
|
165
|
+
static size_t Arena_memsize(const void *data) {
|
166
|
+
const Arena *arena = data;
|
167
|
+
size_t fused_count;
|
168
|
+
size_t memsize = upb_Arena_SpaceAllocated(arena->arena, &fused_count);
|
169
|
+
if (fused_count > 1) {
|
170
|
+
// If other arena were fused we attribute an equal
|
171
|
+
// share of memory usage to each one.
|
172
|
+
memsize /= fused_count;
|
173
|
+
}
|
174
|
+
return memsize + sizeof(Arena);
|
175
|
+
}
|
176
|
+
|
167
177
|
static VALUE cArena;
|
168
178
|
|
169
179
|
const rb_data_type_t Arena_type = {
|
170
180
|
"Google::Protobuf::Internal::Arena",
|
171
|
-
{Arena_mark, Arena_free,
|
181
|
+
{Arena_mark, Arena_free, Arena_memsize},
|
172
182
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
173
183
|
};
|
174
184
|
|
@@ -209,15 +219,6 @@ void Arena_fuse(VALUE _arena, upb_Arena *other) {
|
|
209
219
|
|
210
220
|
VALUE Arena_new() { return Arena_alloc(cArena); }
|
211
221
|
|
212
|
-
void Arena_Pin(VALUE _arena, VALUE obj) {
|
213
|
-
Arena *arena;
|
214
|
-
TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
|
215
|
-
if (arena->pinned_objs == Qnil) {
|
216
|
-
RB_OBJ_WRITE(_arena, &arena->pinned_objs, rb_ary_new());
|
217
|
-
}
|
218
|
-
rb_ary_push(arena->pinned_objs, obj);
|
219
|
-
}
|
220
|
-
|
221
222
|
void Arena_register(VALUE module) {
|
222
223
|
VALUE internal = rb_define_module_under(module, "Internal");
|
223
224
|
VALUE klass = rb_define_class_under(internal, "Arena", rb_cObject);
|
@@ -241,16 +242,17 @@ static void ObjectCache_Init(VALUE protobuf) {
|
|
241
242
|
item_try_add = rb_intern("try_add");
|
242
243
|
|
243
244
|
rb_gc_register_address(&weak_obj_cache);
|
245
|
+
VALUE internal = rb_const_get(protobuf, rb_intern("Internal"));
|
244
246
|
#if SIZEOF_LONG >= SIZEOF_VALUE
|
245
|
-
VALUE cache_class = rb_const_get(
|
247
|
+
VALUE cache_class = rb_const_get(internal, rb_intern("ObjectCache"));
|
246
248
|
#else
|
247
|
-
VALUE cache_class = rb_const_get(
|
249
|
+
VALUE cache_class = rb_const_get(internal, rb_intern("LegacyObjectCache"));
|
248
250
|
#endif
|
249
251
|
|
250
252
|
weak_obj_cache = rb_class_new_instance(0, NULL, cache_class);
|
251
|
-
rb_const_set(
|
252
|
-
rb_const_set(
|
253
|
-
rb_const_set(
|
253
|
+
rb_const_set(internal, rb_intern("OBJECT_CACHE"), weak_obj_cache);
|
254
|
+
rb_const_set(internal, rb_intern("SIZEOF_LONG"), INT2NUM(SIZEOF_LONG));
|
255
|
+
rb_const_set(internal, rb_intern("SIZEOF_VALUE"), INT2NUM(SIZEOF_VALUE));
|
254
256
|
}
|
255
257
|
|
256
258
|
static VALUE ObjectCache_GetKey(const void *key) {
|
@@ -341,3 +343,14 @@ __attribute__((visibility("default"))) void Init_protobuf_c() {
|
|
341
343
|
rb_define_singleton_method(protobuf, "deep_copy", Google_Protobuf_deep_copy,
|
342
344
|
1);
|
343
345
|
}
|
346
|
+
|
347
|
+
// -----------------------------------------------------------------------------
|
348
|
+
// Utilities
|
349
|
+
// -----------------------------------------------------------------------------
|
350
|
+
|
351
|
+
// Raises a Ruby error if val is frozen in Ruby or UPB.
|
352
|
+
void Protobuf_CheckNotFrozen(VALUE val, bool upb_frozen) {
|
353
|
+
if (RB_UNLIKELY(rb_obj_frozen_p(val)||upb_frozen)) {
|
354
|
+
rb_error_frozen_object(val);
|
355
|
+
}
|
356
|
+
}
|
@@ -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
|