google-protobuf 3.6.1 → 3.9.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/defs.c +553 -70
- data/ext/google/protobuf_c/encode_decode.c +281 -66
- data/ext/google/protobuf_c/extconf.rb +5 -1
- data/ext/google/protobuf_c/map.c +8 -3
- data/ext/google/protobuf_c/message.c +253 -72
- data/ext/google/protobuf_c/protobuf.c +4 -0
- data/ext/google/protobuf_c/protobuf.h +67 -5
- data/ext/google/protobuf_c/repeated_field.c +9 -3
- data/ext/google/protobuf_c/storage.c +265 -115
- data/ext/google/protobuf_c/upb.c +4329 -1745
- data/ext/google/protobuf_c/upb.h +2190 -518
- data/ext/google/protobuf_c/wrap_memcpy.c +1 -1
- data/lib/google/protobuf.rb +3 -2
- data/lib/google/protobuf/any_pb.rb +5 -3
- data/lib/google/protobuf/api_pb.rb +23 -21
- data/lib/google/protobuf/duration_pb.rb +5 -3
- data/lib/google/protobuf/empty_pb.rb +3 -1
- data/lib/google/protobuf/field_mask_pb.rb +4 -2
- data/lib/google/protobuf/repeated_field.rb +1 -1
- data/lib/google/protobuf/source_context_pb.rb +4 -2
- data/lib/google/protobuf/struct_pb.rb +19 -17
- data/lib/google/protobuf/timestamp_pb.rb +5 -3
- data/lib/google/protobuf/type_pb.rb +68 -66
- data/lib/google/protobuf/well_known_types.rb +12 -0
- data/lib/google/protobuf/wrappers_pb.rb +28 -26
- data/tests/basic.rb +174 -1192
- data/tests/generated_code_test.rb +5 -3
- metadata +4 -5
@@ -100,24 +100,34 @@ void stringsink_uninit(stringsink *sink) {
|
|
100
100
|
|
101
101
|
#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
103
|
+
typedef struct {
|
104
|
+
size_t ofs;
|
105
|
+
int32_t hasbit;
|
106
|
+
} field_handlerdata_t;
|
107
|
+
|
108
|
+
// Creates a handlerdata that contains the offset and the hasbit for the field
|
109
|
+
static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit) {
|
110
|
+
field_handlerdata_t *hd = ALLOC(field_handlerdata_t);
|
111
|
+
hd->ofs = ofs;
|
112
|
+
hd->hasbit = hasbit;
|
113
|
+
upb_handlers_addcleanup(h, hd, xfree);
|
114
|
+
return hd;
|
109
115
|
}
|
110
116
|
|
111
117
|
typedef struct {
|
112
118
|
size_t ofs;
|
119
|
+
int32_t hasbit;
|
113
120
|
const upb_msgdef *md;
|
114
121
|
} submsg_handlerdata_t;
|
115
122
|
|
116
123
|
// Creates a handlerdata that contains offset and submessage type information.
|
117
|
-
static const void *newsubmsghandlerdata(upb_handlers* h,
|
124
|
+
static const void *newsubmsghandlerdata(upb_handlers* h,
|
125
|
+
uint32_t ofs,
|
126
|
+
int32_t hasbit,
|
118
127
|
const upb_fielddef* f) {
|
119
128
|
submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
|
120
129
|
hd->ofs = ofs;
|
130
|
+
hd->hasbit = hasbit;
|
121
131
|
hd->md = upb_fielddef_msgsubdef(f);
|
122
132
|
upb_handlers_addcleanup(h, hd, xfree);
|
123
133
|
return hd;
|
@@ -189,6 +199,13 @@ static void* appendstr_handler(void *closure,
|
|
189
199
|
return (void*)str;
|
190
200
|
}
|
191
201
|
|
202
|
+
static void set_hasbit(void *closure, int32_t hasbit) {
|
203
|
+
if (hasbit > 0) {
|
204
|
+
uint8_t* storage = closure;
|
205
|
+
storage[hasbit/8] |= 1 << (hasbit % 8);
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
192
209
|
// Appends a 'bytes' string to a repeated field.
|
193
210
|
static void* appendbytes_handler(void *closure,
|
194
211
|
const void *hd,
|
@@ -205,10 +222,12 @@ static void* str_handler(void *closure,
|
|
205
222
|
const void *hd,
|
206
223
|
size_t size_hint) {
|
207
224
|
MessageHeader* msg = closure;
|
208
|
-
const
|
225
|
+
const field_handlerdata_t *fieldhandler = hd;
|
226
|
+
|
209
227
|
VALUE str = rb_str_new2("");
|
210
228
|
rb_enc_associate(str, kRubyStringUtf8Encoding);
|
211
|
-
DEREF(msg,
|
229
|
+
DEREF(msg, fieldhandler->ofs, VALUE) = str;
|
230
|
+
set_hasbit(closure, fieldhandler->hasbit);
|
212
231
|
return (void*)str;
|
213
232
|
}
|
214
233
|
|
@@ -217,10 +236,12 @@ static void* bytes_handler(void *closure,
|
|
217
236
|
const void *hd,
|
218
237
|
size_t size_hint) {
|
219
238
|
MessageHeader* msg = closure;
|
220
|
-
const
|
239
|
+
const field_handlerdata_t *fieldhandler = hd;
|
240
|
+
|
221
241
|
VALUE str = rb_str_new2("");
|
222
242
|
rb_enc_associate(str, kRubyString8bitEncoding);
|
223
|
-
DEREF(msg,
|
243
|
+
DEREF(msg, fieldhandler->ofs, VALUE) = str;
|
244
|
+
set_hasbit(closure, fieldhandler->hasbit);
|
224
245
|
return (void*)str;
|
225
246
|
}
|
226
247
|
|
@@ -233,18 +254,13 @@ static size_t stringdata_handler(void* closure, const void* hd,
|
|
233
254
|
}
|
234
255
|
|
235
256
|
static bool stringdata_end_handler(void* closure, const void* hd) {
|
236
|
-
|
237
|
-
const size_t *ofs = hd;
|
238
|
-
VALUE rb_str = DEREF(msg, *ofs, VALUE);
|
257
|
+
VALUE rb_str = closure;
|
239
258
|
rb_obj_freeze(rb_str);
|
240
259
|
return true;
|
241
260
|
}
|
242
261
|
|
243
262
|
static bool appendstring_end_handler(void* closure, const void* hd) {
|
244
|
-
VALUE
|
245
|
-
int size = RepeatedField_size(ary);
|
246
|
-
VALUE* last = RepeatedField_index_native(ary, size - 1);
|
247
|
-
VALUE rb_str = *last;
|
263
|
+
VALUE rb_str = closure;
|
248
264
|
rb_obj_freeze(rb_str);
|
249
265
|
return true;
|
250
266
|
}
|
@@ -280,8 +296,11 @@ static void *submsg_handler(void *closure, const void *hd) {
|
|
280
296
|
rb_class_new_instance(0, NULL, subklass);
|
281
297
|
}
|
282
298
|
|
299
|
+
set_hasbit(closure, submsgdata->hasbit);
|
300
|
+
|
283
301
|
submsg_rb = DEREF(msg, submsgdata->ofs, VALUE);
|
284
302
|
TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
|
303
|
+
|
285
304
|
return submsg;
|
286
305
|
}
|
287
306
|
|
@@ -370,6 +389,9 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
|
|
370
389
|
if (mapdata->value_field_type == UPB_TYPE_MESSAGE ||
|
371
390
|
mapdata->value_field_type == UPB_TYPE_ENUM) {
|
372
391
|
value_field_typeclass = get_def_obj(mapdata->value_field_subdef);
|
392
|
+
if (mapdata->value_field_type == UPB_TYPE_ENUM) {
|
393
|
+
value_field_typeclass = EnumDescriptor_enummodule(value_field_typeclass);
|
394
|
+
}
|
373
395
|
}
|
374
396
|
|
375
397
|
value = native_slot_get(
|
@@ -457,9 +479,8 @@ static void *oneofbytes_handler(void *closure,
|
|
457
479
|
}
|
458
480
|
|
459
481
|
static bool oneofstring_end_handler(void* closure, const void* hd) {
|
460
|
-
|
461
|
-
|
462
|
-
rb_obj_freeze(DEREF(msg, oneofdata->ofs, VALUE));
|
482
|
+
VALUE rb_str = rb_str_new2("");
|
483
|
+
rb_obj_freeze(rb_str);
|
463
484
|
return true;
|
464
485
|
}
|
465
486
|
|
@@ -500,7 +521,7 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|
500
521
|
const upb_fielddef *f,
|
501
522
|
size_t offset) {
|
502
523
|
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
503
|
-
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
|
524
|
+
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset, -1));
|
504
525
|
upb_handlers_setstartseq(h, f, startseq_handler, &attr);
|
505
526
|
upb_handlerattr_uninit(&attr);
|
506
527
|
|
@@ -534,7 +555,7 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|
534
555
|
}
|
535
556
|
case UPB_TYPE_MESSAGE: {
|
536
557
|
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
537
|
-
upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f));
|
558
|
+
upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, -1, f));
|
538
559
|
upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
|
539
560
|
upb_handlerattr_uninit(&attr);
|
540
561
|
break;
|
@@ -545,7 +566,15 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|
545
566
|
// Set up handlers for a singular field.
|
546
567
|
static void add_handlers_for_singular_field(upb_handlers *h,
|
547
568
|
const upb_fielddef *f,
|
548
|
-
size_t offset
|
569
|
+
size_t offset,
|
570
|
+
size_t hasbit_off) {
|
571
|
+
// The offset we pass to UPB points to the start of the Message,
|
572
|
+
// rather than the start of where our data is stored.
|
573
|
+
int32_t hasbit = -1;
|
574
|
+
if (hasbit_off != MESSAGE_FIELD_NO_HASBIT) {
|
575
|
+
hasbit = hasbit_off + sizeof(MessageHeader) * 8;
|
576
|
+
}
|
577
|
+
|
549
578
|
switch (upb_fielddef_type(f)) {
|
550
579
|
case UPB_TYPE_BOOL:
|
551
580
|
case UPB_TYPE_INT32:
|
@@ -555,13 +584,13 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|
555
584
|
case UPB_TYPE_INT64:
|
556
585
|
case UPB_TYPE_UINT64:
|
557
586
|
case UPB_TYPE_DOUBLE:
|
558
|
-
upb_msg_setscalarhandler(h, f, offset,
|
587
|
+
upb_msg_setscalarhandler(h, f, offset, hasbit);
|
559
588
|
break;
|
560
589
|
case UPB_TYPE_STRING:
|
561
590
|
case UPB_TYPE_BYTES: {
|
562
591
|
bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
|
563
592
|
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
564
|
-
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
|
593
|
+
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset, hasbit));
|
565
594
|
upb_handlers_setstartstr(h, f,
|
566
595
|
is_bytes ? bytes_handler : str_handler,
|
567
596
|
&attr);
|
@@ -572,7 +601,9 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|
572
601
|
}
|
573
602
|
case UPB_TYPE_MESSAGE: {
|
574
603
|
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
575
|
-
upb_handlerattr_sethandlerdata(&attr,
|
604
|
+
upb_handlerattr_sethandlerdata(&attr,
|
605
|
+
newsubmsghandlerdata(h, offset,
|
606
|
+
hasbit, f));
|
576
607
|
upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
|
577
608
|
upb_handlerattr_uninit(&attr);
|
578
609
|
break;
|
@@ -610,10 +641,12 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
|
|
610
641
|
|
611
642
|
add_handlers_for_singular_field(
|
612
643
|
h, key_field,
|
613
|
-
offsetof(map_parse_frame_t, key_storage)
|
644
|
+
offsetof(map_parse_frame_t, key_storage),
|
645
|
+
MESSAGE_FIELD_NO_HASBIT);
|
614
646
|
add_handlers_for_singular_field(
|
615
647
|
h, value_field,
|
616
|
-
offsetof(map_parse_frame_t, value_storage)
|
648
|
+
offsetof(map_parse_frame_t, value_storage),
|
649
|
+
MESSAGE_FIELD_NO_HASBIT);
|
617
650
|
}
|
618
651
|
|
619
652
|
// Set up handlers for a oneof field.
|
@@ -718,7 +751,8 @@ static void add_handlers_for_message(const void *closure, upb_handlers *h) {
|
|
718
751
|
} else if (upb_fielddef_isseq(f)) {
|
719
752
|
add_handlers_for_repeated_field(h, f, offset);
|
720
753
|
} else {
|
721
|
-
add_handlers_for_singular_field(
|
754
|
+
add_handlers_for_singular_field(
|
755
|
+
h, f, offset, desc->layout->fields[upb_fielddef_index(f)].hasbit);
|
722
756
|
}
|
723
757
|
}
|
724
758
|
}
|
@@ -854,19 +888,38 @@ VALUE Message_decode(VALUE klass, VALUE data) {
|
|
854
888
|
|
855
889
|
/*
|
856
890
|
* call-seq:
|
857
|
-
* MessageClass.decode_json(data) => message
|
891
|
+
* MessageClass.decode_json(data, options = {}) => message
|
858
892
|
*
|
859
893
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
860
894
|
* format) under the interpretration given by this message class's definition
|
861
895
|
* and returns a message object with the corresponding field values.
|
896
|
+
*
|
897
|
+
* @param options [Hash] options for the decoder
|
898
|
+
* ignore_unknown_fields: set true to ignore unknown fields (default is to raise an error)
|
862
899
|
*/
|
863
|
-
VALUE Message_decode_json(VALUE
|
900
|
+
VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
864
901
|
VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
|
865
902
|
Descriptor* desc = ruby_to_Descriptor(descriptor);
|
866
903
|
VALUE msgklass = Descriptor_msgclass(descriptor);
|
867
904
|
VALUE msg_rb;
|
905
|
+
VALUE data = argv[0];
|
906
|
+
VALUE ignore_unknown_fields = Qfalse;
|
868
907
|
MessageHeader* msg;
|
869
908
|
|
909
|
+
if (argc < 1 || argc > 2) {
|
910
|
+
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
911
|
+
}
|
912
|
+
|
913
|
+
if (argc == 2) {
|
914
|
+
VALUE hash_args = argv[1];
|
915
|
+
if (TYPE(hash_args) != T_HASH) {
|
916
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
917
|
+
}
|
918
|
+
|
919
|
+
ignore_unknown_fields = rb_hash_lookup2(
|
920
|
+
hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse);
|
921
|
+
}
|
922
|
+
|
870
923
|
if (TYPE(data) != T_STRING) {
|
871
924
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
872
925
|
}
|
@@ -882,10 +935,12 @@ VALUE Message_decode_json(VALUE klass, VALUE data) {
|
|
882
935
|
stackenv se;
|
883
936
|
upb_sink sink;
|
884
937
|
upb_json_parser* parser;
|
938
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
|
885
939
|
stackenv_init(&se, "Error occurred during parsing: %s");
|
886
940
|
|
887
941
|
upb_sink_reset(&sink, get_fill_handlers(desc), msg);
|
888
|
-
parser = upb_json_parser_create(&se.env, method,
|
942
|
+
parser = upb_json_parser_create(&se.env, method, pool->symtab,
|
943
|
+
&sink, ignore_unknown_fields);
|
889
944
|
upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
|
890
945
|
upb_json_parser_input(parser));
|
891
946
|
|
@@ -901,13 +956,9 @@ VALUE Message_decode_json(VALUE klass, VALUE data) {
|
|
901
956
|
|
902
957
|
/* msgvisitor *****************************************************************/
|
903
958
|
|
904
|
-
// TODO: If/when we support proto2 semantics in addition to the current proto3
|
905
|
-
// semantics, which means that we have true field presence, we will want to
|
906
|
-
// modify msgvisitor so that it emits all present fields rather than all
|
907
|
-
// non-default-value fields.
|
908
|
-
|
909
959
|
static void putmsg(VALUE msg, const Descriptor* desc,
|
910
|
-
upb_sink *sink, int depth, bool emit_defaults
|
960
|
+
upb_sink *sink, int depth, bool emit_defaults,
|
961
|
+
bool is_json, bool open_msg);
|
911
962
|
|
912
963
|
static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
|
913
964
|
upb_selector_t ret;
|
@@ -939,7 +990,7 @@ static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) {
|
|
939
990
|
}
|
940
991
|
|
941
992
|
static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
|
942
|
-
int depth, bool emit_defaults) {
|
993
|
+
int depth, bool emit_defaults, bool is_json) {
|
943
994
|
upb_sink subsink;
|
944
995
|
VALUE descriptor;
|
945
996
|
Descriptor* subdesc;
|
@@ -950,18 +1001,22 @@ static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
|
|
950
1001
|
subdesc = ruby_to_Descriptor(descriptor);
|
951
1002
|
|
952
1003
|
upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
|
953
|
-
putmsg(submsg, subdesc, &subsink, depth + 1, emit_defaults);
|
1004
|
+
putmsg(submsg, subdesc, &subsink, depth + 1, emit_defaults, is_json, true);
|
954
1005
|
upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
|
955
1006
|
}
|
956
1007
|
|
957
1008
|
static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
958
|
-
int depth, bool emit_defaults) {
|
1009
|
+
int depth, bool emit_defaults, bool is_json) {
|
959
1010
|
upb_sink subsink;
|
960
1011
|
upb_fieldtype_t type = upb_fielddef_type(f);
|
961
1012
|
upb_selector_t sel = 0;
|
962
1013
|
int size;
|
963
1014
|
|
964
1015
|
if (ary == Qnil) return;
|
1016
|
+
if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return;
|
1017
|
+
|
1018
|
+
size = NUM2INT(RepeatedField_length(ary));
|
1019
|
+
if (size == 0 && !emit_defaults) return;
|
965
1020
|
|
966
1021
|
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
967
1022
|
|
@@ -969,7 +1024,6 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
969
1024
|
sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
970
1025
|
}
|
971
1026
|
|
972
|
-
size = NUM2INT(RepeatedField_length(ary));
|
973
1027
|
for (int i = 0; i < size; i++) {
|
974
1028
|
void* memory = RepeatedField_index_native(ary, i);
|
975
1029
|
switch (type) {
|
@@ -992,7 +1046,8 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
992
1046
|
putstr(*((VALUE *)memory), f, &subsink);
|
993
1047
|
break;
|
994
1048
|
case UPB_TYPE_MESSAGE:
|
995
|
-
putsubmsg(*((VALUE *)memory), f, &subsink, depth,
|
1049
|
+
putsubmsg(*((VALUE *)memory), f, &subsink, depth,
|
1050
|
+
emit_defaults, is_json);
|
996
1051
|
break;
|
997
1052
|
|
998
1053
|
#undef T
|
@@ -1007,7 +1062,13 @@ static void put_ruby_value(VALUE value,
|
|
1007
1062
|
VALUE type_class,
|
1008
1063
|
int depth,
|
1009
1064
|
upb_sink *sink,
|
1010
|
-
bool emit_defaults
|
1065
|
+
bool emit_defaults,
|
1066
|
+
bool is_json) {
|
1067
|
+
if (depth > ENCODE_MAX_NESTING) {
|
1068
|
+
rb_raise(rb_eRuntimeError,
|
1069
|
+
"Maximum recursion depth exceeded during encoding.");
|
1070
|
+
}
|
1071
|
+
|
1011
1072
|
upb_selector_t sel = 0;
|
1012
1073
|
if (upb_fielddef_isprimitive(f)) {
|
1013
1074
|
sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
@@ -1047,12 +1108,12 @@ static void put_ruby_value(VALUE value,
|
|
1047
1108
|
putstr(value, f, sink);
|
1048
1109
|
break;
|
1049
1110
|
case UPB_TYPE_MESSAGE:
|
1050
|
-
putsubmsg(value, f, sink, depth, emit_defaults);
|
1111
|
+
putsubmsg(value, f, sink, depth, emit_defaults, is_json);
|
1051
1112
|
}
|
1052
1113
|
}
|
1053
1114
|
|
1054
1115
|
static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
1055
|
-
int depth, bool emit_defaults) {
|
1116
|
+
int depth, bool emit_defaults, bool is_json) {
|
1056
1117
|
Map* self;
|
1057
1118
|
upb_sink subsink;
|
1058
1119
|
const upb_fielddef* key_field;
|
@@ -1060,6 +1121,8 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1060
1121
|
Map_iter it;
|
1061
1122
|
|
1062
1123
|
if (map == Qnil) return;
|
1124
|
+
if (!emit_defaults && Map_length(map) == 0) return;
|
1125
|
+
|
1063
1126
|
self = ruby_to_Map(map);
|
1064
1127
|
|
1065
1128
|
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
@@ -1078,9 +1141,10 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1078
1141
|
&entry_sink);
|
1079
1142
|
upb_sink_startmsg(&entry_sink);
|
1080
1143
|
|
1081
|
-
put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink,
|
1144
|
+
put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink,
|
1145
|
+
emit_defaults, is_json);
|
1082
1146
|
put_ruby_value(value, value_field, self->value_type_class, depth + 1,
|
1083
|
-
&entry_sink, emit_defaults);
|
1147
|
+
&entry_sink, emit_defaults, is_json);
|
1084
1148
|
|
1085
1149
|
upb_sink_endmsg(&entry_sink, &status);
|
1086
1150
|
upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
|
@@ -1089,13 +1153,143 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1089
1153
|
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
1090
1154
|
}
|
1091
1155
|
|
1156
|
+
static const upb_handlers* msgdef_json_serialize_handlers(
|
1157
|
+
Descriptor* desc, bool preserve_proto_fieldnames);
|
1158
|
+
|
1159
|
+
static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
1160
|
+
upb_sink* sink, int depth, bool emit_defaults) {
|
1161
|
+
upb_status status;
|
1162
|
+
MessageHeader* msg = NULL;
|
1163
|
+
const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
|
1164
|
+
const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE);
|
1165
|
+
|
1166
|
+
size_t type_url_offset;
|
1167
|
+
VALUE type_url_str_rb;
|
1168
|
+
const upb_msgdef *payload_type = NULL;
|
1169
|
+
|
1170
|
+
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
1171
|
+
|
1172
|
+
upb_sink_startmsg(sink);
|
1173
|
+
|
1174
|
+
/* Handle type url */
|
1175
|
+
type_url_offset = desc->layout->fields[upb_fielddef_index(type_field)].offset;
|
1176
|
+
type_url_str_rb = DEREF(Message_data(msg), type_url_offset, VALUE);
|
1177
|
+
if (RSTRING_LEN(type_url_str_rb) > 0) {
|
1178
|
+
putstr(type_url_str_rb, type_field, sink);
|
1179
|
+
}
|
1180
|
+
|
1181
|
+
{
|
1182
|
+
const char* type_url_str = RSTRING_PTR(type_url_str_rb);
|
1183
|
+
size_t type_url_len = RSTRING_LEN(type_url_str_rb);
|
1184
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
|
1185
|
+
|
1186
|
+
if (type_url_len <= 20 ||
|
1187
|
+
strncmp(type_url_str, "type.googleapis.com/", 20) != 0) {
|
1188
|
+
rb_raise(rb_eRuntimeError, "Invalid type url: %s", type_url_str);
|
1189
|
+
return;
|
1190
|
+
}
|
1191
|
+
|
1192
|
+
/* Resolve type url */
|
1193
|
+
type_url_str += 20;
|
1194
|
+
type_url_len -= 20;
|
1195
|
+
|
1196
|
+
payload_type = upb_symtab_lookupmsg2(
|
1197
|
+
pool->symtab, type_url_str, type_url_len);
|
1198
|
+
if (payload_type == NULL) {
|
1199
|
+
rb_raise(rb_eRuntimeError, "Unknown type: %s", type_url_str);
|
1200
|
+
return;
|
1201
|
+
}
|
1202
|
+
}
|
1203
|
+
|
1204
|
+
{
|
1205
|
+
uint32_t value_offset;
|
1206
|
+
VALUE value_str_rb;
|
1207
|
+
const char* value_str;
|
1208
|
+
size_t value_len;
|
1209
|
+
|
1210
|
+
value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset;
|
1211
|
+
value_str_rb = DEREF(Message_data(msg), value_offset, VALUE);
|
1212
|
+
value_str = RSTRING_PTR(value_str_rb);
|
1213
|
+
value_len = RSTRING_LEN(value_str_rb);
|
1214
|
+
|
1215
|
+
if (value_len > 0) {
|
1216
|
+
VALUE payload_desc_rb = get_def_obj(payload_type);
|
1217
|
+
Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb);
|
1218
|
+
VALUE payload_class = Descriptor_msgclass(payload_desc_rb);
|
1219
|
+
upb_sink subsink;
|
1220
|
+
bool is_wellknown;
|
1221
|
+
|
1222
|
+
VALUE payload_msg_rb = Message_decode(payload_class, value_str_rb);
|
1223
|
+
|
1224
|
+
is_wellknown =
|
1225
|
+
upb_msgdef_wellknowntype(payload_desc->msgdef) !=
|
1226
|
+
UPB_WELLKNOWN_UNSPECIFIED;
|
1227
|
+
if (is_wellknown) {
|
1228
|
+
upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0,
|
1229
|
+
&subsink);
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
subsink.handlers =
|
1233
|
+
msgdef_json_serialize_handlers(payload_desc, true);
|
1234
|
+
subsink.closure = sink->closure;
|
1235
|
+
putmsg(payload_msg_rb, payload_desc, &subsink, depth, emit_defaults, true,
|
1236
|
+
is_wellknown);
|
1237
|
+
}
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
upb_sink_endmsg(sink, &status);
|
1241
|
+
}
|
1242
|
+
|
1243
|
+
static void putjsonlistvalue(
|
1244
|
+
VALUE msg_rb, const Descriptor* desc,
|
1245
|
+
upb_sink* sink, int depth, bool emit_defaults) {
|
1246
|
+
upb_status status;
|
1247
|
+
upb_sink subsink;
|
1248
|
+
MessageHeader* msg = NULL;
|
1249
|
+
const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
|
1250
|
+
uint32_t offset =
|
1251
|
+
desc->layout->fields[upb_fielddef_index(f)].offset +
|
1252
|
+
sizeof(MessageHeader);
|
1253
|
+
VALUE ary;
|
1254
|
+
|
1255
|
+
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
1256
|
+
|
1257
|
+
upb_sink_startmsg(sink);
|
1258
|
+
|
1259
|
+
ary = DEREF(msg, offset, VALUE);
|
1260
|
+
|
1261
|
+
if (ary == Qnil || RepeatedField_size(ary) == 0) {
|
1262
|
+
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
1263
|
+
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
1264
|
+
} else {
|
1265
|
+
putary(ary, f, sink, depth, emit_defaults, true);
|
1266
|
+
}
|
1267
|
+
|
1268
|
+
upb_sink_endmsg(sink, &status);
|
1269
|
+
}
|
1270
|
+
|
1092
1271
|
static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
1093
|
-
upb_sink *sink, int depth, bool emit_defaults
|
1272
|
+
upb_sink *sink, int depth, bool emit_defaults,
|
1273
|
+
bool is_json, bool open_msg) {
|
1094
1274
|
MessageHeader* msg;
|
1095
1275
|
upb_msg_field_iter i;
|
1096
1276
|
upb_status status;
|
1097
1277
|
|
1098
|
-
|
1278
|
+
if (is_json &&
|
1279
|
+
upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
|
1280
|
+
putjsonany(msg_rb, desc, sink, depth, emit_defaults);
|
1281
|
+
return;
|
1282
|
+
}
|
1283
|
+
|
1284
|
+
if (is_json &&
|
1285
|
+
upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) {
|
1286
|
+
putjsonlistvalue(msg_rb, desc, sink, depth, emit_defaults);
|
1287
|
+
return;
|
1288
|
+
}
|
1289
|
+
|
1290
|
+
if (open_msg) {
|
1291
|
+
upb_sink_startmsg(sink);
|
1292
|
+
}
|
1099
1293
|
|
1100
1294
|
// Protect against cycles (possible because users may freely reassign message
|
1101
1295
|
// and repeated fields) by imposing a maximum recursion depth.
|
@@ -1140,30 +1334,45 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1140
1334
|
if (is_map_field(f)) {
|
1141
1335
|
VALUE map = DEREF(msg, offset, VALUE);
|
1142
1336
|
if (map != Qnil || emit_defaults) {
|
1143
|
-
putmap(map, f, sink, depth, emit_defaults);
|
1337
|
+
putmap(map, f, sink, depth, emit_defaults, is_json);
|
1144
1338
|
}
|
1145
1339
|
} else if (upb_fielddef_isseq(f)) {
|
1146
1340
|
VALUE ary = DEREF(msg, offset, VALUE);
|
1147
1341
|
if (ary != Qnil) {
|
1148
|
-
putary(ary, f, sink, depth, emit_defaults);
|
1342
|
+
putary(ary, f, sink, depth, emit_defaults, is_json);
|
1149
1343
|
}
|
1150
1344
|
} else if (upb_fielddef_isstring(f)) {
|
1151
1345
|
VALUE str = DEREF(msg, offset, VALUE);
|
1152
|
-
|
1346
|
+
bool is_default = false;
|
1347
|
+
|
1348
|
+
if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO2) {
|
1349
|
+
is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse;
|
1350
|
+
} else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {
|
1351
|
+
is_default = RSTRING_LEN(str) == 0;
|
1352
|
+
}
|
1353
|
+
|
1354
|
+
if (is_matching_oneof || emit_defaults || !is_default) {
|
1153
1355
|
putstr(str, f, sink);
|
1154
1356
|
}
|
1155
1357
|
} else if (upb_fielddef_issubmsg(f)) {
|
1156
|
-
putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth,
|
1358
|
+
putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth,
|
1359
|
+
emit_defaults, is_json);
|
1157
1360
|
} else {
|
1158
1361
|
upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
1159
1362
|
|
1160
|
-
#define T(upbtypeconst, upbtype, ctype, default_value)
|
1161
|
-
case upbtypeconst: {
|
1162
|
-
ctype value = DEREF(msg, offset, ctype);
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1363
|
+
#define T(upbtypeconst, upbtype, ctype, default_value) \
|
1364
|
+
case upbtypeconst: { \
|
1365
|
+
ctype value = DEREF(msg, offset, ctype); \
|
1366
|
+
bool is_default = false; \
|
1367
|
+
if (upb_fielddef_haspresence(f)) { \
|
1368
|
+
is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; \
|
1369
|
+
} else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) { \
|
1370
|
+
is_default = default_value == value; \
|
1371
|
+
} \
|
1372
|
+
if (is_matching_oneof || emit_defaults || !is_default) { \
|
1373
|
+
upb_sink_put##upbtype(sink, sel, value); \
|
1374
|
+
} \
|
1375
|
+
} \
|
1167
1376
|
break;
|
1168
1377
|
|
1169
1378
|
switch (upb_fielddef_type(f)) {
|
@@ -1191,7 +1400,9 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1191
1400
|
upb_sink_putunknown(sink, unknown->ptr, unknown->len);
|
1192
1401
|
}
|
1193
1402
|
|
1194
|
-
|
1403
|
+
if (open_msg) {
|
1404
|
+
upb_sink_endmsg(sink, &status);
|
1405
|
+
}
|
1195
1406
|
}
|
1196
1407
|
|
1197
1408
|
static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
|
@@ -1246,7 +1457,7 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) {
|
|
1246
1457
|
stackenv_init(&se, "Error occurred during encoding: %s");
|
1247
1458
|
encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink);
|
1248
1459
|
|
1249
|
-
putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false);
|
1460
|
+
putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true);
|
1250
1461
|
|
1251
1462
|
ret = rb_str_new(sink.ptr, sink.len);
|
1252
1463
|
|
@@ -1259,9 +1470,12 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) {
|
|
1259
1470
|
|
1260
1471
|
/*
|
1261
1472
|
* call-seq:
|
1262
|
-
* MessageClass.encode_json(msg) => json_string
|
1473
|
+
* MessageClass.encode_json(msg, options = {}) => json_string
|
1263
1474
|
*
|
1264
1475
|
* Encodes the given message object into its serialized JSON representation.
|
1476
|
+
* @param options [Hash] options for the decoder
|
1477
|
+
* preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
|
1478
|
+
* emit_defaults: set true to emit 0/false values (default is to omit them)
|
1265
1479
|
*/
|
1266
1480
|
VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
1267
1481
|
VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
|
@@ -1301,7 +1515,8 @@ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1301
1515
|
stackenv_init(&se, "Error occurred during encoding: %s");
|
1302
1516
|
printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink);
|
1303
1517
|
|
1304
|
-
putmsg(msg_rb, desc, upb_json_printer_input(printer), 0,
|
1518
|
+
putmsg(msg_rb, desc, upb_json_printer_input(printer), 0,
|
1519
|
+
RTEST(emit_defaults), true, true);
|
1305
1520
|
|
1306
1521
|
ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding());
|
1307
1522
|
|