|
|
|
@ -914,13 +914,9 @@ void stringsink_uninit(stringsink *sink) { |
|
|
|
|
// semantics, which means that we have true field presence, we will want to
|
|
|
|
|
// modify msgvisitor so that it emits all present fields rather than all
|
|
|
|
|
// non-default-value fields.
|
|
|
|
|
//
|
|
|
|
|
// Likewise, when implementing JSON serialization, we may need to have a
|
|
|
|
|
// 'verbose' mode that outputs all fields and a 'concise' mode that outputs only
|
|
|
|
|
// those with non-default values.
|
|
|
|
|
|
|
|
|
|
static void putmsg(VALUE msg, const Descriptor* desc, |
|
|
|
|
upb_sink *sink, int depth); |
|
|
|
|
upb_sink *sink, int depth, bool emit_defaults); |
|
|
|
|
|
|
|
|
|
static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { |
|
|
|
|
upb_selector_t ret; |
|
|
|
@ -952,7 +948,7 @@ static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink, |
|
|
|
|
int depth) { |
|
|
|
|
int depth, bool emit_defaults) { |
|
|
|
|
upb_sink subsink; |
|
|
|
|
VALUE descriptor; |
|
|
|
|
Descriptor* subdesc; |
|
|
|
@ -963,12 +959,12 @@ static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink, |
|
|
|
|
subdesc = ruby_to_Descriptor(descriptor); |
|
|
|
|
|
|
|
|
|
upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink); |
|
|
|
|
putmsg(submsg, subdesc, &subsink, depth + 1); |
|
|
|
|
putmsg(submsg, subdesc, &subsink, depth + 1, emit_defaults); |
|
|
|
|
upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink, |
|
|
|
|
int depth) { |
|
|
|
|
int depth, bool emit_defaults) { |
|
|
|
|
upb_sink subsink; |
|
|
|
|
upb_fieldtype_t type = upb_fielddef_type(f); |
|
|
|
|
upb_selector_t sel = 0; |
|
|
|
@ -1005,7 +1001,7 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink, |
|
|
|
|
putstr(*((VALUE *)memory), f, &subsink); |
|
|
|
|
break; |
|
|
|
|
case UPB_TYPE_MESSAGE: |
|
|
|
|
putsubmsg(*((VALUE *)memory), f, &subsink, depth); |
|
|
|
|
putsubmsg(*((VALUE *)memory), f, &subsink, depth, emit_defaults); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
#undef T |
|
|
|
@ -1019,7 +1015,8 @@ static void put_ruby_value(VALUE value, |
|
|
|
|
const upb_fielddef *f, |
|
|
|
|
VALUE type_class, |
|
|
|
|
int depth, |
|
|
|
|
upb_sink *sink) { |
|
|
|
|
upb_sink *sink, |
|
|
|
|
bool emit_defaults) { |
|
|
|
|
upb_selector_t sel = 0; |
|
|
|
|
if (upb_fielddef_isprimitive(f)) { |
|
|
|
|
sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); |
|
|
|
@ -1059,12 +1056,12 @@ static void put_ruby_value(VALUE value, |
|
|
|
|
putstr(value, f, sink); |
|
|
|
|
break; |
|
|
|
|
case UPB_TYPE_MESSAGE: |
|
|
|
|
putsubmsg(value, f, sink, depth); |
|
|
|
|
putsubmsg(value, f, sink, depth, emit_defaults); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink, |
|
|
|
|
int depth) { |
|
|
|
|
int depth, bool emit_defaults) { |
|
|
|
|
Map* self; |
|
|
|
|
upb_sink subsink; |
|
|
|
|
const upb_fielddef* key_field; |
|
|
|
@ -1090,9 +1087,9 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink, |
|
|
|
|
&entry_sink); |
|
|
|
|
upb_sink_startmsg(&entry_sink); |
|
|
|
|
|
|
|
|
|
put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink); |
|
|
|
|
put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink, emit_defaults); |
|
|
|
|
put_ruby_value(value, value_field, self->value_type_class, depth + 1, |
|
|
|
|
&entry_sink); |
|
|
|
|
&entry_sink, emit_defaults); |
|
|
|
|
|
|
|
|
|
upb_sink_endmsg(&entry_sink, &status); |
|
|
|
|
upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); |
|
|
|
@ -1102,7 +1099,7 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void putmsg(VALUE msg_rb, const Descriptor* desc, |
|
|
|
|
upb_sink *sink, int depth) { |
|
|
|
|
upb_sink *sink, int depth, bool emit_defaults) { |
|
|
|
|
MessageHeader* msg; |
|
|
|
|
upb_msg_field_iter i; |
|
|
|
|
upb_status status; |
|
|
|
@ -1144,31 +1141,31 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc, |
|
|
|
|
|
|
|
|
|
if (is_map_field(f)) { |
|
|
|
|
VALUE map = DEREF(msg, offset, VALUE); |
|
|
|
|
if (map != Qnil) { |
|
|
|
|
putmap(map, f, sink, depth); |
|
|
|
|
if (map != Qnil || emit_defaults) { |
|
|
|
|
putmap(map, f, sink, depth, emit_defaults); |
|
|
|
|
} |
|
|
|
|
} else if (upb_fielddef_isseq(f)) { |
|
|
|
|
VALUE ary = DEREF(msg, offset, VALUE); |
|
|
|
|
if (ary != Qnil) { |
|
|
|
|
putary(ary, f, sink, depth); |
|
|
|
|
putary(ary, f, sink, depth, emit_defaults); |
|
|
|
|
} |
|
|
|
|
} else if (upb_fielddef_isstring(f)) { |
|
|
|
|
VALUE str = DEREF(msg, offset, VALUE); |
|
|
|
|
if (is_matching_oneof || RSTRING_LEN(str) > 0) { |
|
|
|
|
if (is_matching_oneof || emit_defaults || RSTRING_LEN(str) > 0) { |
|
|
|
|
putstr(str, f, sink); |
|
|
|
|
} |
|
|
|
|
} else if (upb_fielddef_issubmsg(f)) { |
|
|
|
|
putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth); |
|
|
|
|
putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth, emit_defaults); |
|
|
|
|
} else { |
|
|
|
|
upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); |
|
|
|
|
|
|
|
|
|
#define T(upbtypeconst, upbtype, ctype, default_value) \ |
|
|
|
|
case upbtypeconst: { \
|
|
|
|
|
ctype value = DEREF(msg, offset, ctype); \
|
|
|
|
|
if (is_matching_oneof || value != default_value) { \
|
|
|
|
|
upb_sink_put##upbtype(sink, sel, value); \
|
|
|
|
|
} \
|
|
|
|
|
} \
|
|
|
|
|
#define T(upbtypeconst, upbtype, ctype, default_value) \ |
|
|
|
|
case upbtypeconst: { \
|
|
|
|
|
ctype value = DEREF(msg, offset, ctype); \
|
|
|
|
|
if (is_matching_oneof || emit_defaults || value != default_value) { \
|
|
|
|
|
upb_sink_put##upbtype(sink, sel, value); \
|
|
|
|
|
} \
|
|
|
|
|
} \
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
switch (upb_fielddef_type(f)) { |
|
|
|
@ -1246,7 +1243,7 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) { |
|
|
|
|
stackenv_init(&se, "Error occurred during encoding: %s"); |
|
|
|
|
encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink); |
|
|
|
|
|
|
|
|
|
putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0); |
|
|
|
|
putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false); |
|
|
|
|
|
|
|
|
|
ret = rb_str_new(sink.ptr, sink.len); |
|
|
|
|
|
|
|
|
@ -1268,6 +1265,7 @@ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { |
|
|
|
|
Descriptor* desc = ruby_to_Descriptor(descriptor); |
|
|
|
|
VALUE msg_rb; |
|
|
|
|
VALUE preserve_proto_fieldnames = Qfalse; |
|
|
|
|
VALUE emit_defaults = Qfalse; |
|
|
|
|
stringsink sink; |
|
|
|
|
|
|
|
|
|
if (argc < 1 || argc > 2) { |
|
|
|
@ -1283,6 +1281,9 @@ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { |
|
|
|
|
} |
|
|
|
|
preserve_proto_fieldnames = rb_hash_lookup2( |
|
|
|
|
hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse); |
|
|
|
|
|
|
|
|
|
emit_defaults = rb_hash_lookup2( |
|
|
|
|
hash_args, ID2SYM(rb_intern("emit_defaults")), Qfalse); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
stringsink_init(&sink); |
|
|
|
@ -1297,7 +1298,7 @@ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { |
|
|
|
|
stackenv_init(&se, "Error occurred during encoding: %s"); |
|
|
|
|
printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink); |
|
|
|
|
|
|
|
|
|
putmsg(msg_rb, desc, upb_json_printer_input(printer), 0); |
|
|
|
|
putmsg(msg_rb, desc, upb_json_printer_input(printer), 0, RTEST(emit_defaults)); |
|
|
|
|
|
|
|
|
|
ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding()); |
|
|
|
|
|
|
|
|
|