OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2014 Google Inc. All rights reserved. | 2 // Copyright 2014 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 } | 633 } |
634 | 634 |
635 static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) { | 635 static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) { |
636 if (desc->fill_method == NULL) { | 636 if (desc->fill_method == NULL) { |
637 desc->fill_method = new_fillmsg_decodermethod( | 637 desc->fill_method = new_fillmsg_decodermethod( |
638 desc, &desc->fill_method); | 638 desc, &desc->fill_method); |
639 } | 639 } |
640 return desc->fill_method; | 640 return desc->fill_method; |
641 } | 641 } |
642 | 642 |
| 643 static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { |
| 644 if (desc->json_fill_method == NULL) { |
| 645 desc->json_fill_method = |
| 646 upb_json_parsermethod_new(desc->msgdef, &desc->json_fill_method); |
| 647 } |
| 648 return desc->json_fill_method; |
| 649 } |
| 650 |
643 | 651 |
644 // Stack-allocated context during an encode/decode operation. Contains the upb | 652 // Stack-allocated context during an encode/decode operation. Contains the upb |
645 // environment and its stack-based allocator, an initial buffer for allocations | 653 // environment and its stack-based allocator, an initial buffer for allocations |
646 // to avoid malloc() when possible, and a template for Ruby exception messages | 654 // to avoid malloc() when possible, and a template for Ruby exception messages |
647 // if any error occurs. | 655 // if any error occurs. |
648 #define STACK_ENV_STACKBYTES 4096 | 656 #define STACK_ENV_STACKBYTES 4096 |
649 typedef struct { | 657 typedef struct { |
650 upb_env env; | 658 upb_env env; |
651 upb_seededalloc alloc; | |
652 const char* ruby_error_template; | 659 const char* ruby_error_template; |
653 char allocbuf[STACK_ENV_STACKBYTES]; | 660 char allocbuf[STACK_ENV_STACKBYTES]; |
654 } stackenv; | 661 } stackenv; |
655 | 662 |
656 static void stackenv_init(stackenv* se, const char* errmsg); | 663 static void stackenv_init(stackenv* se, const char* errmsg); |
657 static void stackenv_uninit(stackenv* se); | 664 static void stackenv_uninit(stackenv* se); |
658 | 665 |
659 // Callback invoked by upb if any error occurs during parsing or serialization. | 666 // Callback invoked by upb if any error occurs during parsing or serialization. |
660 static bool env_error_func(void* ud, const upb_status* status) { | 667 static bool env_error_func(void* ud, const upb_status* status) { |
661 stackenv* se = ud; | 668 stackenv* se = ud; |
662 // Free the env -- rb_raise will longjmp up the stack past the encode/decode | 669 // Free the env -- rb_raise will longjmp up the stack past the encode/decode |
663 // function so it would not otherwise have been freed. | 670 // function so it would not otherwise have been freed. |
664 stackenv_uninit(se); | 671 stackenv_uninit(se); |
665 | 672 |
666 // TODO(haberman): have a way to verify that this is actually a parse error, | 673 // TODO(haberman): have a way to verify that this is actually a parse error, |
667 // instead of just throwing "parse error" unconditionally. | 674 // instead of just throwing "parse error" unconditionally. |
668 rb_raise(cParseError, se->ruby_error_template, upb_status_errmsg(status)); | 675 rb_raise(cParseError, se->ruby_error_template, upb_status_errmsg(status)); |
669 // Never reached: rb_raise() always longjmp()s up the stack, past all of our | 676 // Never reached: rb_raise() always longjmp()s up the stack, past all of our |
670 // code, back to Ruby. | 677 // code, back to Ruby. |
671 return false; | 678 return false; |
672 } | 679 } |
673 | 680 |
674 static void stackenv_init(stackenv* se, const char* errmsg) { | 681 static void stackenv_init(stackenv* se, const char* errmsg) { |
675 se->ruby_error_template = errmsg; | 682 se->ruby_error_template = errmsg; |
676 upb_env_init(&se->env); | 683 upb_env_init2(&se->env, se->allocbuf, sizeof(se->allocbuf), NULL); |
677 upb_seededalloc_init(&se->alloc, &se->allocbuf, STACK_ENV_STACKBYTES); | |
678 upb_env_setallocfunc( | |
679 &se->env, upb_seededalloc_getallocfunc(&se->alloc), &se->alloc); | |
680 upb_env_seterrorfunc(&se->env, env_error_func, se); | 684 upb_env_seterrorfunc(&se->env, env_error_func, se); |
681 } | 685 } |
682 | 686 |
683 static void stackenv_uninit(stackenv* se) { | 687 static void stackenv_uninit(stackenv* se) { |
684 upb_env_uninit(&se->env); | 688 upb_env_uninit(&se->env); |
685 upb_seededalloc_uninit(&se->alloc); | |
686 } | 689 } |
687 | 690 |
688 /* | 691 /* |
689 * call-seq: | 692 * call-seq: |
690 * MessageClass.decode(data) => message | 693 * MessageClass.decode(data) => message |
691 * | 694 * |
692 * Decodes the given data (as a string containing bytes in protocol buffers wire | 695 * Decodes the given data (as a string containing bytes in protocol buffers wire |
693 * format) under the interpretration given by this message class's definition | 696 * format) under the interpretration given by this message class's definition |
694 * and returns a message object with the corresponding field values. | 697 * and returns a message object with the corresponding field values. |
695 */ | 698 */ |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 rb_raise(rb_eArgError, "Expected string for JSON data."); | 748 rb_raise(rb_eArgError, "Expected string for JSON data."); |
746 } | 749 } |
747 // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to | 750 // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to |
748 // convert, because string handlers pass data directly to message string | 751 // convert, because string handlers pass data directly to message string |
749 // fields. | 752 // fields. |
750 | 753 |
751 msg_rb = rb_class_new_instance(0, NULL, msgklass); | 754 msg_rb = rb_class_new_instance(0, NULL, msgklass); |
752 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); | 755 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); |
753 | 756 |
754 { | 757 { |
| 758 const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc); |
755 stackenv se; | 759 stackenv se; |
756 upb_sink sink; | 760 upb_sink sink; |
757 upb_json_parser* parser; | 761 upb_json_parser* parser; |
758 stackenv_init(&se, "Error occurred during parsing: %s"); | 762 stackenv_init(&se, "Error occurred during parsing: %s"); |
759 | 763 |
760 upb_sink_reset(&sink, get_fill_handlers(desc), msg); | 764 upb_sink_reset(&sink, get_fill_handlers(desc), msg); |
761 parser = upb_json_parser_create(&se.env, &sink); | 765 parser = upb_json_parser_create(&se.env, method, &sink); |
762 upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), | 766 upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), |
763 upb_json_parser_input(parser)); | 767 upb_json_parser_input(parser)); |
764 | 768 |
765 stackenv_uninit(&se); | 769 stackenv_uninit(&se); |
766 } | 770 } |
767 | 771 |
768 return msg_rb; | 772 return msg_rb; |
769 } | 773 } |
770 | 774 |
771 // ----------------------------------------------------------------------------- | 775 // ----------------------------------------------------------------------------- |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 rb_raise(rb_eRuntimeError, | 1038 rb_raise(rb_eRuntimeError, |
1035 "Maximum recursion depth exceeded during encoding."); | 1039 "Maximum recursion depth exceeded during encoding."); |
1036 } | 1040 } |
1037 | 1041 |
1038 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); | 1042 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); |
1039 | 1043 |
1040 for (upb_msg_field_begin(&i, desc->msgdef); | 1044 for (upb_msg_field_begin(&i, desc->msgdef); |
1041 !upb_msg_field_done(&i); | 1045 !upb_msg_field_done(&i); |
1042 upb_msg_field_next(&i)) { | 1046 upb_msg_field_next(&i)) { |
1043 upb_fielddef *f = upb_msg_iter_field(&i); | 1047 upb_fielddef *f = upb_msg_iter_field(&i); |
| 1048 bool is_matching_oneof = false; |
1044 uint32_t offset = | 1049 uint32_t offset = |
1045 desc->layout->fields[upb_fielddef_index(f)].offset + | 1050 desc->layout->fields[upb_fielddef_index(f)].offset + |
1046 sizeof(MessageHeader); | 1051 sizeof(MessageHeader); |
1047 | 1052 |
1048 if (upb_fielddef_containingoneof(f)) { | 1053 if (upb_fielddef_containingoneof(f)) { |
1049 uint32_t oneof_case_offset = | 1054 uint32_t oneof_case_offset = |
1050 desc->layout->fields[upb_fielddef_index(f)].case_offset + | 1055 desc->layout->fields[upb_fielddef_index(f)].case_offset + |
1051 sizeof(MessageHeader); | 1056 sizeof(MessageHeader); |
1052 // For a oneof, check that this field is actually present -- skip all the | 1057 // For a oneof, check that this field is actually present -- skip all the |
1053 // below if not. | 1058 // below if not. |
1054 if (DEREF(msg, oneof_case_offset, uint32_t) != | 1059 if (DEREF(msg, oneof_case_offset, uint32_t) != |
1055 upb_fielddef_number(f)) { | 1060 upb_fielddef_number(f)) { |
1056 continue; | 1061 continue; |
1057 } | 1062 } |
1058 // Otherwise, fall through to the appropriate singular-field handler | 1063 // Otherwise, fall through to the appropriate singular-field handler |
1059 // below. | 1064 // below. |
| 1065 is_matching_oneof = true; |
1060 } | 1066 } |
1061 | 1067 |
1062 if (is_map_field(f)) { | 1068 if (is_map_field(f)) { |
1063 VALUE map = DEREF(msg, offset, VALUE); | 1069 VALUE map = DEREF(msg, offset, VALUE); |
1064 if (map != Qnil) { | 1070 if (map != Qnil) { |
1065 putmap(map, f, sink, depth); | 1071 putmap(map, f, sink, depth); |
1066 } | 1072 } |
1067 } else if (upb_fielddef_isseq(f)) { | 1073 } else if (upb_fielddef_isseq(f)) { |
1068 VALUE ary = DEREF(msg, offset, VALUE); | 1074 VALUE ary = DEREF(msg, offset, VALUE); |
1069 if (ary != Qnil) { | 1075 if (ary != Qnil) { |
1070 putary(ary, f, sink, depth); | 1076 putary(ary, f, sink, depth); |
1071 } | 1077 } |
1072 } else if (upb_fielddef_isstring(f)) { | 1078 } else if (upb_fielddef_isstring(f)) { |
1073 VALUE str = DEREF(msg, offset, VALUE); | 1079 VALUE str = DEREF(msg, offset, VALUE); |
1074 if (RSTRING_LEN(str) > 0) { | 1080 if (is_matching_oneof || RSTRING_LEN(str) > 0) { |
1075 putstr(str, f, sink); | 1081 putstr(str, f, sink); |
1076 } | 1082 } |
1077 } else if (upb_fielddef_issubmsg(f)) { | 1083 } else if (upb_fielddef_issubmsg(f)) { |
1078 putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth); | 1084 putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth); |
1079 } else { | 1085 } else { |
1080 upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); | 1086 upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); |
1081 | 1087 |
1082 #define T(upbtypeconst, upbtype, ctype, default_value) \ | 1088 #define T(upbtypeconst, upbtype, ctype, default_value) \ |
1083 case upbtypeconst: { \ | 1089 case upbtypeconst: { \ |
1084 ctype value = DEREF(msg, offset, ctype); \ | 1090 ctype value = DEREF(msg, offset, ctype); \ |
1085 if (value != default_value) { \ | 1091 if (is_matching_oneof || value != default_value) { \ |
1086 upb_sink_put##upbtype(sink, sel, value); \ | 1092 upb_sink_put##upbtype(sink, sel, value); \ |
1087 } \ | 1093 } \ |
1088 } \ | 1094 } \ |
1089 break; | 1095 break; |
1090 | 1096 |
1091 switch (upb_fielddef_type(f)) { | 1097 switch (upb_fielddef_type(f)) { |
1092 T(UPB_TYPE_FLOAT, float, float, 0.0) | 1098 T(UPB_TYPE_FLOAT, float, float, 0.0) |
1093 T(UPB_TYPE_DOUBLE, double, double, 0.0) | 1099 T(UPB_TYPE_DOUBLE, double, double, 0.0) |
1094 T(UPB_TYPE_BOOL, bool, uint8_t, 0) | 1100 T(UPB_TYPE_BOOL, bool, uint8_t, 0) |
1095 case UPB_TYPE_ENUM: | 1101 case UPB_TYPE_ENUM: |
(...skipping 16 matching lines...) Expand all Loading... |
1112 } | 1118 } |
1113 | 1119 |
1114 static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { | 1120 static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { |
1115 if (desc->pb_serialize_handlers == NULL) { | 1121 if (desc->pb_serialize_handlers == NULL) { |
1116 desc->pb_serialize_handlers = | 1122 desc->pb_serialize_handlers = |
1117 upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers); | 1123 upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers); |
1118 } | 1124 } |
1119 return desc->pb_serialize_handlers; | 1125 return desc->pb_serialize_handlers; |
1120 } | 1126 } |
1121 | 1127 |
1122 static const upb_handlers* msgdef_json_serialize_handlers(Descriptor* desc) { | 1128 static const upb_handlers* msgdef_json_serialize_handlers( |
1123 if (desc->json_serialize_handlers == NULL) { | 1129 Descriptor* desc, bool preserve_proto_fieldnames) { |
1124 desc->json_serialize_handlers = | 1130 if (preserve_proto_fieldnames) { |
1125 upb_json_printer_newhandlers( | 1131 if (desc->json_serialize_handlers == NULL) { |
1126 desc->msgdef, &desc->json_serialize_handlers); | 1132 desc->json_serialize_handlers = |
| 1133 upb_json_printer_newhandlers( |
| 1134 desc->msgdef, true, &desc->json_serialize_handlers); |
| 1135 } |
| 1136 return desc->json_serialize_handlers; |
| 1137 } else { |
| 1138 if (desc->json_serialize_handlers_preserve == NULL) { |
| 1139 desc->json_serialize_handlers_preserve = |
| 1140 upb_json_printer_newhandlers( |
| 1141 desc->msgdef, false, &desc->json_serialize_handlers_preserve); |
| 1142 } |
| 1143 return desc->json_serialize_handlers_preserve; |
1127 } | 1144 } |
1128 return desc->json_serialize_handlers; | |
1129 } | 1145 } |
1130 | 1146 |
1131 /* | 1147 /* |
1132 * call-seq: | 1148 * call-seq: |
1133 * MessageClass.encode(msg) => bytes | 1149 * MessageClass.encode(msg) => bytes |
1134 * | 1150 * |
1135 * Encodes the given message object to its serialized form in protocol buffers | 1151 * Encodes the given message object to its serialized form in protocol buffers |
1136 * wire format. | 1152 * wire format. |
1137 */ | 1153 */ |
1138 VALUE Message_encode(VALUE klass, VALUE msg_rb) { | 1154 VALUE Message_encode(VALUE klass, VALUE msg_rb) { |
(...skipping 24 matching lines...) Expand all Loading... |
1163 return ret; | 1179 return ret; |
1164 } | 1180 } |
1165 } | 1181 } |
1166 | 1182 |
1167 /* | 1183 /* |
1168 * call-seq: | 1184 * call-seq: |
1169 * MessageClass.encode_json(msg) => json_string | 1185 * MessageClass.encode_json(msg) => json_string |
1170 * | 1186 * |
1171 * Encodes the given message object into its serialized JSON representation. | 1187 * Encodes the given message object into its serialized JSON representation. |
1172 */ | 1188 */ |
1173 VALUE Message_encode_json(VALUE klass, VALUE msg_rb) { | 1189 VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { |
1174 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); | 1190 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); |
1175 Descriptor* desc = ruby_to_Descriptor(descriptor); | 1191 Descriptor* desc = ruby_to_Descriptor(descriptor); |
| 1192 VALUE msg_rb; |
| 1193 VALUE preserve_proto_fieldnames = Qfalse; |
| 1194 stringsink sink; |
1176 | 1195 |
1177 stringsink sink; | 1196 if (argc < 1 || argc > 2) { |
| 1197 rb_raise(rb_eArgError, "Expected 1 or 2 arguments."); |
| 1198 } |
| 1199 |
| 1200 msg_rb = argv[0]; |
| 1201 |
| 1202 if (argc == 2) { |
| 1203 VALUE hash_args = argv[1]; |
| 1204 if (TYPE(hash_args) != T_HASH) { |
| 1205 rb_raise(rb_eArgError, "Expected hash arguments."); |
| 1206 } |
| 1207 preserve_proto_fieldnames = rb_hash_lookup2( |
| 1208 hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse); |
| 1209 } |
| 1210 |
1178 stringsink_init(&sink); | 1211 stringsink_init(&sink); |
1179 | 1212 |
1180 { | 1213 { |
1181 const upb_handlers* serialize_handlers = | 1214 const upb_handlers* serialize_handlers = |
1182 msgdef_json_serialize_handlers(desc); | 1215 msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames)); |
1183 upb_json_printer* printer; | 1216 upb_json_printer* printer; |
1184 stackenv se; | 1217 stackenv se; |
1185 VALUE ret; | 1218 VALUE ret; |
1186 | 1219 |
1187 stackenv_init(&se, "Error occurred during encoding: %s"); | 1220 stackenv_init(&se, "Error occurred during encoding: %s"); |
1188 printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink); | 1221 printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink); |
1189 | 1222 |
1190 putmsg(msg_rb, desc, upb_json_printer_input(printer), 0); | 1223 putmsg(msg_rb, desc, upb_json_printer_input(printer), 0); |
1191 | 1224 |
1192 ret = rb_str_new(sink.ptr, sink.len); | 1225 ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding()); |
1193 | 1226 |
1194 stackenv_uninit(&se); | 1227 stackenv_uninit(&se); |
1195 stringsink_uninit(&sink); | 1228 stringsink_uninit(&sink); |
1196 | 1229 |
1197 return ret; | 1230 return ret; |
1198 } | 1231 } |
1199 } | 1232 } |
1200 | 1233 |
OLD | NEW |