| 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 |