google-protobuf 3.6.1-x64-mingw32 → 3.7.0.rc.2-x64-mingw32
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 +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.so +0 -0
- data/lib/google/2.4/protobuf_c.so +0 -0
- data/lib/google/2.5/protobuf_c.so +0 -0
- data/lib/google/2.6/protobuf_c.so +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 -8
- data/lib/google/2.0/protobuf_c.so +0 -0
- data/lib/google/2.1/protobuf_c.so +0 -0
- data/lib/google/2.2/protobuf_c.so +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
|
|