google-protobuf 3.6.1-universal-darwin → 3.7.0.rc.2-universal-darwin
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/defs.c +554 -71
- data/ext/google/protobuf_c/encode_decode.c +238 -66
- data/ext/google/protobuf_c/extconf.rb +5 -1
- data/ext/google/protobuf_c/message.c +135 -69
- data/ext/google/protobuf_c/protobuf.c +4 -0
- data/ext/google/protobuf_c/protobuf.h +62 -2
- data/ext/google/protobuf_c/storage.c +211 -104
- data/ext/google/protobuf_c/upb.c +4126 -1721
- data/ext/google/protobuf_c/upb.h +1125 -339
- data/ext/google/protobuf_c/wrap_memcpy.c +1 -1
- data/lib/google/2.3/protobuf_c.bundle +0 -0
- data/lib/google/2.4/protobuf_c.bundle +0 -0
- data/lib/google/2.5/protobuf_c.bundle +0 -0
- data/lib/google/2.6/protobuf_c.bundle +0 -0
- 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 +137 -1181
- data/tests/generated_code_test.rb +5 -3
- metadata +6 -9
- data/lib/google/2.0/protobuf_c.bundle +0 -0
- data/lib/google/2.1/protobuf_c.bundle +0 -0
- data/lib/google/2.2/protobuf_c.bundle +0 -0
@@ -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
|
|
@@ -457,9 +476,8 @@ static void *oneofbytes_handler(void *closure,
|
|
457
476
|
}
|
458
477
|
|
459
478
|
static bool oneofstring_end_handler(void* closure, const void* hd) {
|
460
|
-
|
461
|
-
|
462
|
-
rb_obj_freeze(DEREF(msg, oneofdata->ofs, VALUE));
|
479
|
+
VALUE rb_str = rb_str_new2("");
|
480
|
+
rb_obj_freeze(rb_str);
|
463
481
|
return true;
|
464
482
|
}
|
465
483
|
|
@@ -500,7 +518,7 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|
500
518
|
const upb_fielddef *f,
|
501
519
|
size_t offset) {
|
502
520
|
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
503
|
-
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
|
521
|
+
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset, -1));
|
504
522
|
upb_handlers_setstartseq(h, f, startseq_handler, &attr);
|
505
523
|
upb_handlerattr_uninit(&attr);
|
506
524
|
|
@@ -534,7 +552,7 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|
534
552
|
}
|
535
553
|
case UPB_TYPE_MESSAGE: {
|
536
554
|
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
537
|
-
upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f));
|
555
|
+
upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, -1, f));
|
538
556
|
upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
|
539
557
|
upb_handlerattr_uninit(&attr);
|
540
558
|
break;
|
@@ -545,7 +563,15 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|
545
563
|
// Set up handlers for a singular field.
|
546
564
|
static void add_handlers_for_singular_field(upb_handlers *h,
|
547
565
|
const upb_fielddef *f,
|
548
|
-
size_t offset
|
566
|
+
size_t offset,
|
567
|
+
size_t hasbit_off) {
|
568
|
+
// The offset we pass to UPB points to the start of the Message,
|
569
|
+
// rather than the start of where our data is stored.
|
570
|
+
int32_t hasbit = -1;
|
571
|
+
if (hasbit_off != MESSAGE_FIELD_NO_HASBIT) {
|
572
|
+
hasbit = hasbit_off + sizeof(MessageHeader) * 8;
|
573
|
+
}
|
574
|
+
|
549
575
|
switch (upb_fielddef_type(f)) {
|
550
576
|
case UPB_TYPE_BOOL:
|
551
577
|
case UPB_TYPE_INT32:
|
@@ -555,13 +581,13 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|
555
581
|
case UPB_TYPE_INT64:
|
556
582
|
case UPB_TYPE_UINT64:
|
557
583
|
case UPB_TYPE_DOUBLE:
|
558
|
-
upb_msg_setscalarhandler(h, f, offset,
|
584
|
+
upb_msg_setscalarhandler(h, f, offset, hasbit);
|
559
585
|
break;
|
560
586
|
case UPB_TYPE_STRING:
|
561
587
|
case UPB_TYPE_BYTES: {
|
562
588
|
bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
|
563
589
|
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
564
|
-
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
|
590
|
+
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset, hasbit));
|
565
591
|
upb_handlers_setstartstr(h, f,
|
566
592
|
is_bytes ? bytes_handler : str_handler,
|
567
593
|
&attr);
|
@@ -572,7 +598,9 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|
572
598
|
}
|
573
599
|
case UPB_TYPE_MESSAGE: {
|
574
600
|
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
575
|
-
upb_handlerattr_sethandlerdata(&attr,
|
601
|
+
upb_handlerattr_sethandlerdata(&attr,
|
602
|
+
newsubmsghandlerdata(h, offset,
|
603
|
+
hasbit, f));
|
576
604
|
upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
|
577
605
|
upb_handlerattr_uninit(&attr);
|
578
606
|
break;
|
@@ -610,10 +638,12 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
|
|
610
638
|
|
611
639
|
add_handlers_for_singular_field(
|
612
640
|
h, key_field,
|
613
|
-
offsetof(map_parse_frame_t, key_storage)
|
641
|
+
offsetof(map_parse_frame_t, key_storage),
|
642
|
+
MESSAGE_FIELD_NO_HASBIT);
|
614
643
|
add_handlers_for_singular_field(
|
615
644
|
h, value_field,
|
616
|
-
offsetof(map_parse_frame_t, value_storage)
|
645
|
+
offsetof(map_parse_frame_t, value_storage),
|
646
|
+
MESSAGE_FIELD_NO_HASBIT);
|
617
647
|
}
|
618
648
|
|
619
649
|
// Set up handlers for a oneof field.
|
@@ -718,7 +748,8 @@ static void add_handlers_for_message(const void *closure, upb_handlers *h) {
|
|
718
748
|
} else if (upb_fielddef_isseq(f)) {
|
719
749
|
add_handlers_for_repeated_field(h, f, offset);
|
720
750
|
} else {
|
721
|
-
add_handlers_for_singular_field(
|
751
|
+
add_handlers_for_singular_field(
|
752
|
+
h, f, offset, desc->layout->fields[upb_fielddef_index(f)].hasbit);
|
722
753
|
}
|
723
754
|
}
|
724
755
|
}
|
@@ -854,19 +885,38 @@ VALUE Message_decode(VALUE klass, VALUE data) {
|
|
854
885
|
|
855
886
|
/*
|
856
887
|
* call-seq:
|
857
|
-
* MessageClass.decode_json(data) => message
|
888
|
+
* MessageClass.decode_json(data, options = {}) => message
|
858
889
|
*
|
859
890
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
860
891
|
* format) under the interpretration given by this message class's definition
|
861
892
|
* and returns a message object with the corresponding field values.
|
893
|
+
*
|
894
|
+
* @param options [Hash] options for the decoder
|
895
|
+
* ignore_unknown_fields: set true to ignore unknown fields (default is to raise an error)
|
862
896
|
*/
|
863
|
-
VALUE Message_decode_json(VALUE
|
897
|
+
VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
864
898
|
VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
|
865
899
|
Descriptor* desc = ruby_to_Descriptor(descriptor);
|
866
900
|
VALUE msgklass = Descriptor_msgclass(descriptor);
|
867
901
|
VALUE msg_rb;
|
902
|
+
VALUE data = argv[0];
|
903
|
+
VALUE ignore_unknown_fields = Qfalse;
|
868
904
|
MessageHeader* msg;
|
869
905
|
|
906
|
+
if (argc < 1 || argc > 2) {
|
907
|
+
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
908
|
+
}
|
909
|
+
|
910
|
+
if (argc == 2) {
|
911
|
+
VALUE hash_args = argv[1];
|
912
|
+
if (TYPE(hash_args) != T_HASH) {
|
913
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
914
|
+
}
|
915
|
+
|
916
|
+
ignore_unknown_fields = rb_hash_lookup2(
|
917
|
+
hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse);
|
918
|
+
}
|
919
|
+
|
870
920
|
if (TYPE(data) != T_STRING) {
|
871
921
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
872
922
|
}
|
@@ -882,10 +932,12 @@ VALUE Message_decode_json(VALUE klass, VALUE data) {
|
|
882
932
|
stackenv se;
|
883
933
|
upb_sink sink;
|
884
934
|
upb_json_parser* parser;
|
935
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
|
885
936
|
stackenv_init(&se, "Error occurred during parsing: %s");
|
886
937
|
|
887
938
|
upb_sink_reset(&sink, get_fill_handlers(desc), msg);
|
888
|
-
parser = upb_json_parser_create(&se.env, method,
|
939
|
+
parser = upb_json_parser_create(&se.env, method, pool->symtab,
|
940
|
+
&sink, ignore_unknown_fields);
|
889
941
|
upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
|
890
942
|
upb_json_parser_input(parser));
|
891
943
|
|
@@ -901,13 +953,9 @@ VALUE Message_decode_json(VALUE klass, VALUE data) {
|
|
901
953
|
|
902
954
|
/* msgvisitor *****************************************************************/
|
903
955
|
|
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
956
|
static void putmsg(VALUE msg, const Descriptor* desc,
|
910
|
-
upb_sink *sink, int depth, bool emit_defaults
|
957
|
+
upb_sink *sink, int depth, bool emit_defaults,
|
958
|
+
bool is_json, bool open_msg);
|
911
959
|
|
912
960
|
static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
|
913
961
|
upb_selector_t ret;
|
@@ -939,7 +987,7 @@ static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) {
|
|
939
987
|
}
|
940
988
|
|
941
989
|
static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
|
942
|
-
int depth, bool emit_defaults) {
|
990
|
+
int depth, bool emit_defaults, bool is_json) {
|
943
991
|
upb_sink subsink;
|
944
992
|
VALUE descriptor;
|
945
993
|
Descriptor* subdesc;
|
@@ -950,18 +998,22 @@ static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
|
|
950
998
|
subdesc = ruby_to_Descriptor(descriptor);
|
951
999
|
|
952
1000
|
upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
|
953
|
-
putmsg(submsg, subdesc, &subsink, depth + 1, emit_defaults);
|
1001
|
+
putmsg(submsg, subdesc, &subsink, depth + 1, emit_defaults, is_json, true);
|
954
1002
|
upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
|
955
1003
|
}
|
956
1004
|
|
957
1005
|
static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
958
|
-
int depth, bool emit_defaults) {
|
1006
|
+
int depth, bool emit_defaults, bool is_json) {
|
959
1007
|
upb_sink subsink;
|
960
1008
|
upb_fieldtype_t type = upb_fielddef_type(f);
|
961
1009
|
upb_selector_t sel = 0;
|
962
1010
|
int size;
|
963
1011
|
|
964
1012
|
if (ary == Qnil) return;
|
1013
|
+
if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return;
|
1014
|
+
|
1015
|
+
size = NUM2INT(RepeatedField_length(ary));
|
1016
|
+
if (size == 0 && !emit_defaults) return;
|
965
1017
|
|
966
1018
|
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
967
1019
|
|
@@ -969,7 +1021,6 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
969
1021
|
sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
970
1022
|
}
|
971
1023
|
|
972
|
-
size = NUM2INT(RepeatedField_length(ary));
|
973
1024
|
for (int i = 0; i < size; i++) {
|
974
1025
|
void* memory = RepeatedField_index_native(ary, i);
|
975
1026
|
switch (type) {
|
@@ -992,7 +1043,8 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
992
1043
|
putstr(*((VALUE *)memory), f, &subsink);
|
993
1044
|
break;
|
994
1045
|
case UPB_TYPE_MESSAGE:
|
995
|
-
putsubmsg(*((VALUE *)memory), f, &subsink, depth,
|
1046
|
+
putsubmsg(*((VALUE *)memory), f, &subsink, depth,
|
1047
|
+
emit_defaults, is_json);
|
996
1048
|
break;
|
997
1049
|
|
998
1050
|
#undef T
|
@@ -1007,7 +1059,8 @@ static void put_ruby_value(VALUE value,
|
|
1007
1059
|
VALUE type_class,
|
1008
1060
|
int depth,
|
1009
1061
|
upb_sink *sink,
|
1010
|
-
bool emit_defaults
|
1062
|
+
bool emit_defaults,
|
1063
|
+
bool is_json) {
|
1011
1064
|
upb_selector_t sel = 0;
|
1012
1065
|
if (upb_fielddef_isprimitive(f)) {
|
1013
1066
|
sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
@@ -1047,12 +1100,12 @@ static void put_ruby_value(VALUE value,
|
|
1047
1100
|
putstr(value, f, sink);
|
1048
1101
|
break;
|
1049
1102
|
case UPB_TYPE_MESSAGE:
|
1050
|
-
putsubmsg(value, f, sink, depth, emit_defaults);
|
1103
|
+
putsubmsg(value, f, sink, depth, emit_defaults, is_json);
|
1051
1104
|
}
|
1052
1105
|
}
|
1053
1106
|
|
1054
1107
|
static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
1055
|
-
int depth, bool emit_defaults) {
|
1108
|
+
int depth, bool emit_defaults, bool is_json) {
|
1056
1109
|
Map* self;
|
1057
1110
|
upb_sink subsink;
|
1058
1111
|
const upb_fielddef* key_field;
|
@@ -1060,6 +1113,8 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1060
1113
|
Map_iter it;
|
1061
1114
|
|
1062
1115
|
if (map == Qnil) return;
|
1116
|
+
if (!emit_defaults && Map_length(map) == 0) return;
|
1117
|
+
|
1063
1118
|
self = ruby_to_Map(map);
|
1064
1119
|
|
1065
1120
|
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
@@ -1078,9 +1133,10 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1078
1133
|
&entry_sink);
|
1079
1134
|
upb_sink_startmsg(&entry_sink);
|
1080
1135
|
|
1081
|
-
put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink,
|
1136
|
+
put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink,
|
1137
|
+
emit_defaults, is_json);
|
1082
1138
|
put_ruby_value(value, value_field, self->value_type_class, depth + 1,
|
1083
|
-
&entry_sink, emit_defaults);
|
1139
|
+
&entry_sink, emit_defaults, is_json);
|
1084
1140
|
|
1085
1141
|
upb_sink_endmsg(&entry_sink, &status);
|
1086
1142
|
upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
|
@@ -1089,13 +1145,108 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1089
1145
|
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
1090
1146
|
}
|
1091
1147
|
|
1148
|
+
static const upb_handlers* msgdef_json_serialize_handlers(
|
1149
|
+
Descriptor* desc, bool preserve_proto_fieldnames);
|
1150
|
+
|
1151
|
+
static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
1152
|
+
upb_sink* sink, int depth, bool emit_defaults) {
|
1153
|
+
upb_status status;
|
1154
|
+
MessageHeader* msg = NULL;
|
1155
|
+
const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
|
1156
|
+
const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE);
|
1157
|
+
|
1158
|
+
size_t type_url_offset;
|
1159
|
+
VALUE type_url_str_rb;
|
1160
|
+
const upb_msgdef *payload_type = NULL;
|
1161
|
+
|
1162
|
+
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
1163
|
+
|
1164
|
+
upb_sink_startmsg(sink);
|
1165
|
+
|
1166
|
+
/* Handle type url */
|
1167
|
+
type_url_offset = desc->layout->fields[upb_fielddef_index(type_field)].offset;
|
1168
|
+
type_url_str_rb = DEREF(Message_data(msg), type_url_offset, VALUE);
|
1169
|
+
if (RSTRING_LEN(type_url_str_rb) > 0) {
|
1170
|
+
putstr(type_url_str_rb, type_field, sink);
|
1171
|
+
}
|
1172
|
+
|
1173
|
+
{
|
1174
|
+
const char* type_url_str = RSTRING_PTR(type_url_str_rb);
|
1175
|
+
size_t type_url_len = RSTRING_LEN(type_url_str_rb);
|
1176
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
|
1177
|
+
|
1178
|
+
if (type_url_len <= 20 ||
|
1179
|
+
strncmp(type_url_str, "type.googleapis.com/", 20) != 0) {
|
1180
|
+
rb_raise(rb_eRuntimeError, "Invalid type url: %s", type_url_str);
|
1181
|
+
return;
|
1182
|
+
}
|
1183
|
+
|
1184
|
+
/* Resolve type url */
|
1185
|
+
type_url_str += 20;
|
1186
|
+
type_url_len -= 20;
|
1187
|
+
|
1188
|
+
payload_type = upb_symtab_lookupmsg2(
|
1189
|
+
pool->symtab, type_url_str, type_url_len);
|
1190
|
+
if (payload_type == NULL) {
|
1191
|
+
rb_raise(rb_eRuntimeError, "Unknown type: %s", type_url_str);
|
1192
|
+
return;
|
1193
|
+
}
|
1194
|
+
}
|
1195
|
+
|
1196
|
+
{
|
1197
|
+
uint32_t value_offset;
|
1198
|
+
VALUE value_str_rb;
|
1199
|
+
const char* value_str;
|
1200
|
+
size_t value_len;
|
1201
|
+
|
1202
|
+
value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset;
|
1203
|
+
value_str_rb = DEREF(Message_data(msg), value_offset, VALUE);
|
1204
|
+
value_str = RSTRING_PTR(value_str_rb);
|
1205
|
+
value_len = RSTRING_LEN(value_str_rb);
|
1206
|
+
|
1207
|
+
if (value_len > 0) {
|
1208
|
+
VALUE payload_desc_rb = get_def_obj(payload_type);
|
1209
|
+
Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb);
|
1210
|
+
VALUE payload_class = Descriptor_msgclass(payload_desc_rb);
|
1211
|
+
upb_sink subsink;
|
1212
|
+
bool is_wellknown;
|
1213
|
+
|
1214
|
+
VALUE payload_msg_rb = Message_decode(payload_class, value_str_rb);
|
1215
|
+
|
1216
|
+
is_wellknown =
|
1217
|
+
upb_msgdef_wellknowntype(payload_desc->msgdef) !=
|
1218
|
+
UPB_WELLKNOWN_UNSPECIFIED;
|
1219
|
+
if (is_wellknown) {
|
1220
|
+
upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0,
|
1221
|
+
&subsink);
|
1222
|
+
}
|
1223
|
+
|
1224
|
+
subsink.handlers =
|
1225
|
+
msgdef_json_serialize_handlers(payload_desc, true);
|
1226
|
+
subsink.closure = sink->closure;
|
1227
|
+
putmsg(payload_msg_rb, payload_desc, &subsink, depth, emit_defaults, true,
|
1228
|
+
is_wellknown);
|
1229
|
+
}
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
upb_sink_endmsg(sink, &status);
|
1233
|
+
}
|
1234
|
+
|
1092
1235
|
static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
1093
|
-
upb_sink *sink, int depth, bool emit_defaults
|
1236
|
+
upb_sink *sink, int depth, bool emit_defaults,
|
1237
|
+
bool is_json, bool open_msg) {
|
1094
1238
|
MessageHeader* msg;
|
1095
1239
|
upb_msg_field_iter i;
|
1096
1240
|
upb_status status;
|
1097
1241
|
|
1098
|
-
|
1242
|
+
if (is_json && upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
|
1243
|
+
putjsonany(msg_rb, desc, sink, depth, emit_defaults);
|
1244
|
+
return;
|
1245
|
+
}
|
1246
|
+
|
1247
|
+
if (open_msg) {
|
1248
|
+
upb_sink_startmsg(sink);
|
1249
|
+
}
|
1099
1250
|
|
1100
1251
|
// Protect against cycles (possible because users may freely reassign message
|
1101
1252
|
// and repeated fields) by imposing a maximum recursion depth.
|
@@ -1140,30 +1291,45 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1140
1291
|
if (is_map_field(f)) {
|
1141
1292
|
VALUE map = DEREF(msg, offset, VALUE);
|
1142
1293
|
if (map != Qnil || emit_defaults) {
|
1143
|
-
putmap(map, f, sink, depth, emit_defaults);
|
1294
|
+
putmap(map, f, sink, depth, emit_defaults, is_json);
|
1144
1295
|
}
|
1145
1296
|
} else if (upb_fielddef_isseq(f)) {
|
1146
1297
|
VALUE ary = DEREF(msg, offset, VALUE);
|
1147
1298
|
if (ary != Qnil) {
|
1148
|
-
putary(ary, f, sink, depth, emit_defaults);
|
1299
|
+
putary(ary, f, sink, depth, emit_defaults, is_json);
|
1149
1300
|
}
|
1150
1301
|
} else if (upb_fielddef_isstring(f)) {
|
1151
1302
|
VALUE str = DEREF(msg, offset, VALUE);
|
1152
|
-
|
1303
|
+
bool is_default = false;
|
1304
|
+
|
1305
|
+
if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO2) {
|
1306
|
+
is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse;
|
1307
|
+
} else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {
|
1308
|
+
is_default = RSTRING_LEN(str) == 0;
|
1309
|
+
}
|
1310
|
+
|
1311
|
+
if (is_matching_oneof || emit_defaults || !is_default) {
|
1153
1312
|
putstr(str, f, sink);
|
1154
1313
|
}
|
1155
1314
|
} else if (upb_fielddef_issubmsg(f)) {
|
1156
|
-
putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth,
|
1315
|
+
putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth,
|
1316
|
+
emit_defaults, is_json);
|
1157
1317
|
} else {
|
1158
1318
|
upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
1159
1319
|
|
1160
|
-
#define T(upbtypeconst, upbtype, ctype, default_value)
|
1161
|
-
case upbtypeconst: {
|
1162
|
-
ctype value = DEREF(msg, offset, ctype);
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1320
|
+
#define T(upbtypeconst, upbtype, ctype, default_value) \
|
1321
|
+
case upbtypeconst: { \
|
1322
|
+
ctype value = DEREF(msg, offset, ctype); \
|
1323
|
+
bool is_default = false; \
|
1324
|
+
if (upb_fielddef_haspresence(f)) { \
|
1325
|
+
is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; \
|
1326
|
+
} else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) { \
|
1327
|
+
is_default = default_value == value; \
|
1328
|
+
} \
|
1329
|
+
if (is_matching_oneof || emit_defaults || !is_default) { \
|
1330
|
+
upb_sink_put##upbtype(sink, sel, value); \
|
1331
|
+
} \
|
1332
|
+
} \
|
1167
1333
|
break;
|
1168
1334
|
|
1169
1335
|
switch (upb_fielddef_type(f)) {
|
@@ -1191,7 +1357,9 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1191
1357
|
upb_sink_putunknown(sink, unknown->ptr, unknown->len);
|
1192
1358
|
}
|
1193
1359
|
|
1194
|
-
|
1360
|
+
if (open_msg) {
|
1361
|
+
upb_sink_endmsg(sink, &status);
|
1362
|
+
}
|
1195
1363
|
}
|
1196
1364
|
|
1197
1365
|
static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
|
@@ -1246,7 +1414,7 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) {
|
|
1246
1414
|
stackenv_init(&se, "Error occurred during encoding: %s");
|
1247
1415
|
encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink);
|
1248
1416
|
|
1249
|
-
putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false);
|
1417
|
+
putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true);
|
1250
1418
|
|
1251
1419
|
ret = rb_str_new(sink.ptr, sink.len);
|
1252
1420
|
|
@@ -1259,9 +1427,12 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) {
|
|
1259
1427
|
|
1260
1428
|
/*
|
1261
1429
|
* call-seq:
|
1262
|
-
* MessageClass.encode_json(msg) => json_string
|
1430
|
+
* MessageClass.encode_json(msg, options = {}) => json_string
|
1263
1431
|
*
|
1264
1432
|
* Encodes the given message object into its serialized JSON representation.
|
1433
|
+
* @param options [Hash] options for the decoder
|
1434
|
+
* preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
|
1435
|
+
* emit_defaults: set true to emit 0/false values (default is to omit them)
|
1265
1436
|
*/
|
1266
1437
|
VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
1267
1438
|
VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
|
@@ -1301,7 +1472,8 @@ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1301
1472
|
stackenv_init(&se, "Error occurred during encoding: %s");
|
1302
1473
|
printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink);
|
1303
1474
|
|
1304
|
-
putmsg(msg_rb, desc, upb_json_printer_input(printer), 0,
|
1475
|
+
putmsg(msg_rb, desc, upb_json_printer_input(printer), 0,
|
1476
|
+
RTEST(emit_defaults), true, true);
|
1305
1477
|
|
1306
1478
|
ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding());
|
1307
1479
|
|