From dd536fd567b2ba9bed67a0094c5cd905c774f951 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Wed, 5 Jul 2017 15:12:59 -0700 Subject: Be more picky about command-line args in upbc. --- tools/upbc.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/upbc.lua b/tools/upbc.lua index bf9a68d..9d9531c 100644 --- a/tools/upbc.lua +++ b/tools/upbc.lua @@ -15,8 +15,13 @@ local upb = require "upb" local generate_upbdefs = false for _, argument in ipairs(arg) do - if argument == "--generate-upbdefs" then - generate_upbdefs = true + if argument.sub(argument, 1, 2) == "--" then + if argument == "--generate-upbdefs" then + generate_upbdefs = true + else + print("Unknown flag: " .. argument) + return 1 + end else src = argument end -- cgit v1.2.3 From 1aafd4111b9b6d08d2d0937b0f396a4caa9ea04d Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Sat, 8 Jul 2017 00:00:05 -0700 Subject: A good start on upb_encode and upb_decode. --- .gitmodules | 3 + Makefile | 19 +- tests/conformance_upb.c | 23 ++- third_party/protobuf | 1 + tools/make_c_api.lua | 139 ++++++++++--- upb/decode.c | 247 +++++++++++++++++++++++ upb/decode.h | 17 ++ upb/encode.c | 512 ++++++++++++++++++++++++++++++++++++++++++++++++ upb/encode.h | 17 ++ upb/msg.c | 10 +- upb/msg.h | 1 + upb/structs.int.h | 18 ++ upb/upb.h | 3 + 13 files changed, 962 insertions(+), 48 deletions(-) create mode 100644 .gitmodules create mode 160000 third_party/protobuf create mode 100644 upb/decode.c create mode 100644 upb/decode.h create mode 100644 upb/encode.c create mode 100644 upb/encode.h create mode 100644 upb/structs.int.h diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8b52c1d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third_party/protobuf"] + path = third_party/protobuf + url = https://github.com/google/protobuf.git diff --git a/Makefile b/Makefile index 597476c..390e7af 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,7 @@ clean_leave_profile: @rm -rf obj lib @rm -f tests/google_message?.h @rm -f tests/json/test.upbdefs.o - @rm -f $(TESTS) tests/testmain.o tests/t.* + @rm -f $(TESTS) tests/testmain.o tests/t.* tests/conformance_upb @rm -rf tools/upbc deps @rm -rf upb/bindings/python/build @rm -f upb/bindings/ruby/Makefile @@ -148,7 +148,9 @@ make_objs_cc = $$(patsubst upb/$$(pc).cc,obj/upb/$$(pc).$(1),$$($$(call to_srcs, # Core libraries (ie. not bindings). ############################################################### upb_SRCS = \ + upb/decode.c \ upb/def.c \ + upb/encode.c \ upb/handlers.c \ upb/msg.c \ upb/refcounted.c \ @@ -361,6 +363,21 @@ test: done; @echo "All tests passed!" +obj/conformance_protos: obj/conformance_protos.pb tools/upbc + cd obj && ../tools/upbc conformance_protos.pb && touch conformance_protos + +obj/conformance_protos.pb: third_party/protobuf/autogen.sh + protoc -Ithird_party/protobuf/conformance -Ithird_party/protobuf/src --include_imports \ + third_party/protobuf/conformance/conformance.proto \ + third_party/protobuf/src/google/protobuf/test_messages_proto3.proto \ + -o obj/conformance_protos.pb + +third_party/protouf/autogen.sh: .gitmodules + git submodule init && git submodule update + +tests/conformance_upb: tests/conformance_upb.c lib/libupb.a obj/conformance_protos + $(CC) -o tests/conformance_upb tests/conformance_upb.c -Iobj -I. $(CPPFLAGS) $(CFLAGS) obj/conformance.upb.c obj/google/protobuf/*.upb.c lib/libupb.a + # Google protobuf binding ###################################################### diff --git a/tests/conformance_upb.c b/tests/conformance_upb.c index 9f83e80..e1221b2 100644 --- a/tests/conformance_upb.c +++ b/tests/conformance_upb.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -52,7 +53,7 @@ void DoTest( if (!test_message) { /* TODO(haberman): return details. */ - static char msg[] = "Parse error (no more details available)."; + static const char msg[] = "Parse error (no more details available)."; conformance_ConformanceResponse_set_parse_error( response, upb_stringview_make(msg, sizeof(msg))); return; @@ -60,20 +61,20 @@ void DoTest( break; case conformance_ConformanceRequest_payload_json_payload: { - static char msg[] = "JSON support not yet implemented."; + static const char msg[] = "JSON support not yet implemented."; conformance_ConformanceResponse_set_skipped( response, upb_stringview_make(msg, sizeof(msg))); return; } case conformance_ConformanceRequest_payload_NOT_SET: - fprintf(stderr, "conformance_upb: Request didn't have payload."); - exit(1); + fprintf(stderr, "conformance_upb: Request didn't have payload.\n"); + return; } switch (conformance_ConformanceRequest_requested_output_format(request)) { case conformance_UNSPECIFIED: - fprintf(stderr, "conformance_upb: Unspecified output format."); + fprintf(stderr, "conformance_upb: Unspecified output format.\n"); exit(1); case conformance_PROTOBUF: { @@ -81,8 +82,10 @@ void DoTest( char *serialized = protobuf_test_messages_proto3_TestAllTypes_serialize( test_message, env, &serialized_len); if (!serialized) { - fprintf(stderr, "conformance_upb: Error serialiing."); - exit(1); + static const char msg[] = "Error serializing."; + conformance_ConformanceResponse_set_serialize_error( + response, upb_stringview_make(msg, sizeof(msg))); + return; } conformance_ConformanceResponse_set_protobuf_payload( response, upb_stringview_make(serialized, serialized_len)); @@ -90,14 +93,14 @@ void DoTest( } case conformance_JSON: { - static char msg[] = "JSON support not yet implemented."; + static const char msg[] = "JSON support not yet implemented."; conformance_ConformanceResponse_set_skipped( response, upb_stringview_make(msg, sizeof(msg))); break; } default: - fprintf(stderr, "conformance_upb: Unknown output format: %d", + fprintf(stderr, "conformance_upb: Unknown output format: %d\n", conformance_ConformanceRequest_requested_output_format(request)); exit(1); } @@ -111,7 +114,7 @@ bool DoTestIo() { char *serialized_input; char *serialized_output; uint32_t input_size; - size_t output_size; + size_t output_size = 0; conformance_ConformanceRequest *request; conformance_ConformanceResponse *response; diff --git a/third_party/protobuf b/third_party/protobuf new file mode 160000 index 0000000..6bd51a5 --- /dev/null +++ b/third_party/protobuf @@ -0,0 +1 @@ +Subproject commit 6bd51a59df41b99058ec8c2b03a177a218267ce5 diff --git a/tools/make_c_api.lua b/tools/make_c_api.lua index aaf5d1e..62fd370 100644 --- a/tools/make_c_api.lua +++ b/tools/make_c_api.lua @@ -47,7 +47,6 @@ local function to_preproc(...) return string.upper(to_cident(...)) end - -- Strips away last path element, ie: -- foo.Bar.Baz -> foo.Bar local function remove_name(name) @@ -60,6 +59,10 @@ local function remove_name(name) return string.sub(name, 1, package_end) end +local function enum_value_symbol(enumdef, name) + return to_cident(remove_name(enumdef:full_name())) .. "_" .. name +end + local function dump_enum_vals(enumdef, append) local enum_vals = {} @@ -96,7 +99,7 @@ local function dump_enum_vals(enumdef, append) local cident = to_cident(remove_name(enumdef:full_name())) for i, pair in ipairs(enum_vals) do k, v = pair[1], pair[2] - append(' %s = %d', cident .. "_" .. k, v) + append(' %s = %d', enum_value_symbol(enumdef, k), v) if i == #enum_vals then append('\n') else @@ -105,6 +108,20 @@ local function dump_enum_vals(enumdef, append) end end +local function field_default(field) + if field:type() == upb.TYPE_MESSAGE then + return "NULL" + elseif field:type() == upb.TYPE_STRING or + field:type() == upb.TYPE_BYTES then + local default = field:default() or "" + return string.format('upb_stringview_make("%s", strlen("%s"))', field:default(), field:default()) + elseif field:type() == upb.TYPE_ENUM then + return enum_value_symbol(field:subdef(), field:default()) + else + return field:default(); + end +end + local function ctype(field) if field:label() == upb.LABEL_REPEATED then return "upb_array*" @@ -134,19 +151,18 @@ end local function field_layout_rank(field) -- Order: -- 1, 2, 3. primitive fields (8, 4, 1 byte) - -- 4. oneof fields - -- 5. string fields - -- 6. submessage fields - -- 7. repeated fields + -- 4. string fields + -- 5. submessage fields + -- 6. repeated fields local rank if field:containing_oneof() then - rank = 4 + rank = 100 -- These go last (actually we skip them). elseif field:label() == upb.LABEL_REPEATED then - rank = 7 - elseif field:type() == upb.TYPE_MESSAGE then rank = 6 - elseif field:type() == upb.TYPE_STRING or field:type() == upb.TYPE_BYTES then + elseif field:type() == upb.TYPE_MESSAGE then rank = 5 + elseif field:type() == upb.TYPE_STRING or field:type() == upb.TYPE_BYTES then + rank = 4 elseif field:type() == upb.TYPE_BOOL then rank = 3 elseif field:type() == upb.TYPE_FLOAT or @@ -257,6 +273,8 @@ local function write_c_file(filedef, hfilename, append) emit_file_warning(filedef, append) append('#include \n') + append('#include "upb/decode.h"\n\n') + append('#include "upb/encode.h"\n\n') append('#include "upb/msg.h"\n') append('#include "upb/upb.h"\n') append('#include "%s"\n\n', hfilename) @@ -273,13 +291,29 @@ local function write_c_file(filedef, hfilename, append) local fields_array_ref = "NULL" local submsgs_array_ref = "NULL" + local oneofs_array_ref = "NULL" local field_count = 0 local submsg_count = 0 local submsg_set = {} local submsg_indexes = {} local hasbit_count = 0 local hasbit_indexes = {} - -- TODO(haberman): oneofs + local oneof_count = 0 + local oneof_indexes = {} + + -- Create a layout order for oneofs. + local oneofs_layout_order = {} + for oneof in msg:oneofs() do + table.insert(oneofs_layout_order, oneof) + end + table.sort(oneofs_layout_order, function(a, b) + return a:name() < b:name() + end) + + for _, oneof in ipairs(oneofs_layout_order) do + oneof_indexes[oneof] = oneof_count + oneof_count = oneof_count + 1 + end -- Create a layout order for fields. We use this order for the struct and -- for offsets, but our list of fields we keep in field number order. @@ -301,6 +335,8 @@ local function write_c_file(filedef, hfilename, append) end) append('struct %s {\n', msgname) + + -- Non-oneof fields. for _, field in ipairs(fields_layout_order) do field_count = field_count + 1 @@ -309,15 +345,46 @@ local function write_c_file(filedef, hfilename, append) submsg_set[field:subdef()] = true end - if has_hasbit(field) then - hasbit_indexes[field] = hasbit_count - hasbit_count = hasbit_count + 1 + if field:containing_oneof() then + -- Do nothing now + else + if has_hasbit(field) then + hasbit_indexes[field] = hasbit_count + hasbit_count = hasbit_count + 1 + end + + append(' %s %s;\n', ctype(field), field:name()) end + end - append(' %s %s;\n', ctype(field), field:name()) + local oneof_last_fields = {} + -- Oneof fields. + for oneof in msg:oneofs() do + local fullname = to_cident(oneof:containing_type():full_name() .. "." .. oneof:name()) + append(' union {\n') + oneof_last_fields[oneof] = "" + for field in oneof:fields() do + oneof_last_fields[oneof] = field:name() + append(' %s %s;\n', ctype(field), field:name()) + end + append(' } %s;\n', oneof:name()) + append(' %s_oneofcases %s_case;\n', fullname, oneof:name()) end + append('};\n\n') + if oneof_count > 0 then + local oneofs_array_name = msgname .. "_oneofs" + oneofs_array_ref = "&" .. oneofs_array_name .. "[0]" + append('static const upb_msglayout_oneofinit_v1 %s[%s] = {\n', + oneofs_array_name, oneof_count) + for _, oneof in ipairs(oneofs_layout_order) do + append(' {offsetof(%s, %s), offsetof(%s, %s_case)},\n', + msgname, oneof:name(), msgname, oneof:name()) + end + append('};\n\n') + end + if submsg_count > 0 then -- TODO(haberman): could save a little bit of space by only generating a -- "submsgs" array for every strongly-connected component. @@ -354,11 +421,14 @@ local function write_c_file(filedef, hfilename, append) if field:type() == upb.TYPE_MESSAGE then submsg_index = submsg_indexes[field:subdef()] end + if field:containing_oneof() then + oneof_index = oneof_indexes[field:containing_oneof()] + end -- TODO(haberman): oneofs. append(' {%s, offsetof(%s, %s), %s, %s, %s, %s, %s},\n', field:number(), msgname, - field:name(), + (field:containing_oneof() and field:containing_oneof():name()) or field:name(), hasbit_indexes[field] or "-1", oneof_index, submsg_index, @@ -371,7 +441,7 @@ local function write_c_file(filedef, hfilename, append) append('const upb_msglayout_msginit_v1 %s_msginit = {\n', msgname) append(' %s,\n', submsgs_array_ref) append(' %s,\n', fields_array_ref) - append(' NULL, /* TODO. oneofs */\n') + append(' %s,\n', oneofs_array_ref) append(' NULL, /* TODO. default_msg */\n') append(' UPB_ALIGNED_SIZEOF(%s), %s, %s, %s, %s\n', msgname, field_count, @@ -390,36 +460,49 @@ local function write_c_file(filedef, hfilename, append) append('%s *%s_parsenew(upb_stringview buf, upb_env *env) {\n', msgname, msgname) - append(' UPB_UNUSED(buf);\n') - append(' UPB_UNUSED(env);\n') - append(' return NULL;\n') + append(' %s *msg = %s_new(env);\n', msgname, msgname) + append(' if (upb_decode(buf, msg, &%s_msginit, env)) {\n', msgname) + append(' return msg;\n') + append(' } else {\n') + append(' return NULL;\n') + append(' }\n') append('}\n') append('char *%s_serialize(%s *msg, upb_env *env, size_t *size) {\n', msgname, msgname) - append(' UPB_UNUSED(msg);\n') - append(' UPB_UNUSED(env);\n') - append(' UPB_UNUSED(size);\n') - append(' return NULL; /* TODO. */\n') + append(' return upb_encode(msg, &%s_msginit, env, size);\n', msgname) append('}\n') for field in msg:fields() do local typename = ctype(field) append('%s %s_%s(const %s *msg) {\n', typename, msgname, field:name(), msgname); - append(' return msg->%s;\n', field:name()) + if field:containing_oneof() then + local oneof = field:containing_oneof() + append(' return msg->%s_case == %s ? msg->%s.%s : %s;\n', + oneof:name(), field:number(), oneof:name(), field:name(), + field_default(field)) + else + append(' return msg->%s;\n', field:name()) + end append('}\n') append('void %s_set_%s(%s *msg, %s value) {\n', msgname, field:name(), msgname, typename); - append(' msg->%s = value;\n', field:name()) + if field:containing_oneof() then + local oneof = field:containing_oneof() + append(' msg->%s.%s = value;\n', oneof:name(), field:name()) + append(' msg->%s_case = %s;\n', oneof:name(), field:number()) + else + append(' msg->%s = value;\n', field:name()) + end append('}\n') end for oneof in msg:oneofs() do local fullname = to_cident(oneof:containing_type():full_name() .. "." .. oneof:name()) append('%s_oneofcases %s_case(const %s *msg) {\n', fullname, fullname, msgname) - append(' return 0; /* TODO. */') - append('}') + append(' return msg->%s_case;\n', oneof:name()) + append('}\n') end end end diff --git a/upb/decode.c b/upb/decode.c new file mode 100644 index 0000000..3b2ea54 --- /dev/null +++ b/upb/decode.c @@ -0,0 +1,247 @@ + +#include "upb/decode.h" + +typedef enum { + UPB_WIRE_TYPE_VARINT = 0, + UPB_WIRE_TYPE_64BIT = 1, + UPB_WIRE_TYPE_DELIMITED = 2, + UPB_WIRE_TYPE_START_GROUP = 3, + UPB_WIRE_TYPE_END_GROUP = 4, + UPB_WIRE_TYPE_32BIT = 5 +} upb_wiretype_t; + +static void upb_decode_seterr(upb_env *env, const char *msg) { + upb_status status = UPB_STATUS_INIT; + upb_status_seterrmsg(&status, msg); + upb_env_reporterror(env, &status); +} + +static bool upb_decode_varint(const char **ptr, const char *limit, + uint64_t *val) { + uint8_t byte = 0x80; + int bitpos = 0; + const char *p = *ptr; + *val = 0; + + while (byte & 0x80) { + if (bitpos == 70 || p == limit) { + return false; + } + + byte = *p; + *val |= (uint64_t)(byte & 0x7F) << bitpos; + p++; + bitpos += 7; + } + + *ptr = p; + return true; +} + +static bool upb_decode_varint32(const char **ptr, const char *limit, + uint32_t *val) { + uint64_t u64; + if (!upb_decode_varint(ptr, limit, &u64) || u64 > UINT32_MAX) { + return false; + } else { + *val = u64; + return true; + } +} + +static const upb_msglayout_fieldinit_v1 *upb_find_field( + const upb_msglayout_msginit_v1 *l, uint32_t field_number) { + /* Lots of optimization opportunities here. */ + int i; + for (i = 0; i < l->field_count; i++) { + if (l->fields[i].number == field_number) { + return &l->fields[i]; + } + } + + return NULL; /* Unknown field. */ +} + +static bool upb_decode_64bit(const char **ptr, const char *limit, + uint64_t *val) { + if (limit - *ptr < 8) { + return false; + } else { + memcpy(val, *ptr, 8); + *ptr += 8; + return true; + } +} + +static bool upb_decode_32bit(const char **ptr, const char *limit, + uint32_t *val) { + if (limit - *ptr < 4) { + return false; + } else { + memcpy(val, *ptr, 4); + *ptr += 4; + return true; + } +} + +static int32_t upb_zzdec_32(uint32_t n) { + return (n >> 1) ^ -(int32_t)(n & 1); +} + +static int64_t upb_zzdec_64(uint64_t n) { + return (n >> 1) ^ -(int64_t)(n & 1); +} + +static bool upb_decode_string(const char **ptr, const char *limit, + upb_stringview *val) { + uint32_t len; + + if (!upb_decode_varint32(ptr, limit, &len) || + limit - *ptr < len) { + return false; + } + + *val = upb_stringview_make(*ptr, len); + *ptr += len; + return true; +} + +static void upb_set32(void *msg, size_t ofs, uint32_t val) { + memcpy((char*)msg + ofs, &val, sizeof(val)); +} + +bool upb_append_unknown(const char **ptr, const char *start, const char *limit, + char *msg) { + UPB_UNUSED(limit); + UPB_UNUSED(msg); + *ptr = limit; + return true; +} + +bool upb_decode_field(const char **ptr, const char *limit, char *msg, + const upb_msglayout_msginit_v1 *l, upb_env *env) { + uint32_t tag; + uint32_t wire_type; + uint32_t field_number; + const char *p = *ptr; + const char *field_start = p; + const upb_msglayout_fieldinit_v1 *f; + + if (!upb_decode_varint32(&p, limit, &tag)) { + upb_decode_seterr(env, "Error decoding tag.\n"); + return false; + } + + wire_type = tag & 0x7; + field_number = tag >> 3; + + if (field_number == 0) { + return false; + } + + f = upb_find_field(l, field_number); + + switch (wire_type) { + case UPB_WIRE_TYPE_VARINT: { + uint64_t val; + if (!upb_decode_varint(&p, limit, &val)) { + upb_decode_seterr(env, "Error decoding varint value.\n"); + return false; + } + + if (!f) { + return upb_append_unknown(ptr, field_start, p, msg); + } + + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + memcpy(msg + f->offset, &val, sizeof(val)); + break; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_ENUM: { + uint32_t val32 = val; + memcpy(msg + f->offset, &val32, sizeof(val32)); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT32: { + int32_t decoded = upb_zzdec_32(val); + memcpy(msg + f->offset, &decoded, sizeof(decoded)); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT64: { + int64_t decoded = upb_zzdec_64(val); + memcpy(msg + f->offset, &decoded, sizeof(decoded)); + break; + } + default: + return upb_append_unknown(ptr, field_start, p, msg); + } + + break; + } + case UPB_WIRE_TYPE_64BIT: { + uint64_t val; + if (!upb_decode_64bit(&p, limit, &val)) { + upb_decode_seterr(env, "Error decoding 64bit value.\n"); + return false; + } + + if (!f) { + return upb_append_unknown(ptr, field_start, p, msg); + } + + break; + } + case UPB_WIRE_TYPE_32BIT: { + uint32_t val; + if (!upb_decode_32bit(&p, limit, &val)) { + upb_decode_seterr(env, "Error decoding 32bit value.\n"); + return false; + } + + if (!f) { + return upb_append_unknown(ptr, field_start, p, msg); + } + + break; + } + case UPB_WIRE_TYPE_DELIMITED: { + upb_stringview val; + if (!upb_decode_string(&p, limit, &val)) { + upb_decode_seterr(env, "Error decoding delimited value.\n"); + return false; + } + + if (!f) { + return upb_append_unknown(ptr, field_start, p, msg); + } + + memcpy(msg + f->offset, &val, sizeof(val)); + break; + } + } + + if (f->oneof_index != UPB_NOT_IN_ONEOF) { + upb_set32(msg, l->oneofs[f->oneof_index].case_offset, f->number); + } + + *ptr = p; + return true; +} + +bool upb_decode(upb_stringview buf, void *msg_void, + const upb_msglayout_msginit_v1 *l, upb_env *env) { + char *msg = msg_void; + const char *ptr = buf.data; + const char *limit = ptr + buf.size; + + while (ptr < limit) { + if (!upb_decode_field(&ptr, limit, msg, l, env)) { + return false; + } + } + + return true; +} diff --git a/upb/decode.h b/upb/decode.h new file mode 100644 index 0000000..2a9e39e --- /dev/null +++ b/upb/decode.h @@ -0,0 +1,17 @@ +/* +** upb_decode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_DECODE_H_ +#define UPB_DECODE_H_ + +#include "upb/msg.h" + +UPB_BEGIN_EXTERN_C + +bool upb_decode(upb_stringview buf, void *msg, + const upb_msglayout_msginit_v1 *l, upb_env *env); + +UPB_END_EXTERN_C + +#endif /* UPB_DECODE_H_ */ diff --git a/upb/encode.c b/upb/encode.c new file mode 100644 index 0000000..30f2da7 --- /dev/null +++ b/upb/encode.c @@ -0,0 +1,512 @@ + +#include "upb/encode.h" +#include "upb/structs.int.h" + +#define UPB_PB_VARINT_MAX_LEN 10 + +static size_t upb_encode_varint(uint64_t val, char *buf) { + size_t i; + if (val == 0) { buf[0] = 0; return 1; } + i = 0; + while (val) { + uint8_t byte = val & 0x7fU; + val >>= 7; + if (val) byte |= 0x80U; + buf[i++] = byte; + } + return i; +} + +static size_t upb_varint_size(uint64_t val) { + char buf[UPB_PB_VARINT_MAX_LEN]; + return upb_encode_varint(val, buf); +} + +static uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); } +static uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } + +typedef enum { + UPB_WIRE_TYPE_VARINT = 0, + UPB_WIRE_TYPE_64BIT = 1, + UPB_WIRE_TYPE_DELIMITED = 2, + UPB_WIRE_TYPE_START_GROUP = 3, + UPB_WIRE_TYPE_END_GROUP = 4, + UPB_WIRE_TYPE_32BIT = 5 +} upb_wiretype_t; + +/* Index is descriptor type. */ +const uint8_t upb_native_wiretypes[] = { + UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ + UPB_WIRE_TYPE_64BIT, /* DOUBLE */ + UPB_WIRE_TYPE_32BIT, /* FLOAT */ + UPB_WIRE_TYPE_VARINT, /* INT64 */ + UPB_WIRE_TYPE_VARINT, /* UINT64 */ + UPB_WIRE_TYPE_VARINT, /* INT32 */ + UPB_WIRE_TYPE_64BIT, /* FIXED64 */ + UPB_WIRE_TYPE_32BIT, /* FIXED32 */ + UPB_WIRE_TYPE_VARINT, /* BOOL */ + UPB_WIRE_TYPE_DELIMITED, /* STRING */ + UPB_WIRE_TYPE_START_GROUP, /* GROUP */ + UPB_WIRE_TYPE_DELIMITED, /* MESSAGE */ + UPB_WIRE_TYPE_DELIMITED, /* BYTES */ + UPB_WIRE_TYPE_VARINT, /* UINT32 */ + UPB_WIRE_TYPE_VARINT, /* ENUM */ + UPB_WIRE_TYPE_32BIT, /* SFIXED32 */ + UPB_WIRE_TYPE_64BIT, /* SFIXED64 */ + UPB_WIRE_TYPE_VARINT, /* SINT32 */ + UPB_WIRE_TYPE_VARINT, /* SINT64 */ +}; + +/* The output buffer is divided into segments; a segment is a string of data + * that is "ready to go" -- it does not need any varint lengths inserted into + * the middle. The seams between segments are where varints will be inserted + * once they are known. + * + * We also use the concept of a "run", which is a range of encoded bytes that + * occur at a single submessage level. Every segment contains one or more runs. + * + * A segment can span messages. Consider: + * + * .--Submessage lengths---------. + * | | | + * | V V + * V | |--------------- | |----------------- + * Submessages: | |----------------------------------------------- + * Top-level msg: ------------------------------------------------------------ + * + * Segments: ----- ------------------- ----------------- + * Runs: *---- *--------------*--- *---------------- + * (* marks the start) + * + * Note that the top-level menssage is not in any segment because it does not + * have any length preceding it. + * + * A segment is only interrupted when another length needs to be inserted. So + * observe how the second segment spans both the inner submessage and part of + * the next enclosing message. */ + +typedef struct { + uint32_t msglen; /* The length to varint-encode before this segment. */ + uint32_t seglen; /* Length of the segment. */ +} upb_segment; + +typedef struct { + upb_env *env; + char *buf, *ptr, *limit; + + /* The beginning of the current run, or undefined if we are at the top + * level. */ + char *runbegin; + + /* The list of segments we are accumulating. */ + upb_segment *segbuf, *segptr, *seglimit; + + /* The stack of enclosing submessages. Each entry in the stack points to the + * segment where this submessage's length is being accumulated. */ + int *stack, *top, *stacklimit; +} upb_encstate; + +static upb_segment *upb_encode_top(upb_encstate *e) { + return &e->segbuf[*e->top]; +} + +static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) { + char *new_buf; + size_t needed = bytes + (e->ptr - e->buf); + size_t old_size = e->limit - e->buf; + + size_t new_size = old_size; + + while (new_size < needed) { + new_size *= 2; + } + + new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); + + if (new_buf == NULL) { + return false; + } + + e->ptr = new_buf + (e->ptr - e->buf); + e->runbegin = new_buf + (e->runbegin - e->buf); + e->limit = new_buf + new_size; + e->buf = new_buf; + return true; +} + +/* Call to ensure that at least "bytes" bytes are available for writing at + * e->ptr. Returns false if the bytes could not be allocated. */ +static bool upb_encode_reserve(upb_encstate *e, size_t bytes) { + if (UPB_LIKELY((size_t)(e->limit - e->ptr) >= bytes)) { + return true; + } + + return upb_encode_growbuffer(e, bytes); +} + +/* Call when "bytes" bytes have been writte at e->ptr. The caller *must* have + * previously called reserve() with at least this many bytes. */ +static void upb_encode_advance(upb_encstate *e, size_t bytes) { + UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes); + e->ptr += bytes; +} + +/* Writes the given bytes to the buffer, handling reserve/advance. */ +static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) { + if (!upb_encode_reserve(e, len)) { + return false; + } + + memcpy(e->ptr, data, len); + upb_encode_advance(e, len); + return true; +} + +/* Finish the current run by adding the run totals to the segment and message + * length. */ +static void upb_encode_accumulate(upb_encstate *e) { + size_t run_len; + UPB_ASSERT(e->ptr >= e->runbegin); + run_len = e->ptr - e->runbegin; + e->segptr->seglen += run_len; + upb_encode_top(e)->msglen += run_len; + e->runbegin = e->ptr; +} + +/* Call to indicate the start of delimited region for which the full length is + * not yet known. The length will be inserted at the current position once it + * is known (and subsequent data moved if necessary). */ +static bool upb_encode_startdelim(upb_encstate *e) { + if (e->top) { + /* We are already buffering, advance to the next segment and push it on the + * stack. */ + upb_encode_accumulate(e); + + if (++e->top == e->stacklimit) { + /* TODO(haberman): grow stack? */ + return false; + } + + if (++e->segptr == e->seglimit) { + /* Grow segment buffer. */ + size_t old_size = + (e->seglimit - e->segbuf) * sizeof(upb_segment); + size_t new_size = old_size * 2; + upb_segment *new_buf = + upb_env_realloc(e->env, e->segbuf, old_size, new_size); + + if (new_buf == NULL) { + return false; + } + + e->segptr = new_buf + (e->segptr - e->segbuf); + e->seglimit = new_buf + (new_size / sizeof(upb_segment)); + e->segbuf = new_buf; + } + } else { + /* We were previously at the top level, start buffering. */ + e->segptr = e->segbuf; + e->top = e->stack; + e->runbegin = e->ptr; + } + + *e->top = e->segptr - e->segbuf; + e->segptr->seglen = 0; + e->segptr->msglen = 0; + + return true; +} + +/* Call to indicate the end of a delimited region. We now know the length of + * the delimited region. If we are not nested inside any other delimited + * regions, we can now emit all of the buffered data we accumulated. */ +static bool upb_encode_enddelim(upb_encstate *e) { + size_t msglen; + upb_encode_accumulate(e); + msglen = upb_encode_top(e)->msglen; + + if (e->top == e->stack) { + /* All lengths are now available, emit all buffered data. */ + char buf[UPB_PB_VARINT_MAX_LEN]; + upb_segment *s; + const char *ptr = e->buf; + for (s = e->segbuf; s <= e->segptr; s++) { + size_t lenbytes = upb_encode_varint(s->msglen, buf); + //putbuf(e, buf, lenbytes); + //putbuf(e, ptr, s->seglen); + ptr += s->seglen; + } + + e->ptr = e->buf; + e->top = NULL; + } else { + /* Need to keep buffering; propagate length info into enclosing + * submessages. */ + --e->top; + upb_encode_top(e)->msglen += msglen + upb_varint_size(msglen); + } + + return true; +} + +/* encoding of wire types *****************************************************/ + +static bool upb_put_fixed64(upb_encstate *e, uint64_t val) { + /* TODO(haberman): byte-swap for big endian. */ + return upb_put_bytes(e, &val, sizeof(uint64_t)); +} + +static bool upb_put_fixed32(upb_encstate *e, uint32_t val) { + /* TODO(haberman): byte-swap for big endian. */ + return upb_put_bytes(e, &val, sizeof(uint32_t)); +} + +static bool upb_put_varint(upb_encstate *e, uint64_t val) { + if (!upb_encode_reserve(e, UPB_PB_VARINT_MAX_LEN)) { + return false; + } + + upb_encode_advance(e, upb_encode_varint(val, e->ptr)); + return true; +} + +static bool upb_put_double(upb_encstate *e, double d) { + uint64_t u64; + UPB_ASSERT(sizeof(double) == sizeof(uint64_t)); + memcpy(&u64, &d, sizeof(uint64_t)); + return upb_put_fixed64(e, u64); +} + +static bool upb_put_float(upb_encstate *e, float d) { + uint32_t u32; + UPB_ASSERT(sizeof(float) == sizeof(uint32_t)); + memcpy(&u32, &d, sizeof(uint32_t)); + return upb_put_fixed32(e, u32); +} + +static uint32_t upb_readcase(const char *msg, const upb_msglayout_msginit_v1 *m, + int oneof_index) { + uint32_t ret; + memcpy(&ret, msg + m->oneofs[oneof_index].case_offset, sizeof(ret)); + return ret; +} + +static bool upb_readhasbit(const char *msg, + const upb_msglayout_fieldinit_v1 *f) { + UPB_ASSERT(f->hasbit != UPB_NO_HASBIT); + return msg[f->hasbit / 8] & (1 << (f->hasbit % 8)); +} + +static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) { + return upb_put_varint(e, (field_number << 3) | wire_type); +} + +static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr, + size_t size) { + size_t bytes = arr->len * size; + return upb_put_varint(e, bytes) && upb_put_bytes(e, arr->data, bytes); +} + +bool upb_encode_message(upb_encstate *e, const char *msg, + const upb_msglayout_msginit_v1 *m); + +static bool upb_encode_array(upb_encstate *e, const char *field_mem, + const upb_msglayout_msginit_v1 *m, + const upb_msglayout_fieldinit_v1 *f) { + const upb_array *arr = *(const upb_array**)field_mem; + + if (arr->len == 0) { + return true; + } + + /* We encode all primitive arrays as packed, regardless of what was specified + * in the .proto file. Could special case 1-sized arrays. */ + if (!upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)) { + return false; + } + +#define VARINT_CASE(ctype, encode) { \ + uint64_t *data = arr->data; \ + uint64_t *limit = data + arr->len; \ + if (!upb_encode_startdelim(e)) { \ + return false; \ + } \ + for (; data < limit; data++) { \ + if (!upb_put_varint(e, encode)) { \ + return false; \ + } \ + } \ + return upb_encode_enddelim(e); \ +} + + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + return upb_put_fixedarray(e, arr, sizeof(double)); + case UPB_DESCRIPTOR_TYPE_FLOAT: + return upb_put_fixedarray(e, arr, sizeof(float)); + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + return upb_put_fixedarray(e, arr, sizeof(uint64_t)); + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + return upb_put_fixedarray(e, arr, sizeof(uint32_t)); + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + VARINT_CASE(uint64_t, *data); + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + VARINT_CASE(uint32_t, *data); + case UPB_DESCRIPTOR_TYPE_BOOL: + VARINT_CASE(bool, *data); + case UPB_DESCRIPTOR_TYPE_SINT32: + VARINT_CASE(int32_t, upb_zzenc_32(*data)); + case UPB_DESCRIPTOR_TYPE_SINT64: + VARINT_CASE(int64_t, upb_zzenc_64(*data)); + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + upb_stringview *data = arr->data; + upb_stringview *limit = data + arr->len; + goto put_string_data; /* Skip first tag, we already put it. */ + for (; data < limit; data++) { + if (!upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)) { + return false; + } +put_string_data: + if (!upb_put_varint(e, data->size) || + !upb_put_bytes(e, data->data, data->size)) { + return false; + } + } + } + case UPB_DESCRIPTOR_TYPE_GROUP: + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + void **data = arr->data; + void **limit = data + arr->len; + const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; + goto put_submsg_data; /* Skip first tag, we already put it. */ + for (; data < limit; data++) { + if (!upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)) { + return false; + } +put_submsg_data: + if (!upb_encode_startdelim(e) || + !upb_encode_message(e, *data, subm) || + !upb_encode_enddelim(e)) { + return false; + } + } + } + } + UPB_UNREACHABLE(); +#undef VARINT_CASE +} + +static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, + const upb_msglayout_msginit_v1 *m, + const upb_msglayout_fieldinit_v1 *f, + bool is_proto3) { +#define CASE(ctype, type, wire_type, encodeval) { \ + ctype val = *(ctype*)field_mem; \ + if (is_proto3 && val == 0) { \ + return true; \ + } \ + return upb_put_tag(e, f->number, wire_type) && \ + upb_put_ ## type(e, encodeval); \ +} + + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + CASE(double, double, UPB_WIRE_TYPE_64BIT, val) + case UPB_DESCRIPTOR_TYPE_FLOAT: + CASE(float, float, UPB_WIRE_TYPE_32BIT, val) + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val) + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val) + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val) + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val) + case UPB_DESCRIPTOR_TYPE_BOOL: + CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val) + case UPB_DESCRIPTOR_TYPE_SINT32: + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzenc_32(val)) + case UPB_DESCRIPTOR_TYPE_SINT64: + CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzenc_64(val)) + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + upb_stringview view = *(upb_stringview*)field_mem; + if (is_proto3 && view.size == 0) { + return true; + } + return upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED) && + upb_put_varint(e, view.size) && + upb_put_bytes(e, view.data, view.size); + } + case UPB_DESCRIPTOR_TYPE_GROUP: + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + void *submsg = *(void**)field_mem; + if (is_proto3 && submsg == NULL) { + return true; + } + return upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED) && + upb_encode_startdelim(e) && + upb_encode_message(e, submsg, m->submsgs[f->submsg_index]) && + upb_encode_enddelim(e); + } + } +#undef CASE + UPB_UNREACHABLE(); +} + +bool upb_encode_hasscalarfield(const char *msg, + const upb_msglayout_msginit_v1 *m, + const upb_msglayout_fieldinit_v1 *f) { + if (f->oneof_index != UPB_NOT_IN_ONEOF) { + return upb_readcase(msg, m, f->oneof_index) == f->number; + } else if (m->is_proto2) { + return upb_readhasbit(msg, f); + } else { + /* For proto3, we'll test for the field being empty later. */ + return true; + } +} + +bool upb_encode_message(upb_encstate* e, const char *msg, + const upb_msglayout_msginit_v1 *m) { + int i; + for (i = 0; i < m->field_count; i++) { + const upb_msglayout_fieldinit_v1 *f = &m->fields[i]; + + if (f->label == UPB_LABEL_REPEATED) { + if (!upb_encode_array(e, msg, m, f)) { + return NULL; + } + } else { + if (upb_encode_hasscalarfield(msg, m, f) && + !upb_encode_scalarfield(e, msg + f->offset, m, f, !m->is_proto2)) { + return NULL; + } + } + } + + return true; +} + +char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *m, + upb_env *env, size_t *size) { + upb_encstate e; + + if (!upb_encode_message(&e, msg, m)) { + return false; + } + + *size = e.ptr - e.buf; + return e.buf; +} diff --git a/upb/encode.h b/upb/encode.h new file mode 100644 index 0000000..83908d4 --- /dev/null +++ b/upb/encode.h @@ -0,0 +1,17 @@ +/* +** upb_encode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_ENCODE_H_ +#define UPB_ENCODE_H_ + +#include "upb/msg.h" + +UPB_BEGIN_EXTERN_C + +char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *l, + upb_env *env, size_t *size); + +UPB_END_EXTERN_C + +#endif /* UPB_ENCODE_H_ */ diff --git a/upb/msg.c b/upb/msg.c index ef39dc0..9d29a39 100644 --- a/upb/msg.c +++ b/upb/msg.c @@ -1,5 +1,6 @@ #include "upb/msg.h" +#include "upb/structs.int.h" static bool is_power_of_two(size_t val) { return (val & (val - 1)) == 0; @@ -791,15 +792,6 @@ void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val, /** upb_array *****************************************************************/ -struct upb_array { - upb_fieldtype_t type; - uint8_t element_size; - void *data; /* Each element is element_size. */ - size_t len; /* Measured in elements. */ - size_t size; /* Measured in elements. */ - upb_alloc *alloc; -}; - #define DEREF_ARR(arr, i, type) ((type*)arr->data)[i] size_t upb_array_sizeof(upb_fieldtype_t type) { diff --git a/upb/msg.h b/upb/msg.h index ee1e2fb..8024828 100644 --- a/upb/msg.h +++ b/upb/msg.h @@ -386,6 +386,7 @@ bool upb_msg_getscalarhandlerdata(const upb_handlers *h, /** Interfaces for generated code *********************************************/ #define UPB_NOT_IN_ONEOF UINT16_MAX +#define UPB_NO_HASBIT UINT16_MAX typedef struct { uint32_t number; diff --git a/upb/structs.int.h b/upb/structs.int.h new file mode 100644 index 0000000..242155b --- /dev/null +++ b/upb/structs.int.h @@ -0,0 +1,18 @@ +/* +** structs.int.h: structures definitions that are internal to upb. +*/ + +#ifndef UPB_STRUCTS_H_ +#define UPB_STRUCTS_H_ + +struct upb_array { + upb_fieldtype_t type; + uint8_t element_size; + void *data; /* Each element is element_size. */ + size_t len; /* Measured in elements. */ + size_t size; /* Measured in elements. */ + upb_alloc *alloc; +}; + +#endif /* UPB_STRUCTS_H_ */ + diff --git a/upb/upb.h b/upb/upb.h index a2b79ca..19cd02c 100644 --- a/upb/upb.h +++ b/upb/upb.h @@ -34,6 +34,9 @@ template class InlinedEnvironment; #define UPB_INLINE static #endif +/* Hints to the compiler about likely/unlikely branches. */ +#define UPB_LIKELY(x) __builtin_expect((x),1) + /* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler * doesn't provide these preprocessor symbols. */ #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -- cgit v1.2.3 From 699b51b441c6f963ca95e9a7c40c2cb14adde014 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 10 Jul 2017 16:25:50 -0500 Subject: Lots of encoder/decoder work (backwards encoder). --- upb/decode.c | 226 ++++++++++++++++++++++++++------- upb/encode.c | 401 ++++++++++++++++++++--------------------------------------- 2 files changed, 317 insertions(+), 310 deletions(-) diff --git a/upb/decode.c b/upb/decode.c index 3b2ea54..f28642b 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -10,6 +10,15 @@ typedef enum { UPB_WIRE_TYPE_32BIT = 5 } upb_wiretype_t; +typedef struct { + upb_env *env; + /* Current decoding pointer. Points to the beginning of a field until we + * have finished decoding the whole field. */ + const char *ptr; +} upb_decstate; + +#define CHK(x) if (!(x)) { return false; } + static void upb_decode_seterr(upb_env *env, const char *msg) { upb_status status = UPB_STATUS_INIT; upb_status_seterrmsg(&status, msg); @@ -110,24 +119,56 @@ static void upb_set32(void *msg, size_t ofs, uint32_t val) { memcpy((char*)msg + ofs, &val, sizeof(val)); } -bool upb_append_unknown(const char **ptr, const char *start, const char *limit, - char *msg) { +static bool upb_append_unknownfield(const char **ptr, const char *start, + const char *limit, char *msg) { UPB_UNUSED(limit); UPB_UNUSED(msg); *ptr = limit; return true; } -bool upb_decode_field(const char **ptr, const char *limit, char *msg, - const upb_msglayout_msginit_v1 *l, upb_env *env) { +static bool upb_decode_unknownfielddata(upb_decstate *d, const char *ptr, + const char *limit, char *msg, + const upb_msglayout_msginit_v1 *l) { + do { + switch (wire_type) { + case UPB_WIRE_TYPE_VARINT: + CHK(upb_decode_varint(&ptr, limit, &val)); + break; + case UPB_WIRE_TYPE_32BIT: + CHK(upb_decode_32bit(&ptr, limit, &val)); + break; + case UPB_WIRE_TYPE_64BIT: + CHK(upb_decode_64bit(&ptr, limit, &val)); + break; + case UPB_WIRE_TYPE_DELIMITED: { + upb_stringview val; + CHK(upb_decode_string(&ptr, limit, &val)); + } + case UPB_WIRE_TYPE_START_GROUP: + depth++; + continue; + case UPB_WIRE_TYPE_END_GROUP: + depth--; + continue; + } + + UPB_ASSERT(depth == 0); + upb_append_unknown(msg, l, d->ptr, ptr); + d->ptr = ptr; + return true; + } while (true); +} + +static bool upb_decode_field(upb_decstate *d, const char *limit, char *msg, + const upb_msglayout_msginit_v1 *l) { uint32_t tag; uint32_t wire_type; uint32_t field_number; - const char *p = *ptr; - const char *field_start = p; + const char *ptr = d->ptr; const upb_msglayout_fieldinit_v1 *f; - if (!upb_decode_varint32(&p, limit, &tag)) { + if (!upb_decode_varint32(&ptr, limit, &tag)) { upb_decode_seterr(env, "Error decoding tag.\n"); return false; } @@ -141,84 +182,178 @@ bool upb_decode_field(const char **ptr, const char *limit, char *msg, f = upb_find_field(l, field_number); + if (f) { + return upb_decode_knownfield(d, ptr, limit, msg, l, f); + } else { + return upb_decode_unknownfield(d, ptr, limit, msg, l); + } + + if (f->label == UPB_LABEL_REPEATED) { + arr = upb_getarray(msg, f, env); + } + switch (wire_type) { case UPB_WIRE_TYPE_VARINT: { uint64_t val; - if (!upb_decode_varint(&p, limit, &val)) { + if (!upb_decode_varint(&ptr, limit, &val)) { upb_decode_seterr(env, "Error decoding varint value.\n"); return false; } if (!f) { - return upb_append_unknown(ptr, field_start, p, msg); + return upb_append_unknown(ptr, field_start, ptr, msg); } - switch (f->type) { - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_UINT64: - memcpy(msg + f->offset, &val, sizeof(val)); - break; - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_ENUM: { - uint32_t val32 = val; - memcpy(msg + f->offset, &val32, sizeof(val32)); - break; + if (f->label == UPB_LABEL_REPEATED) { + upb_array *arr = upb_getarray(msg, f, env); + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + memcpy(arr->data, &val, sizeof(val)); + arr->len++; + break; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_ENUM: { + uint32_t val32 = val; + memcpy(arr->data, &val32, sizeof(val32)); + arr->len++; + break; + } + case UPB_DESCRIPTOR_TYPE_SINT32: { + int32_t decoded = upb_zzdec_32(val); + memcpy(arr->data, &decoded, sizeof(decoded)); + arr->len++; + break; + } + case UPB_DESCRIPTOR_TYPE_SINT64: { + int64_t decoded = upb_zzdec_64(val); + memcpy(arr->data, &decoded, sizeof(decoded)); + arr->len++; + break; + } + default: + return upb_append_unknown(ptr, field_start, ptr, msg); } - case UPB_DESCRIPTOR_TYPE_SINT32: { - int32_t decoded = upb_zzdec_32(val); - memcpy(msg + f->offset, &decoded, sizeof(decoded)); - break; - } - case UPB_DESCRIPTOR_TYPE_SINT64: { - int64_t decoded = upb_zzdec_64(val); - memcpy(msg + f->offset, &decoded, sizeof(decoded)); - break; + } else { + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + memcpy(msg + f->offset, &val, sizeof(val)); + break; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_ENUM: { + uint32_t val32 = val; + memcpy(msg + f->offset, &val32, sizeof(val32)); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT32: { + int32_t decoded = upb_zzdec_32(val); + memcpy(msg + f->offset, &decoded, sizeof(decoded)); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT64: { + int64_t decoded = upb_zzdec_64(val); + memcpy(msg + f->offset, &decoded, sizeof(decoded)); + break; + } + default: + return upb_append_unknown(ptr, field_start, ptr, msg); } - default: - return upb_append_unknown(ptr, field_start, p, msg); } break; } case UPB_WIRE_TYPE_64BIT: { uint64_t val; - if (!upb_decode_64bit(&p, limit, &val)) { + if (!upb_decode_64bit(&ptr, limit, &val)) { upb_decode_seterr(env, "Error decoding 64bit value.\n"); return false; } if (!f) { - return upb_append_unknown(ptr, field_start, p, msg); + return upb_append_unknown(ptr, field_start, ptr, msg); + } + + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + case UPB_DESCRIPTOR_TYPE_FIXED64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + memcpy(msg + f->offset, &val, sizeof(val)); + default: + return upb_append_unknown(ptr, field_start, ptr, msg); } break; } case UPB_WIRE_TYPE_32BIT: { uint32_t val; - if (!upb_decode_32bit(&p, limit, &val)) { + if (!upb_decode_32bit(&ptr, limit, &val)) { upb_decode_seterr(env, "Error decoding 32bit value.\n"); return false; } if (!f) { - return upb_append_unknown(ptr, field_start, p, msg); + return upb_append_unknown(ptr, field_start, ptr, msg); + } + + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_FLOAT: + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + memcpy(msg + f->offset, &val, sizeof(val)); + default: + return upb_append_unknown(ptr, field_start, ptr, msg); } break; } case UPB_WIRE_TYPE_DELIMITED: { upb_stringview val; - if (!upb_decode_string(&p, limit, &val)) { + if (!upb_decode_string(&ptr, limit, &val)) { upb_decode_seterr(env, "Error decoding delimited value.\n"); return false; } if (!f) { - return upb_append_unknown(ptr, field_start, p, msg); + return upb_append_unknown(ptr, field_start, ptr, msg); + } + + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: + memcpy(msg + f->offset, &val, sizeof(val)); + break; + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: { + memcpy(msg + f->offset, &val, sizeof(val)); + break; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_ENUM: { + uint32_t val32 = val; + memcpy(msg + f->offset, &val32, sizeof(val32)); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT32: { + int32_t decoded = upb_zzdec_32(val); + memcpy(msg + f->offset, &decoded, sizeof(decoded)); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT64: + case UPB_DESCRIPTOR_TYPE_FLOAT: + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + /* + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + upb_decode_message(val, + } + */ + default: + return upb_append_unknown(ptr, field_start, ptr, msg); } - memcpy(msg + f->offset, &val, sizeof(val)); break; } } @@ -227,17 +362,15 @@ bool upb_decode_field(const char **ptr, const char *limit, char *msg, upb_set32(msg, l->oneofs[f->oneof_index].case_offset, f->number); } - *ptr = p; + d->ptr = ptr; return true; } -bool upb_decode(upb_stringview buf, void *msg_void, - const upb_msglayout_msginit_v1 *l, upb_env *env) { - char *msg = msg_void; - const char *ptr = buf.data; +static bool upb_decode_message(upb_decstate *d, upb_stringview buf, + char *msg, const upb_msglayout_msginit_v1 *l) { const char *limit = ptr + buf.size; - while (ptr < limit) { + while (d->ptr < limit) { if (!upb_decode_field(&ptr, limit, msg, l, env)) { return false; } @@ -245,3 +378,8 @@ bool upb_decode(upb_stringview buf, void *msg_void, return true; } + +bool upb_decode(upb_stringview buf, void *msg, + const upb_msglayout_msginit_v1 *l, upb_env *env) { + return upb_decode_message(buf, msg, l, env); +} diff --git a/upb/encode.c b/upb/encode.c index 30f2da7..2fe1cc3 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -3,6 +3,7 @@ #include "upb/structs.int.h" #define UPB_PB_VARINT_MAX_LEN 10 +#define CHK(x) do { if (!(x)) { return false; } } while(0) static size_t upb_encode_varint(uint64_t val, char *buf) { size_t i; @@ -17,11 +18,6 @@ static size_t upb_encode_varint(uint64_t val, char *buf) { return i; } -static size_t upb_varint_size(uint64_t val) { - char buf[UPB_PB_VARINT_MAX_LEN]; - return upb_encode_varint(val, buf); -} - static uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); } static uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } @@ -57,78 +53,29 @@ const uint8_t upb_native_wiretypes[] = { UPB_WIRE_TYPE_VARINT, /* SINT64 */ }; -/* The output buffer is divided into segments; a segment is a string of data - * that is "ready to go" -- it does not need any varint lengths inserted into - * the middle. The seams between segments are where varints will be inserted - * once they are known. - * - * We also use the concept of a "run", which is a range of encoded bytes that - * occur at a single submessage level. Every segment contains one or more runs. - * - * A segment can span messages. Consider: - * - * .--Submessage lengths---------. - * | | | - * | V V - * V | |--------------- | |----------------- - * Submessages: | |----------------------------------------------- - * Top-level msg: ------------------------------------------------------------ - * - * Segments: ----- ------------------- ----------------- - * Runs: *---- *--------------*--- *---------------- - * (* marks the start) - * - * Note that the top-level menssage is not in any segment because it does not - * have any length preceding it. - * - * A segment is only interrupted when another length needs to be inserted. So - * observe how the second segment spans both the inner submessage and part of - * the next enclosing message. */ - -typedef struct { - uint32_t msglen; /* The length to varint-encode before this segment. */ - uint32_t seglen; /* Length of the segment. */ -} upb_segment; - typedef struct { upb_env *env; char *buf, *ptr, *limit; - - /* The beginning of the current run, or undefined if we are at the top - * level. */ - char *runbegin; - - /* The list of segments we are accumulating. */ - upb_segment *segbuf, *segptr, *seglimit; - - /* The stack of enclosing submessages. Each entry in the stack points to the - * segment where this submessage's length is being accumulated. */ - int *stack, *top, *stacklimit; } upb_encstate; -static upb_segment *upb_encode_top(upb_encstate *e) { - return &e->segbuf[*e->top]; +static size_t upb_roundup_pow2(size_t bytes) { + size_t ret = 128; + while (ret < bytes) { + ret *= 2; + } + return ret; } static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) { - char *new_buf; - size_t needed = bytes + (e->ptr - e->buf); size_t old_size = e->limit - e->buf; + size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr)); + char *new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); + CHK(new_buf); - size_t new_size = old_size; + /* We want previous data at the end, realloc() put it at the beginning. */ + memmove(e->limit - old_size, e->buf, old_size); - while (new_size < needed) { - new_size *= 2; - } - - new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); - - if (new_buf == NULL) { - return false; - } - - e->ptr = new_buf + (e->ptr - e->buf); - e->runbegin = new_buf + (e->runbegin - e->buf); + e->ptr = new_buf + new_size - (e->limit - e->ptr); e->limit = new_buf + new_size; e->buf = new_buf; return true; @@ -137,120 +84,20 @@ static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) { /* Call to ensure that at least "bytes" bytes are available for writing at * e->ptr. Returns false if the bytes could not be allocated. */ static bool upb_encode_reserve(upb_encstate *e, size_t bytes) { - if (UPB_LIKELY((size_t)(e->limit - e->ptr) >= bytes)) { - return true; - } - - return upb_encode_growbuffer(e, bytes); -} + CHK(UPB_LIKELY((size_t)(e->ptr - e->buf) >= bytes) || + upb_encode_growbuffer(e, bytes)); -/* Call when "bytes" bytes have been writte at e->ptr. The caller *must* have - * previously called reserve() with at least this many bytes. */ -static void upb_encode_advance(upb_encstate *e, size_t bytes) { - UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes); - e->ptr += bytes; + e->ptr -= bytes; + return true; } /* Writes the given bytes to the buffer, handling reserve/advance. */ static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) { - if (!upb_encode_reserve(e, len)) { - return false; - } - + CHK(upb_encode_reserve(e, len)); memcpy(e->ptr, data, len); - upb_encode_advance(e, len); - return true; -} - -/* Finish the current run by adding the run totals to the segment and message - * length. */ -static void upb_encode_accumulate(upb_encstate *e) { - size_t run_len; - UPB_ASSERT(e->ptr >= e->runbegin); - run_len = e->ptr - e->runbegin; - e->segptr->seglen += run_len; - upb_encode_top(e)->msglen += run_len; - e->runbegin = e->ptr; -} - -/* Call to indicate the start of delimited region for which the full length is - * not yet known. The length will be inserted at the current position once it - * is known (and subsequent data moved if necessary). */ -static bool upb_encode_startdelim(upb_encstate *e) { - if (e->top) { - /* We are already buffering, advance to the next segment and push it on the - * stack. */ - upb_encode_accumulate(e); - - if (++e->top == e->stacklimit) { - /* TODO(haberman): grow stack? */ - return false; - } - - if (++e->segptr == e->seglimit) { - /* Grow segment buffer. */ - size_t old_size = - (e->seglimit - e->segbuf) * sizeof(upb_segment); - size_t new_size = old_size * 2; - upb_segment *new_buf = - upb_env_realloc(e->env, e->segbuf, old_size, new_size); - - if (new_buf == NULL) { - return false; - } - - e->segptr = new_buf + (e->segptr - e->segbuf); - e->seglimit = new_buf + (new_size / sizeof(upb_segment)); - e->segbuf = new_buf; - } - } else { - /* We were previously at the top level, start buffering. */ - e->segptr = e->segbuf; - e->top = e->stack; - e->runbegin = e->ptr; - } - - *e->top = e->segptr - e->segbuf; - e->segptr->seglen = 0; - e->segptr->msglen = 0; - return true; } -/* Call to indicate the end of a delimited region. We now know the length of - * the delimited region. If we are not nested inside any other delimited - * regions, we can now emit all of the buffered data we accumulated. */ -static bool upb_encode_enddelim(upb_encstate *e) { - size_t msglen; - upb_encode_accumulate(e); - msglen = upb_encode_top(e)->msglen; - - if (e->top == e->stack) { - /* All lengths are now available, emit all buffered data. */ - char buf[UPB_PB_VARINT_MAX_LEN]; - upb_segment *s; - const char *ptr = e->buf; - for (s = e->segbuf; s <= e->segptr; s++) { - size_t lenbytes = upb_encode_varint(s->msglen, buf); - //putbuf(e, buf, lenbytes); - //putbuf(e, ptr, s->seglen); - ptr += s->seglen; - } - - e->ptr = e->buf; - e->top = NULL; - } else { - /* Need to keep buffering; propagate length info into enclosing - * submessages. */ - --e->top; - upb_encode_top(e)->msglen += msglen + upb_varint_size(msglen); - } - - return true; -} - -/* encoding of wire types *****************************************************/ - static bool upb_put_fixed64(upb_encstate *e, uint64_t val) { /* TODO(haberman): byte-swap for big endian. */ return upb_put_bytes(e, &val, sizeof(uint64_t)); @@ -262,11 +109,13 @@ static bool upb_put_fixed32(upb_encstate *e, uint32_t val) { } static bool upb_put_varint(upb_encstate *e, uint64_t val) { - if (!upb_encode_reserve(e, UPB_PB_VARINT_MAX_LEN)) { - return false; - } - - upb_encode_advance(e, upb_encode_varint(val, e->ptr)); + size_t len; + char *start; + CHK(upb_encode_reserve(e, UPB_PB_VARINT_MAX_LEN)); + len = upb_encode_varint(val, e->ptr); + start = e->ptr + UPB_PB_VARINT_MAX_LEN - len; + memmove(start, e->ptr, len); + e->ptr = start; return true; } @@ -304,11 +153,12 @@ static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) { static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr, size_t size) { size_t bytes = arr->len * size; - return upb_put_varint(e, bytes) && upb_put_bytes(e, arr->data, bytes); + return upb_put_bytes(e, arr->data, bytes) && upb_put_varint(e, bytes); } bool upb_encode_message(upb_encstate *e, const char *msg, - const upb_msglayout_msginit_v1 *m); + const upb_msglayout_msginit_v1 *m, + size_t *size); static bool upb_encode_array(upb_encstate *e, const char *field_mem, const upb_msglayout_msginit_v1 *m, @@ -319,146 +169,161 @@ static bool upb_encode_array(upb_encstate *e, const char *field_mem, return true; } - /* We encode all primitive arrays as packed, regardless of what was specified - * in the .proto file. Could special case 1-sized arrays. */ - if (!upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)) { - return false; - } - -#define VARINT_CASE(ctype, encode) { \ - uint64_t *data = arr->data; \ - uint64_t *limit = data + arr->len; \ - if (!upb_encode_startdelim(e)) { \ - return false; \ - } \ - for (; data < limit; data++) { \ - if (!upb_put_varint(e, encode)) { \ - return false; \ - } \ - } \ - return upb_encode_enddelim(e); \ -} +#define VARINT_CASE(ctype, encode) do { \ + uint64_t *start = arr->data; \ + uint64_t *ptr = start + arr->len; \ + char *buf_ptr = e->ptr; \ + do { \ + ptr--; \ + CHK(upb_put_varint(e, encode)); \ + } while (ptr != start); \ + CHK(upb_put_varint(e, buf_ptr - e->ptr)); \ + break; \ +} while(0) switch (f->type) { case UPB_DESCRIPTOR_TYPE_DOUBLE: - return upb_put_fixedarray(e, arr, sizeof(double)); + CHK(upb_put_fixedarray(e, arr, sizeof(double))); + break; case UPB_DESCRIPTOR_TYPE_FLOAT: - return upb_put_fixedarray(e, arr, sizeof(float)); + CHK(upb_put_fixedarray(e, arr, sizeof(float))); + break; case UPB_DESCRIPTOR_TYPE_SFIXED64: case UPB_DESCRIPTOR_TYPE_FIXED64: - return upb_put_fixedarray(e, arr, sizeof(uint64_t)); + CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t))); + break; case UPB_DESCRIPTOR_TYPE_FIXED32: case UPB_DESCRIPTOR_TYPE_SFIXED32: - return upb_put_fixedarray(e, arr, sizeof(uint32_t)); + CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t))); + break; case UPB_DESCRIPTOR_TYPE_INT64: case UPB_DESCRIPTOR_TYPE_UINT64: - VARINT_CASE(uint64_t, *data); + VARINT_CASE(uint64_t, *ptr); case UPB_DESCRIPTOR_TYPE_UINT32: case UPB_DESCRIPTOR_TYPE_INT32: case UPB_DESCRIPTOR_TYPE_ENUM: - VARINT_CASE(uint32_t, *data); + VARINT_CASE(uint32_t, *ptr); case UPB_DESCRIPTOR_TYPE_BOOL: - VARINT_CASE(bool, *data); + VARINT_CASE(bool, *ptr); case UPB_DESCRIPTOR_TYPE_SINT32: - VARINT_CASE(int32_t, upb_zzenc_32(*data)); + VARINT_CASE(int32_t, upb_zzenc_32(*ptr)); case UPB_DESCRIPTOR_TYPE_SINT64: - VARINT_CASE(int64_t, upb_zzenc_64(*data)); + VARINT_CASE(int64_t, upb_zzenc_64(*ptr)); case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { - upb_stringview *data = arr->data; - upb_stringview *limit = data + arr->len; - goto put_string_data; /* Skip first tag, we already put it. */ - for (; data < limit; data++) { - if (!upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)) { - return false; - } -put_string_data: - if (!upb_put_varint(e, data->size) || - !upb_put_bytes(e, data->data, data->size)) { - return false; - } - } + upb_stringview *start = arr->data; + upb_stringview *ptr = start + arr->len; + do { + ptr--; + CHK(upb_put_bytes(e, ptr->data, ptr->size) && + upb_put_varint(e, ptr->size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); + } while (ptr != start); + return true; + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + void **start = arr->data; + void **ptr = start + arr->len; + const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; + do { + size_t size; + ptr--; + CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) && + upb_encode_message(e, *ptr, subm, &size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP)); + } while (ptr != start); + return true; } - case UPB_DESCRIPTOR_TYPE_GROUP: case UPB_DESCRIPTOR_TYPE_MESSAGE: { - void **data = arr->data; - void **limit = data + arr->len; + void **start = arr->data; + void **ptr = start + arr->len; const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; - goto put_submsg_data; /* Skip first tag, we already put it. */ - for (; data < limit; data++) { - if (!upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)) { - return false; - } -put_submsg_data: - if (!upb_encode_startdelim(e) || - !upb_encode_message(e, *data, subm) || - !upb_encode_enddelim(e)) { - return false; - } - } + do { + size_t size; + ptr--; + CHK(upb_encode_message(e, *ptr, subm, &size) && + upb_put_varint(e, size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); + } while (ptr != start); + return true; } } - UPB_UNREACHABLE(); #undef VARINT_CASE + + /* We encode all primitive arrays as packed, regardless of what was specified + * in the .proto file. Could special case 1-sized arrays. */ + CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); + return true; } static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, const upb_msglayout_msginit_v1 *m, const upb_msglayout_fieldinit_v1 *f, bool is_proto3) { -#define CASE(ctype, type, wire_type, encodeval) { \ +#define CASE(ctype, type, wire_type, encodeval) do { \ ctype val = *(ctype*)field_mem; \ if (is_proto3 && val == 0) { \ return true; \ } \ - return upb_put_tag(e, f->number, wire_type) && \ - upb_put_ ## type(e, encodeval); \ -} + return upb_put_ ## type(e, encodeval) && \ + upb_put_tag(e, f->number, wire_type); \ +} while(0) switch (f->type) { case UPB_DESCRIPTOR_TYPE_DOUBLE: - CASE(double, double, UPB_WIRE_TYPE_64BIT, val) + CASE(double, double, UPB_WIRE_TYPE_64BIT, val); case UPB_DESCRIPTOR_TYPE_FLOAT: - CASE(float, float, UPB_WIRE_TYPE_32BIT, val) + CASE(float, float, UPB_WIRE_TYPE_32BIT, val); case UPB_DESCRIPTOR_TYPE_INT64: case UPB_DESCRIPTOR_TYPE_UINT64: - CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val) + CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val); case UPB_DESCRIPTOR_TYPE_UINT32: case UPB_DESCRIPTOR_TYPE_INT32: case UPB_DESCRIPTOR_TYPE_ENUM: - CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val) + CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val); case UPB_DESCRIPTOR_TYPE_SFIXED64: case UPB_DESCRIPTOR_TYPE_FIXED64: - CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val) + CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val); case UPB_DESCRIPTOR_TYPE_FIXED32: case UPB_DESCRIPTOR_TYPE_SFIXED32: - CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val) + CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val); case UPB_DESCRIPTOR_TYPE_BOOL: - CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val) + CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val); case UPB_DESCRIPTOR_TYPE_SINT32: - CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzenc_32(val)) + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzenc_32(val)); case UPB_DESCRIPTOR_TYPE_SINT64: - CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzenc_64(val)) + CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzenc_64(val)); case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { upb_stringview view = *(upb_stringview*)field_mem; if (is_proto3 && view.size == 0) { return true; } - return upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED) && + return upb_put_bytes(e, view.data, view.size) && upb_put_varint(e, view.size) && - upb_put_bytes(e, view.data, view.size); + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + size_t size; + void *submsg = *(void**)field_mem; + const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; + if (is_proto3 && submsg == NULL) { + return true; + } + return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) && + upb_encode_message(e, submsg, subm, &size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); } - case UPB_DESCRIPTOR_TYPE_GROUP: case UPB_DESCRIPTOR_TYPE_MESSAGE: { + size_t size; void *submsg = *(void**)field_mem; + const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; if (is_proto3 && submsg == NULL) { return true; } - return upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED) && - upb_encode_startdelim(e) && - upb_encode_message(e, submsg, m->submsgs[f->submsg_index]) && - upb_encode_enddelim(e); + return upb_encode_message(e, submsg, subm, &size) && + upb_put_varint(e, size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); } } #undef CASE @@ -479,34 +344,38 @@ bool upb_encode_hasscalarfield(const char *msg, } bool upb_encode_message(upb_encstate* e, const char *msg, - const upb_msglayout_msginit_v1 *m) { + const upb_msglayout_msginit_v1 *m, + size_t *size) { int i; - for (i = 0; i < m->field_count; i++) { + char *buf_end = e->ptr; + for (i = m->field_count - 1; i >= 0; i--) { const upb_msglayout_fieldinit_v1 *f = &m->fields[i]; if (f->label == UPB_LABEL_REPEATED) { - if (!upb_encode_array(e, msg, m, f)) { - return NULL; - } + CHK(upb_encode_array(e, msg, m, f)); } else { - if (upb_encode_hasscalarfield(msg, m, f) && - !upb_encode_scalarfield(e, msg + f->offset, m, f, !m->is_proto2)) { - return NULL; + if (upb_encode_hasscalarfield(msg, m, f)) { + CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, !m->is_proto2)); } } } + *size = buf_end - e->ptr; return true; } char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *m, upb_env *env, size_t *size) { upb_encstate e; + e.env = env; + e.buf = NULL; + e.limit = NULL; + e.ptr = NULL; - if (!upb_encode_message(&e, msg, m)) { + if (!upb_encode_message(&e, msg, m, size)) { return false; } - *size = e.ptr - e.buf; - return e.buf; + *size = e.limit - e.ptr; + return e.ptr; } -- cgit v1.2.3 From edad06a9fa9b9725ad6412156e573623e24bb17d Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Tue, 11 Jul 2017 14:40:35 -0500 Subject: WIP. --- upb/decode.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/upb/decode.c b/upb/decode.c index f28642b..7cffbe4 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -1,5 +1,6 @@ #include "upb/decode.h" +#include "upb/structs.int.h" typedef enum { UPB_WIRE_TYPE_VARINT = 0, @@ -17,6 +18,13 @@ typedef struct { const char *ptr; } upb_decstate; +typedef struct { + int32_t group_number; /* 0 if we are not parsing a group. */ + char *msg; + const upb_msglayout_msginit_v1 *m; + const char *limit; +} upb_decframe; + #define CHK(x) if (!(x)) { return false; } static void upb_decode_seterr(upb_env *env, const char *msg) { @@ -160,6 +168,25 @@ static bool upb_decode_unknownfielddata(upb_decstate *d, const char *ptr, } while (true); } +static bool upb_decode_knownfield(upb_decstate *d, const char *ptr, + const char *limit, char *msg, + const upb_msglayout_msginit_v1 *l, + const upb_msglayout_fieldinit_v1 *l) { + switch (wire_type) { + case UPB_WIRE_TYPE_VARINT: + return upb_decode_varintfield(d, ptr, limit, msg, l, f); + case UPB_WIRE_TYPE_32BIT: + return upb_decode_32bitfield(d, ptr, limit, msg, l, f); + case UPB_WIRE_TYPE_64BIT: + return upb_decode_64bitfield(d, ptr, limit, msg, l, f); + case UPB_WIRE_TYPE_DELIMITED: + return upb_decode_delimitedfield(d, ptr, limit, msg, l, f); + case UPB_WIRE_TYPE_START_GROUP: + case UPB_WIRE_TYPE_END_GROUP: + } +} + + static bool upb_decode_field(upb_decstate *d, const char *limit, char *msg, const upb_msglayout_msginit_v1 *l) { uint32_t tag; @@ -366,12 +393,9 @@ static bool upb_decode_field(upb_decstate *d, const char *limit, char *msg, return true; } -static bool upb_decode_message(upb_decstate *d, upb_stringview buf, - char *msg, const upb_msglayout_msginit_v1 *l) { - const char *limit = ptr + buf.size; - - while (d->ptr < limit) { - if (!upb_decode_field(&ptr, limit, msg, l, env)) { +static bool upb_decode_message(upb_decstate *d, upb_decframe *frame) { + while (d->ptr < frame->limit) { + if (!upb_decode_field(d, frame)) { return false; } } @@ -381,5 +405,15 @@ static bool upb_decode_message(upb_decstate *d, upb_stringview buf, bool upb_decode(upb_stringview buf, void *msg, const upb_msglayout_msginit_v1 *l, upb_env *env) { - return upb_decode_message(buf, msg, l, env); + upb_decstate state; + state.ptr = buf.data; + state.env = env; + + upb_decframe frame; + frame.msg = msg; + frame.l = l; + frame.group_number = 0; + frame.limit = buf.data + buf.size + + return upb_decode_message(&state, &frame); } -- cgit v1.2.3 From be9094d91a2da777002a0f713306ac1bb74a6ac5 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 17 Jul 2017 21:54:38 +0200 Subject: New encode/decode: most (171 / 192) conformance tests pass. --- tests/conformance_upb_failures.txt | 21 ++ tools/make_c_api.lua | 6 +- upb/decode.c | 727 ++++++++++++++++++++++--------------- upb/encode.c | 88 ++--- upb/msg.c | 2 +- upb/msg.h | 7 +- upb/pb/varint.int.h | 14 +- upb/upb.h | 12 +- 8 files changed, 525 insertions(+), 352 deletions(-) create mode 100644 tests/conformance_upb_failures.txt diff --git a/tests/conformance_upb_failures.txt b/tests/conformance_upb_failures.txt new file mode 100644 index 0000000..7ff834a --- /dev/null +++ b/tests/conformance_upb_failures.txt @@ -0,0 +1,21 @@ +Recommended.ProtobufInput.OneofZeroBool.ProtobufOutput +Recommended.ProtobufInput.OneofZeroBytes.ProtobufOutput +Recommended.ProtobufInput.OneofZeroDouble.ProtobufOutput +Recommended.ProtobufInput.OneofZeroEnum.ProtobufOutput +Recommended.ProtobufInput.OneofZeroFloat.ProtobufOutput +Recommended.ProtobufInput.OneofZeroString.ProtobufOutput +Recommended.ProtobufInput.OneofZeroUint32.ProtobufOutput +Recommended.ProtobufInput.OneofZeroUint64.ProtobufOutput +Required.ProtobufInput.PrematureEofInSubmessageValue.MESSAGE +Required.ProtobufInput.RepeatedScalarSelectsLast.BOOL.ProtobufOutput +Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput +Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput +Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput +Required.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput +Required.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput +Required.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput +Required.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput +Required.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput +Required.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput +Required.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput +Required.ProtobufInput.ValidDataScalar.BOOL.ProtobufOutput diff --git a/tools/make_c_api.lua b/tools/make_c_api.lua index 9e6d734..cfcf38d 100644 --- a/tools/make_c_api.lua +++ b/tools/make_c_api.lua @@ -417,7 +417,7 @@ local function write_c_file(filedef, hfilename, append) append('static const upb_msglayout_fieldinit_v1 %s[%s] = {\n', fields_array_name, field_count) for _, field in ipairs(fields_number_order) do - local submsg_index = "-1" + local submsg_index = "UPB_NO_SUBMSG" local oneof_index = "UPB_NOT_IN_ONEOF" if field:type() == upb.TYPE_MESSAGE then submsg_index = submsg_indexes[field:subdef()] @@ -430,7 +430,7 @@ local function write_c_file(filedef, hfilename, append) field:number(), msgname, (field:containing_oneof() and field:containing_oneof():name()) or field:name(), - hasbit_indexes[field] or "-1", + hasbit_indexes[field] or "UPB_NO_HASBIT", oneof_index, submsg_index, field:descriptor_type(), @@ -448,7 +448,7 @@ local function write_c_file(filedef, hfilename, append) msgname, field_count, 0, -- TODO: oneof_count 'false', -- TODO: extendable - 'true' -- TODO: is_proto2 + msg:file():syntax() == upb.SYNTAX_PROTO2 ) append('};\n\n') diff --git a/upb/decode.c b/upb/decode.c index 7cffbe4..a1910a1 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -1,16 +1,32 @@ +#include "upb/upb.h" #include "upb/decode.h" #include "upb/structs.int.h" -typedef enum { - UPB_WIRE_TYPE_VARINT = 0, - UPB_WIRE_TYPE_64BIT = 1, - UPB_WIRE_TYPE_DELIMITED = 2, - UPB_WIRE_TYPE_START_GROUP = 3, - UPB_WIRE_TYPE_END_GROUP = 4, - UPB_WIRE_TYPE_32BIT = 5 -} upb_wiretype_t; - +/* Maps descriptor type -> upb field type. */ +static const uint8_t upb_desctype_to_fieldtype[] = { + UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ + UPB_TYPE_DOUBLE, /* DOUBLE */ + UPB_TYPE_FLOAT, /* FLOAT */ + UPB_TYPE_INT64, /* INT64 */ + UPB_TYPE_UINT64, /* UINT64 */ + UPB_TYPE_INT32, /* INT32 */ + UPB_TYPE_UINT64, /* FIXED64 */ + UPB_TYPE_UINT32, /* FIXED32 */ + UPB_TYPE_BOOL, /* BOOL */ + UPB_TYPE_STRING, /* STRING */ + UPB_TYPE_MESSAGE, /* GROUP */ + UPB_TYPE_MESSAGE, /* MESSAGE */ + UPB_TYPE_BYTES, /* BYTES */ + UPB_TYPE_UINT32, /* UINT32 */ + UPB_TYPE_ENUM, /* ENUM */ + UPB_TYPE_INT32, /* SFIXED32 */ + UPB_TYPE_INT64, /* SFIXED64 */ + UPB_TYPE_INT32, /* SINT32 */ + UPB_TYPE_INT64, /* SINT64 */ +}; + +/* Data pertaining to the parse. */ typedef struct { upb_env *env; /* Current decoding pointer. Points to the beginning of a field until we @@ -18,20 +34,23 @@ typedef struct { const char *ptr; } upb_decstate; +/* Data pertaining to a single message frame. */ typedef struct { + const char *limit; int32_t group_number; /* 0 if we are not parsing a group. */ + + /* These members are unset for an unknown group frame. */ char *msg; const upb_msglayout_msginit_v1 *m; - const char *limit; } upb_decframe; #define CHK(x) if (!(x)) { return false; } -static void upb_decode_seterr(upb_env *env, const char *msg) { - upb_status status = UPB_STATUS_INIT; - upb_status_seterrmsg(&status, msg); - upb_env_reporterror(env, &status); -} +static bool upb_skip_unknowngroup(upb_decstate *d, int field_number, + const char *limit); +static bool upb_decode_message(upb_decstate *d, const char *limit, + int group_number, char *msg, + const upb_msglayout_msginit_v1 *l); static bool upb_decode_varint(const char **ptr, const char *limit, uint64_t *val) { @@ -41,10 +60,7 @@ static bool upb_decode_varint(const char **ptr, const char *limit, *val = 0; while (byte & 0x80) { - if (bitpos == 70 || p == limit) { - return false; - } - + CHK(bitpos < 70 && p < limit); byte = *p; *val |= (uint64_t)(byte & 0x7F) << bitpos; p++; @@ -58,47 +74,34 @@ static bool upb_decode_varint(const char **ptr, const char *limit, static bool upb_decode_varint32(const char **ptr, const char *limit, uint32_t *val) { uint64_t u64; - if (!upb_decode_varint(ptr, limit, &u64) || u64 > UINT32_MAX) { - return false; - } else { - *val = u64; - return true; - } -} - -static const upb_msglayout_fieldinit_v1 *upb_find_field( - const upb_msglayout_msginit_v1 *l, uint32_t field_number) { - /* Lots of optimization opportunities here. */ - int i; - for (i = 0; i < l->field_count; i++) { - if (l->fields[i].number == field_number) { - return &l->fields[i]; - } - } - - return NULL; /* Unknown field. */ + CHK(upb_decode_varint(ptr, limit, &u64) && u64 <= UINT32_MAX); + *val = u64; + return true; } static bool upb_decode_64bit(const char **ptr, const char *limit, uint64_t *val) { - if (limit - *ptr < 8) { - return false; - } else { - memcpy(val, *ptr, 8); - *ptr += 8; - return true; - } + CHK(limit - *ptr >= 8); + memcpy(val, *ptr, 8); + *ptr += 8; + return true; } static bool upb_decode_32bit(const char **ptr, const char *limit, uint32_t *val) { - if (limit - *ptr < 4) { - return false; - } else { - memcpy(val, *ptr, 4); - *ptr += 4; - return true; - } + CHK(limit - *ptr >= 4); + memcpy(val, *ptr, 4); + *ptr += 4; + return true; +} + +static bool upb_decode_tag(const char **ptr, const char *limit, + int *field_number, int *wire_type) { + uint32_t tag; + CHK(upb_decode_varint32(ptr, limit, &tag)); + *field_number = tag >> 3; + *wire_type = tag & 7; + return true; } static int32_t upb_zzdec_32(uint32_t n) { @@ -113,10 +116,7 @@ static bool upb_decode_string(const char **ptr, const char *limit, upb_stringview *val) { uint32_t len; - if (!upb_decode_varint32(ptr, limit, &len) || - limit - *ptr < len) { - return false; - } + CHK(upb_decode_varint32(ptr, limit, &len) && limit - *ptr >= len); *val = upb_stringview_make(*ptr, len); *ptr += len; @@ -127,277 +127,436 @@ static void upb_set32(void *msg, size_t ofs, uint32_t val) { memcpy((char*)msg + ofs, &val, sizeof(val)); } -static bool upb_append_unknownfield(const char **ptr, const char *start, - const char *limit, char *msg) { - UPB_UNUSED(limit); - UPB_UNUSED(msg); - *ptr = limit; +static bool upb_append_unknown(upb_decstate *d, upb_decframe *frame, + const char *start) { + UPB_UNUSED(d); + UPB_UNUSED(frame); + UPB_UNUSED(start); return true; } -static bool upb_decode_unknownfielddata(upb_decstate *d, const char *ptr, - const char *limit, char *msg, - const upb_msglayout_msginit_v1 *l) { - do { - switch (wire_type) { - case UPB_WIRE_TYPE_VARINT: - CHK(upb_decode_varint(&ptr, limit, &val)); - break; - case UPB_WIRE_TYPE_32BIT: - CHK(upb_decode_32bit(&ptr, limit, &val)); - break; - case UPB_WIRE_TYPE_64BIT: - CHK(upb_decode_64bit(&ptr, limit, &val)); - break; - case UPB_WIRE_TYPE_DELIMITED: { - upb_stringview val; - CHK(upb_decode_string(&ptr, limit, &val)); - } - case UPB_WIRE_TYPE_START_GROUP: - depth++; - continue; - case UPB_WIRE_TYPE_END_GROUP: - depth--; - continue; +static bool upb_skip_unknownfielddata(upb_decstate *d, upb_decframe *frame, + int field_number, int wire_type) { + switch (wire_type) { + case UPB_WIRE_TYPE_VARINT: { + uint64_t val; + return upb_decode_varint(&d->ptr, frame->limit, &val); + } + case UPB_WIRE_TYPE_32BIT: { + uint32_t val; + return upb_decode_32bit(&d->ptr, frame->limit, &val); + } + case UPB_WIRE_TYPE_64BIT: { + uint64_t val; + return upb_decode_64bit(&d->ptr, frame->limit, &val); } + case UPB_WIRE_TYPE_DELIMITED: { + upb_stringview val; + return upb_decode_string(&d->ptr, frame->limit, &val); + } + case UPB_WIRE_TYPE_START_GROUP: + return upb_skip_unknowngroup(d, field_number, frame->limit); + case UPB_WIRE_TYPE_END_GROUP: + CHK(field_number == frame->group_number); + frame->limit = d->ptr; + return true; + } + return false; +} - UPB_ASSERT(depth == 0); - upb_append_unknown(msg, l, d->ptr, ptr); - d->ptr = ptr; - return true; - } while (true); +static bool upb_array_grow(upb_array *arr, size_t elements) { + size_t needed = arr->len + elements; + size_t new_size = UPB_MAX(arr->size, 8); + size_t new_bytes; + size_t old_bytes; + void *new_data; + + while (new_size < needed) { + new_size *= 2; + } + + old_bytes = arr->len * arr->element_size; + new_bytes = new_size * arr->element_size; + new_data = upb_realloc(arr->alloc, arr->data, old_bytes, new_bytes); + CHK(new_data); + + arr->data = new_data; + arr->size = new_size; + return true; } -static bool upb_decode_knownfield(upb_decstate *d, const char *ptr, - const char *limit, char *msg, - const upb_msglayout_msginit_v1 *l, - const upb_msglayout_fieldinit_v1 *l) { - switch (wire_type) { - case UPB_WIRE_TYPE_VARINT: - return upb_decode_varintfield(d, ptr, limit, msg, l, f); - case UPB_WIRE_TYPE_32BIT: - return upb_decode_32bitfield(d, ptr, limit, msg, l, f); - case UPB_WIRE_TYPE_64BIT: - return upb_decode_64bitfield(d, ptr, limit, msg, l, f); - case UPB_WIRE_TYPE_DELIMITED: - return upb_decode_delimitedfield(d, ptr, limit, msg, l, f); - case UPB_WIRE_TYPE_START_GROUP: - case UPB_WIRE_TYPE_END_GROUP: +static void *upb_array_reserve(upb_array *arr, size_t elements) { + if (arr->size - arr->len < elements) { + CHK(upb_array_grow(arr, elements)); } + return (char*)arr->data + (arr->len * arr->element_size); } +static void *upb_array_add(upb_array *arr, size_t elements) { + void *ret = upb_array_reserve(arr, elements); + arr->len += elements; + return ret; +} -static bool upb_decode_field(upb_decstate *d, const char *limit, char *msg, - const upb_msglayout_msginit_v1 *l) { - uint32_t tag; - uint32_t wire_type; - uint32_t field_number; - const char *ptr = d->ptr; - const upb_msglayout_fieldinit_v1 *f; - - if (!upb_decode_varint32(&ptr, limit, &tag)) { - upb_decode_seterr(env, "Error decoding tag.\n"); - return false; +static upb_array *upb_getarr(upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + UPB_ASSERT(field->label == UPB_LABEL_REPEATED); + return *(upb_array**)&frame->msg[field->offset]; +} + +static upb_array *upb_getorcreatearr(upb_decstate *d, + upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + upb_array *arr = upb_getarr(frame, field); + + if (!arr) { + arr = upb_env_malloc(d->env, sizeof(*arr)); + if (!arr) { + return NULL; + } + upb_array_init(arr, upb_desctype_to_fieldtype[field->type], + upb_arena_alloc(upb_env_arena(d->env))); + *(upb_array**)&frame->msg[field->offset] = arr; } - wire_type = tag & 0x7; - field_number = tag >> 3; + return arr; +} + +static void upb_sethasbit(upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + UPB_ASSERT(field->hasbit != UPB_NO_HASBIT); + frame->msg[field->hasbit / 8] |= (1 << (field->hasbit % 8)); +} + +static void upb_setoneofcase(upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + UPB_ASSERT(field->oneof_index != UPB_NOT_IN_ONEOF); + upb_set32(frame->msg, frame->m->oneofs[field->oneof_index].case_offset, + field->number); +} + +static char *upb_decode_prepareslot(upb_decstate *d, + upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + char *field_mem = frame->msg + field->offset; + upb_array *arr; - if (field_number == 0) { - return false; + if (field->label == UPB_LABEL_REPEATED) { + arr = upb_getorcreatearr(d, frame, field); + field_mem = upb_array_reserve(arr, 1); } - f = upb_find_field(l, field_number); + return field_mem; +} - if (f) { - return upb_decode_knownfield(d, ptr, limit, msg, l, f); - } else { - return upb_decode_unknownfield(d, ptr, limit, msg, l); +static void upb_decode_setpresent(upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + if (field->label == UPB_LABEL_REPEATED) { + upb_array *arr = upb_getarr(frame, field); + UPB_ASSERT(arr->len < arr->size); + arr->len++; + } else if (field->oneof_index != UPB_NOT_IN_ONEOF) { + upb_setoneofcase(frame, field); + } else if (field->hasbit != UPB_NO_HASBIT) { + upb_sethasbit(frame, field); } +} - if (f->label == UPB_LABEL_REPEATED) { - arr = upb_getarray(msg, f, env); +static bool upb_decode_submsg(upb_decstate *d, + upb_decframe *frame, + const char *limit, + const upb_msglayout_fieldinit_v1 *field, + int group_number) { + char *submsg = *(void**)&frame->msg[field->offset]; + const upb_msglayout_msginit_v1 *subm; + + UPB_ASSERT(field->submsg_index != UPB_NO_SUBMSG); + subm = frame->m->submsgs[field->submsg_index]; + UPB_ASSERT(subm); + + if (!submsg) { + submsg = upb_env_malloc(d->env, upb_msg_sizeof((upb_msglayout *)subm)); + CHK(submsg); + submsg = upb_msg_init( + submsg, (upb_msglayout*)subm, upb_arena_alloc(upb_env_arena(d->env))); + *(void**)&frame->msg[field->offset] = submsg; } - switch (wire_type) { - case UPB_WIRE_TYPE_VARINT: { - uint64_t val; - if (!upb_decode_varint(&ptr, limit, &val)) { - upb_decode_seterr(env, "Error decoding varint value.\n"); - return false; - } + upb_decode_message(d, limit, group_number, submsg, subm); - if (!f) { - return upb_append_unknown(ptr, field_start, ptr, msg); - } + return true; +} - if (f->label == UPB_LABEL_REPEATED) { - upb_array *arr = upb_getarray(msg, f, env); - switch (f->type) { - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_UINT64: - memcpy(arr->data, &val, sizeof(val)); - arr->len++; - break; - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_ENUM: { - uint32_t val32 = val; - memcpy(arr->data, &val32, sizeof(val32)); - arr->len++; - break; - } - case UPB_DESCRIPTOR_TYPE_SINT32: { - int32_t decoded = upb_zzdec_32(val); - memcpy(arr->data, &decoded, sizeof(decoded)); - arr->len++; - break; - } - case UPB_DESCRIPTOR_TYPE_SINT64: { - int64_t decoded = upb_zzdec_64(val); - memcpy(arr->data, &decoded, sizeof(decoded)); - arr->len++; - break; - } - default: - return upb_append_unknown(ptr, field_start, ptr, msg); - } - } else { - switch (f->type) { - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_UINT64: - memcpy(msg + f->offset, &val, sizeof(val)); - break; - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_ENUM: { - uint32_t val32 = val; - memcpy(msg + f->offset, &val32, sizeof(val32)); - break; - } - case UPB_DESCRIPTOR_TYPE_SINT32: { - int32_t decoded = upb_zzdec_32(val); - memcpy(msg + f->offset, &decoded, sizeof(decoded)); - break; - } - case UPB_DESCRIPTOR_TYPE_SINT64: { - int64_t decoded = upb_zzdec_64(val); - memcpy(msg + f->offset, &decoded, sizeof(decoded)); - break; - } - default: - return upb_append_unknown(ptr, field_start, ptr, msg); - } - } +static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field) { + uint64_t val; + void *field_mem; + field_mem = upb_decode_prepareslot(d, frame, field); + CHK(field_mem); + CHK(upb_decode_varint(&d->ptr, frame->limit, &val)); + + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + memcpy(field_mem, &val, sizeof(val)); + break; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_ENUM: { + uint32_t val32 = val; + memcpy(field_mem, &val32, sizeof(val32)); break; } - case UPB_WIRE_TYPE_64BIT: { - uint64_t val; - if (!upb_decode_64bit(&ptr, limit, &val)) { - upb_decode_seterr(env, "Error decoding 64bit value.\n"); - return false; - } + case UPB_DESCRIPTOR_TYPE_SINT32: { + int32_t decoded = upb_zzdec_32(val); + memcpy(field_mem, &decoded, sizeof(decoded)); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT64: { + int64_t decoded = upb_zzdec_64(val); + memcpy(field_mem, &decoded, sizeof(decoded)); + break; + } + default: + return upb_append_unknown(d, frame, field_start); + } - if (!f) { - return upb_append_unknown(ptr, field_start, ptr, msg); - } + upb_decode_setpresent(frame, field); + return true; +} - switch (f->type) { - case UPB_DESCRIPTOR_TYPE_DOUBLE: - case UPB_DESCRIPTOR_TYPE_FIXED64: - case UPB_DESCRIPTOR_TYPE_SFIXED64: - memcpy(msg + f->offset, &val, sizeof(val)); - default: - return upb_append_unknown(ptr, field_start, ptr, msg); - } +static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field) { + void *field_mem; + uint64_t val; + + field_mem = upb_decode_prepareslot(d, frame, field); + CHK(field_mem); + CHK(upb_decode_64bit(&d->ptr, frame->limit, &val)); + + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + case UPB_DESCRIPTOR_TYPE_FIXED64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + memcpy(field_mem, &val, sizeof(val)); + break; + default: + return upb_append_unknown(d, frame, field_start); + } + upb_decode_setpresent(frame, field); + return true; +} + +static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field) { + void *field_mem; + uint32_t val; + + field_mem = upb_decode_prepareslot(d, frame, field); + CHK(field_mem); + CHK(upb_decode_32bit(&d->ptr, frame->limit, &val)); + + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_FLOAT: + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + memcpy(field_mem, &val, sizeof(val)); break; + default: + return upb_append_unknown(d, frame, field_start); + } + + upb_decode_setpresent(frame, field); + return true; +} + +static bool upb_decode_fixedpacked(upb_array *arr, upb_stringview data, + int elem_size) { + int elements = data.size / elem_size; + void *field_mem; + + CHK((data.size % elem_size) == 0); + field_mem = upb_array_add(arr, elements); + CHK(field_mem); + memcpy(field_mem, data.data, data.size); + return true; +} + +static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field, + upb_stringview val) { + upb_array *arr = upb_getorcreatearr(d, frame, field); + +#define VARINT_CASE(ctype, decode) { \ + const char *ptr = val.data; \ + const char *limit = ptr + val.size; \ + while (ptr < limit) { \ + uint64_t val; \ + void *field_mem; \ + ctype decoded; \ + CHK(upb_decode_varint(&ptr, limit, &val)); \ + decoded = (decode)(val); \ + field_mem = upb_array_add(arr, 1); \ + CHK(field_mem); \ + memcpy(field_mem, &decoded, sizeof(ctype)); \ + } \ + return true; \ +} + + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + void *field_mem = upb_array_add(arr, 1); + CHK(field_mem); + memcpy(field_mem, &val, sizeof(val)); + return true; } - case UPB_WIRE_TYPE_32BIT: { - uint32_t val; - if (!upb_decode_32bit(&ptr, limit, &val)) { - upb_decode_seterr(env, "Error decoding 32bit value.\n"); - return false; - } + case UPB_DESCRIPTOR_TYPE_FLOAT: + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + return upb_decode_fixedpacked(arr, val, sizeof(int32_t)); + case UPB_DESCRIPTOR_TYPE_DOUBLE: + case UPB_DESCRIPTOR_TYPE_FIXED64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + return upb_decode_fixedpacked(arr, val, sizeof(int64_t)); + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + /* TODO: proto2 enum field that isn't in the enum. */ + VARINT_CASE(uint32_t, uint32_t); + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + VARINT_CASE(uint64_t, uint64_t); + case UPB_DESCRIPTOR_TYPE_BOOL: + VARINT_CASE(bool, bool); + case UPB_DESCRIPTOR_TYPE_SINT32: + VARINT_CASE(int32_t, upb_zzdec_32); + case UPB_DESCRIPTOR_TYPE_SINT64: + VARINT_CASE(int64_t, upb_zzdec_64); + case UPB_DESCRIPTOR_TYPE_MESSAGE: + CHK(val.size <= (size_t)(frame->limit - val.data)); + return upb_decode_submsg(d, frame, val.data + val.size, field, 0); + case UPB_DESCRIPTOR_TYPE_GROUP: + return upb_append_unknown(d, frame, field_start); + } +#undef VARINT_CASE +} - if (!f) { - return upb_append_unknown(ptr, field_start, ptr, msg); - } +static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field) { + upb_stringview val; + + CHK(upb_decode_string(&d->ptr, frame->limit, &val)); - switch (f->type) { - case UPB_DESCRIPTOR_TYPE_FLOAT: - case UPB_DESCRIPTOR_TYPE_FIXED32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - memcpy(msg + f->offset, &val, sizeof(val)); - default: - return upb_append_unknown(ptr, field_start, ptr, msg); + if (field->label == UPB_LABEL_REPEATED) { + return upb_decode_toarray(d, frame, field_start, field, val); + } else { + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + void *field_mem = upb_decode_prepareslot(d, frame, field); + CHK(field_mem); + memcpy(field_mem, &val, sizeof(val)); + break; } + case UPB_DESCRIPTOR_TYPE_MESSAGE: + CHK(val.size <= (size_t)(frame->limit - val.data)); + CHK(upb_decode_submsg(d, frame, val.data + val.size, field, 0)); + break; + default: + /* TODO(haberman): should we accept the last element of a packed? */ + return upb_append_unknown(d, frame, field_start); + } + upb_decode_setpresent(frame, field); + return true; + } +} - break; +static const upb_msglayout_fieldinit_v1 *upb_find_field( + const upb_msglayout_msginit_v1 *l, uint32_t field_number) { + /* Lots of optimization opportunities here. */ + int i; + for (i = 0; i < l->field_count; i++) { + if (l->fields[i].number == field_number) { + return &l->fields[i]; } - case UPB_WIRE_TYPE_DELIMITED: { - upb_stringview val; - if (!upb_decode_string(&ptr, limit, &val)) { - upb_decode_seterr(env, "Error decoding delimited value.\n"); - return false; - } + } - if (!f) { - return upb_append_unknown(ptr, field_start, ptr, msg); - } + return NULL; /* Unknown field. */ +} - switch (f->type) { - case UPB_DESCRIPTOR_TYPE_STRING: - case UPB_DESCRIPTOR_TYPE_BYTES: - memcpy(msg + f->offset, &val, sizeof(val)); - break; - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_UINT64: { - memcpy(msg + f->offset, &val, sizeof(val)); - break; - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_ENUM: { - uint32_t val32 = val; - memcpy(msg + f->offset, &val32, sizeof(val32)); - break; - } - case UPB_DESCRIPTOR_TYPE_SINT32: { - int32_t decoded = upb_zzdec_32(val); - memcpy(msg + f->offset, &decoded, sizeof(decoded)); - break; - } - case UPB_DESCRIPTOR_TYPE_SINT64: - case UPB_DESCRIPTOR_TYPE_FLOAT: - case UPB_DESCRIPTOR_TYPE_FIXED32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - /* - case UPB_DESCRIPTOR_TYPE_MESSAGE: { - upb_decode_message(val, - } - */ - default: - return upb_append_unknown(ptr, field_start, ptr, msg); - } +static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) { + int field_number; + int wire_type; + const char *field_start = d->ptr; + const upb_msglayout_fieldinit_v1 *field; - break; + CHK(upb_decode_tag(&d->ptr, frame->limit, &field_number, &wire_type)); + field = upb_find_field(frame->m, field_number); + + if (field) { + switch (wire_type) { + case UPB_WIRE_TYPE_VARINT: + return upb_decode_varintfield(d, frame, field_start, field); + case UPB_WIRE_TYPE_32BIT: + return upb_decode_32bitfield(d, frame, field_start, field); + case UPB_WIRE_TYPE_64BIT: + return upb_decode_64bitfield(d, frame, field_start, field); + case UPB_WIRE_TYPE_DELIMITED: + return upb_decode_delimitedfield(d, frame, field_start, field); + case UPB_WIRE_TYPE_START_GROUP: + CHK(field->type == UPB_DESCRIPTOR_TYPE_GROUP); + return upb_decode_submsg(d, frame, frame->limit, field, field_number); + case UPB_WIRE_TYPE_END_GROUP: + CHK(frame->group_number == field_number) + frame->limit = d->ptr; + return true; + default: + return false; } + } else { + CHK(field_number != 0); + return upb_skip_unknownfielddata(d, frame, field_number, wire_type); } +} + +static bool upb_skip_unknowngroup(upb_decstate *d, int field_number, + const char *limit) { + upb_decframe frame; + frame.msg = NULL; + frame.m = NULL; + frame.group_number = field_number; + frame.limit = limit; - if (f->oneof_index != UPB_NOT_IN_ONEOF) { - upb_set32(msg, l->oneofs[f->oneof_index].case_offset, f->number); + while (d->ptr < frame.limit) { + int wire_type; + int field_number; + + CHK(upb_decode_tag(&d->ptr, frame.limit, &field_number, &wire_type)); + CHK(upb_skip_unknownfielddata(d, &frame, field_number, wire_type)); } - d->ptr = ptr; return true; } -static bool upb_decode_message(upb_decstate *d, upb_decframe *frame) { - while (d->ptr < frame->limit) { - if (!upb_decode_field(d, frame)) { - return false; - } +static bool upb_decode_message(upb_decstate *d, const char *limit, + int group_number, char *msg, + const upb_msglayout_msginit_v1 *l) { + upb_decframe frame; + frame.group_number = group_number; + frame.limit = limit; + frame.msg = msg; + frame.m = l; + + while (d->ptr < frame.limit) { + CHK(upb_decode_field(d, &frame)); } return true; @@ -409,11 +568,5 @@ bool upb_decode(upb_stringview buf, void *msg, state.ptr = buf.data; state.env = env; - upb_decframe frame; - frame.msg = msg; - frame.l = l; - frame.group_number = 0; - frame.limit = buf.data + buf.size - - return upb_decode_message(&state, &frame); + return upb_decode_message(&state, buf.data + buf.size, 0, msg, l); } diff --git a/upb/encode.c b/upb/encode.c index 2fe1cc3..ced971e 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -1,10 +1,35 @@ +/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */ +#include "upb/upb.h" #include "upb/encode.h" #include "upb/structs.int.h" #define UPB_PB_VARINT_MAX_LEN 10 #define CHK(x) do { if (!(x)) { return false; } } while(0) +/* Maps descriptor type -> upb field type. */ +static const uint8_t upb_desctype_to_fieldtype[] = { + UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ + UPB_TYPE_DOUBLE, /* DOUBLE */ + UPB_TYPE_FLOAT, /* FLOAT */ + UPB_TYPE_INT64, /* INT64 */ + UPB_TYPE_UINT64, /* UINT64 */ + UPB_TYPE_INT32, /* INT32 */ + UPB_TYPE_UINT64, /* FIXED64 */ + UPB_TYPE_UINT32, /* FIXED32 */ + UPB_TYPE_BOOL, /* BOOL */ + UPB_TYPE_STRING, /* STRING */ + UPB_TYPE_MESSAGE, /* GROUP */ + UPB_TYPE_MESSAGE, /* MESSAGE */ + UPB_TYPE_BYTES, /* BYTES */ + UPB_TYPE_UINT32, /* UINT32 */ + UPB_TYPE_ENUM, /* ENUM */ + UPB_TYPE_INT32, /* SFIXED32 */ + UPB_TYPE_INT64, /* SFIXED64 */ + UPB_TYPE_INT32, /* SINT32 */ + UPB_TYPE_INT64, /* SINT64 */ +}; + static size_t upb_encode_varint(uint64_t val, char *buf) { size_t i; if (val == 0) { buf[0] = 0; return 1; } @@ -21,38 +46,6 @@ static size_t upb_encode_varint(uint64_t val, char *buf) { static uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); } static uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } -typedef enum { - UPB_WIRE_TYPE_VARINT = 0, - UPB_WIRE_TYPE_64BIT = 1, - UPB_WIRE_TYPE_DELIMITED = 2, - UPB_WIRE_TYPE_START_GROUP = 3, - UPB_WIRE_TYPE_END_GROUP = 4, - UPB_WIRE_TYPE_32BIT = 5 -} upb_wiretype_t; - -/* Index is descriptor type. */ -const uint8_t upb_native_wiretypes[] = { - UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ - UPB_WIRE_TYPE_64BIT, /* DOUBLE */ - UPB_WIRE_TYPE_32BIT, /* FLOAT */ - UPB_WIRE_TYPE_VARINT, /* INT64 */ - UPB_WIRE_TYPE_VARINT, /* UINT64 */ - UPB_WIRE_TYPE_VARINT, /* INT32 */ - UPB_WIRE_TYPE_64BIT, /* FIXED64 */ - UPB_WIRE_TYPE_32BIT, /* FIXED32 */ - UPB_WIRE_TYPE_VARINT, /* BOOL */ - UPB_WIRE_TYPE_DELIMITED, /* STRING */ - UPB_WIRE_TYPE_START_GROUP, /* GROUP */ - UPB_WIRE_TYPE_DELIMITED, /* MESSAGE */ - UPB_WIRE_TYPE_DELIMITED, /* BYTES */ - UPB_WIRE_TYPE_VARINT, /* UINT32 */ - UPB_WIRE_TYPE_VARINT, /* ENUM */ - UPB_WIRE_TYPE_32BIT, /* SFIXED32 */ - UPB_WIRE_TYPE_64BIT, /* SFIXED64 */ - UPB_WIRE_TYPE_VARINT, /* SINT32 */ - UPB_WIRE_TYPE_VARINT, /* SINT64 */ -}; - typedef struct { upb_env *env; char *buf, *ptr, *limit; @@ -165,21 +158,24 @@ static bool upb_encode_array(upb_encstate *e, const char *field_mem, const upb_msglayout_fieldinit_v1 *f) { const upb_array *arr = *(const upb_array**)field_mem; - if (arr->len == 0) { + if (arr == NULL || arr->len == 0) { return true; } -#define VARINT_CASE(ctype, encode) do { \ - uint64_t *start = arr->data; \ - uint64_t *ptr = start + arr->len; \ + UPB_ASSERT(arr->type == upb_desctype_to_fieldtype[f->type]); + +#define VARINT_CASE(ctype, encode) { \ + ctype *start = arr->data; \ + ctype *ptr = start + arr->len; \ char *buf_ptr = e->ptr; \ do { \ ptr--; \ CHK(upb_put_varint(e, encode)); \ } while (ptr != start); \ CHK(upb_put_varint(e, buf_ptr - e->ptr)); \ - break; \ -} while(0) +} \ +break; \ +do { ; } while(0) switch (f->type) { case UPB_DESCRIPTOR_TYPE_DOUBLE: @@ -352,7 +348,7 @@ bool upb_encode_message(upb_encstate* e, const char *msg, const upb_msglayout_fieldinit_v1 *f = &m->fields[i]; if (f->label == UPB_LABEL_REPEATED) { - CHK(upb_encode_array(e, msg, m, f)); + CHK(upb_encode_array(e, msg + f->offset, m, f)); } else { if (upb_encode_hasscalarfield(msg, m, f)) { CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, !m->is_proto2)); @@ -372,10 +368,14 @@ char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *m, e.limit = NULL; e.ptr = NULL; - if (!upb_encode_message(&e, msg, m, size)) { - return false; - } - + CHK(upb_encode_message(&e, msg, m, size)); *size = e.limit - e.ptr; - return e.ptr; + + if (*size == 0) { + static char ch; + return &ch; + } else { + UPB_ASSERT(e.ptr); + return e.ptr; + } } diff --git a/upb/msg.c b/upb/msg.c index f0a4201..b3b0420 100644 --- a/upb/msg.c +++ b/upb/msg.c @@ -68,7 +68,7 @@ static size_t upb_msgval_sizeof(upb_fieldtype_t type) { case UPB_TYPE_MESSAGE: return sizeof(void*); case UPB_TYPE_STRING: - return sizeof(char*) + sizeof(size_t); + return sizeof(upb_stringview); } UPB_UNREACHABLE(); } diff --git a/upb/msg.h b/upb/msg.h index 71df7f1..3579a3f 100644 --- a/upb/msg.h +++ b/upb/msg.h @@ -388,13 +388,14 @@ bool upb_msg_getscalarhandlerdata(const upb_handlers *h, #define UPB_NOT_IN_ONEOF UINT16_MAX #define UPB_NO_HASBIT UINT16_MAX +#define UPB_NO_SUBMSG UINT16_MAX typedef struct { uint32_t number; uint32_t offset; /* If in a oneof, offset of default in default_msg below. */ - uint16_t hasbit; - uint16_t oneof_index; /* UPB_NOT_IN_ONEOF if not in a oneof. */ - uint16_t submsg_index; + uint16_t hasbit; /* UPB_NO_HASBIT if no hasbit. */ + uint16_t oneof_index; /* UPB_NOT_IN_ONEOF if not in a oneof. */ + uint16_t submsg_index; /* UPB_NO_SUBMSG if no submsg. */ uint8_t type; uint8_t label; } upb_msglayout_fieldinit_v1; diff --git a/upb/pb/varint.int.h b/upb/pb/varint.int.h index 3ef84fb..9c54311 100644 --- a/upb/pb/varint.int.h +++ b/upb/pb/varint.int.h @@ -15,21 +15,9 @@ extern "C" { #endif -/* A list of types as they are encoded on-the-wire. */ -typedef enum { - UPB_WIRE_TYPE_VARINT = 0, - UPB_WIRE_TYPE_64BIT = 1, - UPB_WIRE_TYPE_DELIMITED = 2, - UPB_WIRE_TYPE_START_GROUP = 3, - UPB_WIRE_TYPE_END_GROUP = 4, - UPB_WIRE_TYPE_32BIT = 5 -} upb_wiretype_t; - #define UPB_MAX_WIRE_TYPE 5 -/* The maximum number of bytes that it takes to encode a 64-bit varint. - * Note that with a better encoding this could be 9 (TODO: write up a - * wiki document about this). */ +/* The maximum number of bytes that it takes to encode a 64-bit varint. */ #define UPB_PB_VARINT_MAX_LEN 10 /* Array of the "native" (ie. non-packed-repeated) wire type for the given a diff --git a/upb/upb.h b/upb/upb.h index 19cd02c..2d6db8e 100644 --- a/upb/upb.h +++ b/upb/upb.h @@ -298,6 +298,16 @@ class PointerBase2 : public PointerBase { #endif +/* A list of types as they are encoded on-the-wire. */ +typedef enum { + UPB_WIRE_TYPE_VARINT = 0, + UPB_WIRE_TYPE_64BIT = 1, + UPB_WIRE_TYPE_DELIMITED = 2, + UPB_WIRE_TYPE_START_GROUP = 3, + UPB_WIRE_TYPE_END_GROUP = 4, + UPB_WIRE_TYPE_32BIT = 5 +} upb_wiretype_t; + /* upb::ErrorSpace ************************************************************/ @@ -626,7 +636,7 @@ void upb_env_uninit(upb_env *e); void upb_env_initonly(upb_env *e); -upb_arena *upb_env_arena(upb_env *e); +UPB_INLINE upb_arena *upb_env_arena(upb_env *e) { return (upb_arena*)e; } bool upb_env_ok(const upb_env *e); void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud); -- cgit v1.2.3 From b697882fb272c2f3408f5c821a88aaf3e3db6f52 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Tue, 18 Jul 2017 01:04:48 +0200 Subject: Fixed varint length when buffer is reallocated. --- tests/conformance_upb_failures.txt | 6 ------ upb/encode.c | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/tests/conformance_upb_failures.txt b/tests/conformance_upb_failures.txt index 7ff834a..33c013d 100644 --- a/tests/conformance_upb_failures.txt +++ b/tests/conformance_upb_failures.txt @@ -12,10 +12,4 @@ Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput Required.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput -Required.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput -Required.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput -Required.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput -Required.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput -Required.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput -Required.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput Required.ProtobufInput.ValidDataScalar.BOOL.ProtobufOutput diff --git a/upb/encode.c b/upb/encode.c index ced971e..8a220ef 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -167,12 +167,12 @@ static bool upb_encode_array(upb_encstate *e, const char *field_mem, #define VARINT_CASE(ctype, encode) { \ ctype *start = arr->data; \ ctype *ptr = start + arr->len; \ - char *buf_ptr = e->ptr; \ + size_t pre_len = e->limit - e->ptr; \ do { \ ptr--; \ CHK(upb_put_varint(e, encode)); \ } while (ptr != start); \ - CHK(upb_put_varint(e, buf_ptr - e->ptr)); \ + CHK(upb_put_varint(e, e->limit - e->ptr - pre_len)); \ } \ break; \ do { ; } while(0) -- cgit v1.2.3 From 15308afff2d0d288b73c1b4278bd28f926ce02b8 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Tue, 18 Jul 2017 01:58:03 +0200 Subject: Fixes for oneof conformance tests. --- tests/conformance_upb_failures.txt | 14 -------------- upb/decode.c | 5 +++++ upb/encode.c | 13 +++++++++---- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/tests/conformance_upb_failures.txt b/tests/conformance_upb_failures.txt index 33c013d..05aab58 100644 --- a/tests/conformance_upb_failures.txt +++ b/tests/conformance_upb_failures.txt @@ -1,15 +1 @@ -Recommended.ProtobufInput.OneofZeroBool.ProtobufOutput -Recommended.ProtobufInput.OneofZeroBytes.ProtobufOutput -Recommended.ProtobufInput.OneofZeroDouble.ProtobufOutput -Recommended.ProtobufInput.OneofZeroEnum.ProtobufOutput -Recommended.ProtobufInput.OneofZeroFloat.ProtobufOutput -Recommended.ProtobufInput.OneofZeroString.ProtobufOutput -Recommended.ProtobufInput.OneofZeroUint32.ProtobufOutput -Recommended.ProtobufInput.OneofZeroUint64.ProtobufOutput Required.ProtobufInput.PrematureEofInSubmessageValue.MESSAGE -Required.ProtobufInput.RepeatedScalarSelectsLast.BOOL.ProtobufOutput -Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput -Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput -Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput -Required.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput -Required.ProtobufInput.ValidDataScalar.BOOL.ProtobufOutput diff --git a/upb/decode.c b/upb/decode.c index a1910a1..3a44021 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -309,6 +309,11 @@ static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame, memcpy(field_mem, &val32, sizeof(val32)); break; } + case UPB_DESCRIPTOR_TYPE_BOOL: { + bool valbool = val != 0; + memcpy(field_mem, &valbool, sizeof(valbool)); + break; + } case UPB_DESCRIPTOR_TYPE_SINT32: { int32_t decoded = upb_zzdec_32(val); memcpy(field_mem, &decoded, sizeof(decoded)); diff --git a/upb/encode.c b/upb/encode.c index 8a220ef..4aafb9c 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -258,7 +258,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, bool is_proto3) { #define CASE(ctype, type, wire_type, encodeval) do { \ ctype val = *(ctype*)field_mem; \ - if (is_proto3 && val == 0) { \ + if (is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF && val == 0) { \ return true; \ } \ return upb_put_ ## type(e, encodeval) && \ @@ -292,7 +292,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { upb_stringview view = *(upb_stringview*)field_mem; - if (is_proto3 && view.size == 0) { + if (is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF && view.size == 0) { return true; } return upb_put_bytes(e, view.data, view.size) && @@ -303,7 +303,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, size_t size; void *submsg = *(void**)field_mem; const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; - if (is_proto3 && submsg == NULL) { + if (is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF && submsg == NULL) { return true; } return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) && @@ -314,7 +314,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, size_t size; void *submsg = *(void**)field_mem; const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; - if (is_proto3 && submsg == NULL) { + if (is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF && submsg == NULL) { return true; } return upb_encode_message(e, submsg, subm, &size) && @@ -344,6 +344,11 @@ bool upb_encode_message(upb_encstate* e, const char *msg, size_t *size) { int i; char *buf_end = e->ptr; + + if (msg == NULL) { + return true; + } + for (i = m->field_count - 1; i >= 0; i--) { const upb_msglayout_fieldinit_v1 *f = &m->fields[i]; -- cgit v1.2.3 From 806ffc1d2053f1c02167c7965b39abc997d12ad6 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Tue, 18 Jul 2017 11:48:29 +0200 Subject: Responded to PR comments. --- tests/conformance_upb.c | 2 +- tools/make_c_api.lua | 8 +++----- upb/decode.c | 9 +++++---- upb/encode.c | 8 ++++++-- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/conformance_upb.c b/tests/conformance_upb.c index e1221b2..2ef8c6d 100644 --- a/tests/conformance_upb.c +++ b/tests/conformance_upb.c @@ -114,7 +114,7 @@ bool DoTestIo() { char *serialized_input; char *serialized_output; uint32_t input_size; - size_t output_size = 0; + size_t output_size; conformance_ConformanceRequest *request; conformance_ConformanceResponse *response; diff --git a/tools/make_c_api.lua b/tools/make_c_api.lua index cfcf38d..552e861 100644 --- a/tools/make_c_api.lua +++ b/tools/make_c_api.lua @@ -155,6 +155,8 @@ local function field_layout_rank(field) -- 1. padding alignment is (nearly) minimized. -- 2. fields that might have defaults (1-4) are segregated -- from fields that are always zero-initialized (5-7). + -- + -- We skip oneof fields, because they are emitted in a separate pass. local rank if field:containing_oneof() then rank = 100 -- These go last (actually we skip them). @@ -347,7 +349,7 @@ local function write_c_file(filedef, hfilename, append) end if field:containing_oneof() then - -- Do nothing now + -- Handled below. else if has_hasbit(field) then hasbit_indexes[field] = hasbit_count @@ -358,14 +360,11 @@ local function write_c_file(filedef, hfilename, append) end end - local oneof_last_fields = {} -- Oneof fields. for oneof in msg:oneofs() do local fullname = to_cident(oneof:containing_type():full_name() .. "." .. oneof:name()) append(' union {\n') - oneof_last_fields[oneof] = "" for field in oneof:fields() do - oneof_last_fields[oneof] = field:name() append(' %s %s;\n', ctype(field), field:name()) end append(' } %s;\n', oneof:name()) @@ -425,7 +424,6 @@ local function write_c_file(filedef, hfilename, append) if field:containing_oneof() then oneof_index = oneof_indexes[field:containing_oneof()] end - -- TODO(haberman): oneofs. append(' {%s, offsetof(%s, %s), %s, %s, %s, %s, %s},\n', field:number(), msgname, diff --git a/upb/decode.c b/upb/decode.c index 3a44021..b09da42 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -54,18 +54,18 @@ static bool upb_decode_message(upb_decstate *d, const char *limit, static bool upb_decode_varint(const char **ptr, const char *limit, uint64_t *val) { - uint8_t byte = 0x80; + uint8_t byte; int bitpos = 0; const char *p = *ptr; *val = 0; - while (byte & 0x80) { + do { CHK(bitpos < 70 && p < limit); byte = *p; *val |= (uint64_t)(byte & 0x7F) << bitpos; p++; bitpos += 7; - } + } while (byte & 0x80); *ptr = p; return true; @@ -385,7 +385,7 @@ static bool upb_decode_fixedpacked(upb_array *arr, upb_stringview data, int elements = data.size / elem_size; void *field_mem; - CHK((data.size % elem_size) == 0); + CHK(elements * elem_size == data.size); field_mem = upb_array_add(arr, elements); CHK(field_mem); memcpy(field_mem, data.data, data.size); @@ -451,6 +451,7 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, return upb_append_unknown(d, frame, field_start); } #undef VARINT_CASE + UPB_UNREACHABLE(); } static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, diff --git a/upb/encode.c b/upb/encode.c index 4aafb9c..e7585eb 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -32,7 +32,7 @@ static const uint8_t upb_desctype_to_fieldtype[] = { static size_t upb_encode_varint(uint64_t val, char *buf) { size_t i; - if (val == 0) { buf[0] = 0; return 1; } + if (val < 128) { buf[0] = val; return 1; } i = 0; while (val) { uint8_t byte = val & 0x7fU; @@ -373,7 +373,11 @@ char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *m, e.limit = NULL; e.ptr = NULL; - CHK(upb_encode_message(&e, msg, m, size)); + if (!upb_encode_message(&e, msg, m, size)) { + *size = 0; + return NULL; + } + *size = e.limit - e.ptr; if (*size == 0) { -- cgit v1.2.3 From 6b8767422154008eed98d0df42e36758d38877a4 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 19 Jul 2017 00:33:30 +0200 Subject: Address review comments and fix compile warnings. --- tests/conformance_upb.c | 2 +- upb/decode.c | 2 +- upb/encode.c | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/conformance_upb.c b/tests/conformance_upb.c index 2ef8c6d..70ea300 100644 --- a/tests/conformance_upb.c +++ b/tests/conformance_upb.c @@ -33,7 +33,7 @@ bool CheckedRead(int fd, void *buf, size_t len) { } void CheckedWrite(int fd, const void *buf, size_t len) { - if (write(fd, buf, len) != len) { + if ((size_t)write(fd, buf, len) != len) { perror("writing to test runner"); exit(1); } diff --git a/upb/decode.c b/upb/decode.c index b09da42..cba9f61 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -385,7 +385,7 @@ static bool upb_decode_fixedpacked(upb_array *arr, upb_stringview data, int elements = data.size / elem_size; void *field_mem; - CHK(elements * elem_size == data.size); + CHK((size_t)(elements * elem_size) == data.size); field_mem = upb_array_add(arr, elements); CHK(field_mem); memcpy(field_mem, data.data, data.size); diff --git a/upb/encode.c b/upb/encode.c index e7585eb..cb72bf9 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -256,9 +256,11 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, const upb_msglayout_msginit_v1 *m, const upb_msglayout_fieldinit_v1 *f, bool is_proto3) { + bool skip_zero_value = is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF; + #define CASE(ctype, type, wire_type, encodeval) do { \ ctype val = *(ctype*)field_mem; \ - if (is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF && val == 0) { \ + if (skip_zero_value && val == 0) { \ return true; \ } \ return upb_put_ ## type(e, encodeval) && \ @@ -292,7 +294,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { upb_stringview view = *(upb_stringview*)field_mem; - if (is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF && view.size == 0) { + if (skip_zero_value && view.size == 0) { return true; } return upb_put_bytes(e, view.data, view.size) && @@ -303,7 +305,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, size_t size; void *submsg = *(void**)field_mem; const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; - if (is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF && submsg == NULL) { + if (skip_zero_value && submsg == NULL) { return true; } return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) && @@ -314,7 +316,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, size_t size; void *submsg = *(void**)field_mem; const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; - if (is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF && submsg == NULL) { + if (skip_zero_value && submsg == NULL) { return true; } return upb_encode_message(e, submsg, subm, &size) && -- cgit v1.2.3 From 98f513fb8fa5e3360baeb59c37636ca71d562490 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 19 Jul 2017 00:48:15 +0200 Subject: Fixed 32-bit build and added generated files. --- tools/make_c_api.lua | 4 +- upb/decode.c | 4 +- upb/descriptor/descriptor.upb.c | 552 ++++++++++++++++++++-------------------- 3 files changed, 282 insertions(+), 278 deletions(-) diff --git a/tools/make_c_api.lua b/tools/make_c_api.lua index 552e861..d81ca6b 100644 --- a/tools/make_c_api.lua +++ b/tools/make_c_api.lua @@ -276,8 +276,8 @@ local function write_c_file(filedef, hfilename, append) emit_file_warning(filedef, append) append('#include \n') - append('#include "upb/decode.h"\n\n') - append('#include "upb/encode.h"\n\n') + append('#include "upb/decode.h"\n') + append('#include "upb/encode.h"\n') append('#include "upb/msg.h"\n') append('#include "upb/upb.h"\n') append('#include "%s"\n\n', hfilename) diff --git a/upb/decode.c b/upb/decode.c index cba9f61..8c3ecb4 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -116,7 +116,9 @@ static bool upb_decode_string(const char **ptr, const char *limit, upb_stringview *val) { uint32_t len; - CHK(upb_decode_varint32(ptr, limit, &len) && limit - *ptr >= len); + CHK(upb_decode_varint32(ptr, limit, &len) && + len < INT32_MAX && + limit - *ptr >= (int32_t)len); *val = upb_stringview_make(*ptr, len); *ptr += len; diff --git a/upb/descriptor/descriptor.upb.c b/upb/descriptor/descriptor.upb.c index c0b537c..f388cfd 100644 --- a/upb/descriptor/descriptor.upb.c +++ b/upb/descriptor/descriptor.upb.c @@ -7,6 +7,8 @@ * regenerated. */ #include +#include "upb/decode.h" +#include "upb/encode.h" #include "upb/msg.h" #include "upb/upb.h" #include "upb/descriptor/descriptor.upb.h" @@ -21,13 +23,13 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_FileDescriptorSet_s }; static const upb_msglayout_fieldinit_v1 google_protobuf_FileDescriptorSet__fields[1] = { - {1, offsetof(google_protobuf_FileDescriptorSet, file), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {1, offsetof(google_protobuf_FileDescriptorSet, file), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_FileDescriptorSet_msginit = { &google_protobuf_FileDescriptorSet_submsgs[0], &google_protobuf_FileDescriptorSet__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_FileDescriptorSet), 1, 0, false, true }; @@ -38,15 +40,15 @@ google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_env return msg; } google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_FileDescriptorSet *msg = google_protobuf_FileDescriptorSet_new(env); + if (upb_decode(buf, msg, &google_protobuf_FileDescriptorSet_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_FileDescriptorSet_serialize(google_protobuf_FileDescriptorSet *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, env, size); } upb_array* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg) { return msg->file; @@ -79,24 +81,24 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_FileDescriptorProto }; static const upb_msglayout_fieldinit_v1 google_protobuf_FileDescriptorProto__fields[12] = { - {1, offsetof(google_protobuf_FileDescriptorProto, name), 0, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {2, offsetof(google_protobuf_FileDescriptorProto, package), 1, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {3, offsetof(google_protobuf_FileDescriptorProto, dependency), -1, UPB_NOT_IN_ONEOF, -1, 9, 3}, - {4, offsetof(google_protobuf_FileDescriptorProto, message_type), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, - {5, offsetof(google_protobuf_FileDescriptorProto, enum_type), -1, UPB_NOT_IN_ONEOF, 1, 11, 3}, - {6, offsetof(google_protobuf_FileDescriptorProto, service), -1, UPB_NOT_IN_ONEOF, 4, 11, 3}, - {7, offsetof(google_protobuf_FileDescriptorProto, extension), -1, UPB_NOT_IN_ONEOF, 2, 11, 3}, + {1, offsetof(google_protobuf_FileDescriptorProto, name), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {2, offsetof(google_protobuf_FileDescriptorProto, package), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {3, offsetof(google_protobuf_FileDescriptorProto, dependency), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 3}, + {4, offsetof(google_protobuf_FileDescriptorProto, message_type), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {5, offsetof(google_protobuf_FileDescriptorProto, enum_type), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 1, 11, 3}, + {6, offsetof(google_protobuf_FileDescriptorProto, service), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 4, 11, 3}, + {7, offsetof(google_protobuf_FileDescriptorProto, extension), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 2, 11, 3}, {8, offsetof(google_protobuf_FileDescriptorProto, options), 3, UPB_NOT_IN_ONEOF, 3, 11, 1}, {9, offsetof(google_protobuf_FileDescriptorProto, source_code_info), 4, UPB_NOT_IN_ONEOF, 5, 11, 1}, - {10, offsetof(google_protobuf_FileDescriptorProto, public_dependency), -1, UPB_NOT_IN_ONEOF, -1, 5, 3}, - {11, offsetof(google_protobuf_FileDescriptorProto, weak_dependency), -1, UPB_NOT_IN_ONEOF, -1, 5, 3}, - {12, offsetof(google_protobuf_FileDescriptorProto, syntax), 2, UPB_NOT_IN_ONEOF, -1, 9, 1}, + {10, offsetof(google_protobuf_FileDescriptorProto, public_dependency), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 3}, + {11, offsetof(google_protobuf_FileDescriptorProto, weak_dependency), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 3}, + {12, offsetof(google_protobuf_FileDescriptorProto, syntax), 2, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_FileDescriptorProto_msginit = { &google_protobuf_FileDescriptorProto_submsgs[0], &google_protobuf_FileDescriptorProto__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_FileDescriptorProto), 12, 0, false, true }; @@ -107,15 +109,15 @@ google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb return msg; } google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_FileDescriptorProto *msg = google_protobuf_FileDescriptorProto_new(env); + if (upb_decode(buf, msg, &google_protobuf_FileDescriptorProto_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_FileDescriptorProto_serialize(google_protobuf_FileDescriptorProto *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, env, size); } upb_stringview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return msg->name; @@ -213,22 +215,22 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_DescriptorProto_sub }; static const upb_msglayout_fieldinit_v1 google_protobuf_DescriptorProto__fields[10] = { - {1, offsetof(google_protobuf_DescriptorProto, name), 0, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {2, offsetof(google_protobuf_DescriptorProto, field), -1, UPB_NOT_IN_ONEOF, 4, 11, 3}, - {3, offsetof(google_protobuf_DescriptorProto, nested_type), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, - {4, offsetof(google_protobuf_DescriptorProto, enum_type), -1, UPB_NOT_IN_ONEOF, 3, 11, 3}, - {5, offsetof(google_protobuf_DescriptorProto, extension_range), -1, UPB_NOT_IN_ONEOF, 1, 11, 3}, - {6, offsetof(google_protobuf_DescriptorProto, extension), -1, UPB_NOT_IN_ONEOF, 4, 11, 3}, + {1, offsetof(google_protobuf_DescriptorProto, name), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {2, offsetof(google_protobuf_DescriptorProto, field), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 4, 11, 3}, + {3, offsetof(google_protobuf_DescriptorProto, nested_type), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {4, offsetof(google_protobuf_DescriptorProto, enum_type), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 3, 11, 3}, + {5, offsetof(google_protobuf_DescriptorProto, extension_range), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 1, 11, 3}, + {6, offsetof(google_protobuf_DescriptorProto, extension), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 4, 11, 3}, {7, offsetof(google_protobuf_DescriptorProto, options), 1, UPB_NOT_IN_ONEOF, 5, 11, 1}, - {8, offsetof(google_protobuf_DescriptorProto, oneof_decl), -1, UPB_NOT_IN_ONEOF, 6, 11, 3}, - {9, offsetof(google_protobuf_DescriptorProto, reserved_range), -1, UPB_NOT_IN_ONEOF, 2, 11, 3}, - {10, offsetof(google_protobuf_DescriptorProto, reserved_name), -1, UPB_NOT_IN_ONEOF, -1, 9, 3}, + {8, offsetof(google_protobuf_DescriptorProto, oneof_decl), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 6, 11, 3}, + {9, offsetof(google_protobuf_DescriptorProto, reserved_range), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 2, 11, 3}, + {10, offsetof(google_protobuf_DescriptorProto, reserved_name), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_DescriptorProto_msginit = { &google_protobuf_DescriptorProto_submsgs[0], &google_protobuf_DescriptorProto__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_DescriptorProto), 10, 0, false, true }; @@ -239,15 +241,15 @@ google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_env *en return msg; } google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_DescriptorProto *msg = google_protobuf_DescriptorProto_new(env); + if (upb_decode(buf, msg, &google_protobuf_DescriptorProto_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_DescriptorProto_serialize(google_protobuf_DescriptorProto *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, env, size); } upb_stringview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return msg->name; @@ -315,14 +317,14 @@ struct google_protobuf_DescriptorProto_ExtensionRange { }; static const upb_msglayout_fieldinit_v1 google_protobuf_DescriptorProto_ExtensionRange__fields[2] = { - {1, offsetof(google_protobuf_DescriptorProto_ExtensionRange, start), 0, UPB_NOT_IN_ONEOF, -1, 5, 1}, - {2, offsetof(google_protobuf_DescriptorProto_ExtensionRange, end), 1, UPB_NOT_IN_ONEOF, -1, 5, 1}, + {1, offsetof(google_protobuf_DescriptorProto_ExtensionRange, start), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 1}, + {2, offsetof(google_protobuf_DescriptorProto_ExtensionRange, end), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_DescriptorProto_ExtensionRange_msginit = { NULL, &google_protobuf_DescriptorProto_ExtensionRange__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_DescriptorProto_ExtensionRange), 2, 0, false, true }; @@ -333,15 +335,15 @@ google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ return msg; } google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_DescriptorProto_ExtensionRange *msg = google_protobuf_DescriptorProto_ExtensionRange_new(env); + if (upb_decode(buf, msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_DescriptorProto_ExtensionRange_serialize(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, env, size); } int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return msg->start; @@ -361,14 +363,14 @@ struct google_protobuf_DescriptorProto_ReservedRange { }; static const upb_msglayout_fieldinit_v1 google_protobuf_DescriptorProto_ReservedRange__fields[2] = { - {1, offsetof(google_protobuf_DescriptorProto_ReservedRange, start), 0, UPB_NOT_IN_ONEOF, -1, 5, 1}, - {2, offsetof(google_protobuf_DescriptorProto_ReservedRange, end), 1, UPB_NOT_IN_ONEOF, -1, 5, 1}, + {1, offsetof(google_protobuf_DescriptorProto_ReservedRange, start), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 1}, + {2, offsetof(google_protobuf_DescriptorProto_ReservedRange, end), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_DescriptorProto_ReservedRange_msginit = { NULL, &google_protobuf_DescriptorProto_ReservedRange__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_DescriptorProto_ReservedRange), 2, 0, false, true }; @@ -379,15 +381,15 @@ google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_R return msg; } google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_DescriptorProto_ReservedRange *msg = google_protobuf_DescriptorProto_ReservedRange_new(env); + if (upb_decode(buf, msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_DescriptorProto_ReservedRange_serialize(google_protobuf_DescriptorProto_ReservedRange *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, env, size); } int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return msg->start; @@ -419,22 +421,22 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_FieldDescriptorProt }; static const upb_msglayout_fieldinit_v1 google_protobuf_FieldDescriptorProto__fields[10] = { - {1, offsetof(google_protobuf_FieldDescriptorProto, name), 4, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {2, offsetof(google_protobuf_FieldDescriptorProto, extendee), 5, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {3, offsetof(google_protobuf_FieldDescriptorProto, number), 2, UPB_NOT_IN_ONEOF, -1, 5, 1}, - {4, offsetof(google_protobuf_FieldDescriptorProto, label), 0, UPB_NOT_IN_ONEOF, -1, 14, 1}, - {5, offsetof(google_protobuf_FieldDescriptorProto, type), 1, UPB_NOT_IN_ONEOF, -1, 14, 1}, - {6, offsetof(google_protobuf_FieldDescriptorProto, type_name), 6, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {7, offsetof(google_protobuf_FieldDescriptorProto, default_value), 7, UPB_NOT_IN_ONEOF, -1, 9, 1}, + {1, offsetof(google_protobuf_FieldDescriptorProto, name), 4, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {2, offsetof(google_protobuf_FieldDescriptorProto, extendee), 5, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {3, offsetof(google_protobuf_FieldDescriptorProto, number), 2, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 1}, + {4, offsetof(google_protobuf_FieldDescriptorProto, label), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 14, 1}, + {5, offsetof(google_protobuf_FieldDescriptorProto, type), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 14, 1}, + {6, offsetof(google_protobuf_FieldDescriptorProto, type_name), 6, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {7, offsetof(google_protobuf_FieldDescriptorProto, default_value), 7, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, {8, offsetof(google_protobuf_FieldDescriptorProto, options), 9, UPB_NOT_IN_ONEOF, 0, 11, 1}, - {9, offsetof(google_protobuf_FieldDescriptorProto, oneof_index), 3, UPB_NOT_IN_ONEOF, -1, 5, 1}, - {10, offsetof(google_protobuf_FieldDescriptorProto, json_name), 8, UPB_NOT_IN_ONEOF, -1, 9, 1}, + {9, offsetof(google_protobuf_FieldDescriptorProto, oneof_index), 3, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 1}, + {10, offsetof(google_protobuf_FieldDescriptorProto, json_name), 8, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_FieldDescriptorProto_msginit = { &google_protobuf_FieldDescriptorProto_submsgs[0], &google_protobuf_FieldDescriptorProto__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_FieldDescriptorProto), 10, 0, false, true }; @@ -445,15 +447,15 @@ google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(u return msg; } google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_FieldDescriptorProto *msg = google_protobuf_FieldDescriptorProto_new(env); + if (upb_decode(buf, msg, &google_protobuf_FieldDescriptorProto_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_FieldDescriptorProto_serialize(google_protobuf_FieldDescriptorProto *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, env, size); } upb_stringview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return msg->name; @@ -520,13 +522,13 @@ struct google_protobuf_OneofDescriptorProto { }; static const upb_msglayout_fieldinit_v1 google_protobuf_OneofDescriptorProto__fields[1] = { - {1, offsetof(google_protobuf_OneofDescriptorProto, name), 0, UPB_NOT_IN_ONEOF, -1, 9, 1}, + {1, offsetof(google_protobuf_OneofDescriptorProto, name), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_OneofDescriptorProto_msginit = { NULL, &google_protobuf_OneofDescriptorProto__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_OneofDescriptorProto), 1, 0, false, true }; @@ -537,15 +539,15 @@ google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(u return msg; } google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_OneofDescriptorProto *msg = google_protobuf_OneofDescriptorProto_new(env); + if (upb_decode(buf, msg, &google_protobuf_OneofDescriptorProto_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_OneofDescriptorProto_serialize(google_protobuf_OneofDescriptorProto *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, env, size); } upb_stringview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return msg->name; @@ -565,15 +567,15 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_EnumDescriptorProto }; static const upb_msglayout_fieldinit_v1 google_protobuf_EnumDescriptorProto__fields[3] = { - {1, offsetof(google_protobuf_EnumDescriptorProto, name), 0, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {2, offsetof(google_protobuf_EnumDescriptorProto, value), -1, UPB_NOT_IN_ONEOF, 1, 11, 3}, + {1, offsetof(google_protobuf_EnumDescriptorProto, name), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {2, offsetof(google_protobuf_EnumDescriptorProto, value), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 1, 11, 3}, {3, offsetof(google_protobuf_EnumDescriptorProto, options), 1, UPB_NOT_IN_ONEOF, 0, 11, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_EnumDescriptorProto_msginit = { &google_protobuf_EnumDescriptorProto_submsgs[0], &google_protobuf_EnumDescriptorProto__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_EnumDescriptorProto), 3, 0, false, true }; @@ -584,15 +586,15 @@ google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb return msg; } google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_EnumDescriptorProto *msg = google_protobuf_EnumDescriptorProto_new(env); + if (upb_decode(buf, msg, &google_protobuf_EnumDescriptorProto_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_EnumDescriptorProto_serialize(google_protobuf_EnumDescriptorProto *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, env, size); } upb_stringview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return msg->name; @@ -623,15 +625,15 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_EnumValueDescriptor }; static const upb_msglayout_fieldinit_v1 google_protobuf_EnumValueDescriptorProto__fields[3] = { - {1, offsetof(google_protobuf_EnumValueDescriptorProto, name), 1, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {2, offsetof(google_protobuf_EnumValueDescriptorProto, number), 0, UPB_NOT_IN_ONEOF, -1, 5, 1}, + {1, offsetof(google_protobuf_EnumValueDescriptorProto, name), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {2, offsetof(google_protobuf_EnumValueDescriptorProto, number), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 1}, {3, offsetof(google_protobuf_EnumValueDescriptorProto, options), 2, UPB_NOT_IN_ONEOF, 0, 11, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_EnumValueDescriptorProto_msginit = { &google_protobuf_EnumValueDescriptorProto_submsgs[0], &google_protobuf_EnumValueDescriptorProto__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_EnumValueDescriptorProto), 3, 0, false, true }; @@ -642,15 +644,15 @@ google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorPro return msg; } google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_EnumValueDescriptorProto *msg = google_protobuf_EnumValueDescriptorProto_new(env); + if (upb_decode(buf, msg, &google_protobuf_EnumValueDescriptorProto_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_EnumValueDescriptorProto_serialize(google_protobuf_EnumValueDescriptorProto *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, env, size); } upb_stringview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return msg->name; @@ -682,15 +684,15 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_ServiceDescriptorPr }; static const upb_msglayout_fieldinit_v1 google_protobuf_ServiceDescriptorProto__fields[3] = { - {1, offsetof(google_protobuf_ServiceDescriptorProto, name), 0, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {2, offsetof(google_protobuf_ServiceDescriptorProto, method), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {1, offsetof(google_protobuf_ServiceDescriptorProto, name), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {2, offsetof(google_protobuf_ServiceDescriptorProto, method), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, {3, offsetof(google_protobuf_ServiceDescriptorProto, options), 1, UPB_NOT_IN_ONEOF, 1, 11, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_ServiceDescriptorProto_msginit = { &google_protobuf_ServiceDescriptorProto_submsgs[0], &google_protobuf_ServiceDescriptorProto__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_ServiceDescriptorProto), 3, 0, false, true }; @@ -701,15 +703,15 @@ google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_n return msg; } google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_ServiceDescriptorProto *msg = google_protobuf_ServiceDescriptorProto_new(env); + if (upb_decode(buf, msg, &google_protobuf_ServiceDescriptorProto_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_ServiceDescriptorProto_serialize(google_protobuf_ServiceDescriptorProto *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, env, size); } upb_stringview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return msg->name; @@ -743,18 +745,18 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_MethodDescriptorPro }; static const upb_msglayout_fieldinit_v1 google_protobuf_MethodDescriptorProto__fields[6] = { - {1, offsetof(google_protobuf_MethodDescriptorProto, name), 2, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {2, offsetof(google_protobuf_MethodDescriptorProto, input_type), 3, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {3, offsetof(google_protobuf_MethodDescriptorProto, output_type), 4, UPB_NOT_IN_ONEOF, -1, 9, 1}, + {1, offsetof(google_protobuf_MethodDescriptorProto, name), 2, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {2, offsetof(google_protobuf_MethodDescriptorProto, input_type), 3, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {3, offsetof(google_protobuf_MethodDescriptorProto, output_type), 4, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, {4, offsetof(google_protobuf_MethodDescriptorProto, options), 5, UPB_NOT_IN_ONEOF, 0, 11, 1}, - {5, offsetof(google_protobuf_MethodDescriptorProto, client_streaming), 0, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {6, offsetof(google_protobuf_MethodDescriptorProto, server_streaming), 1, UPB_NOT_IN_ONEOF, -1, 8, 1}, + {5, offsetof(google_protobuf_MethodDescriptorProto, client_streaming), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {6, offsetof(google_protobuf_MethodDescriptorProto, server_streaming), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_MethodDescriptorProto_msginit = { &google_protobuf_MethodDescriptorProto_submsgs[0], &google_protobuf_MethodDescriptorProto__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_MethodDescriptorProto), 6, 0, false, true }; @@ -765,15 +767,15 @@ google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new return msg; } google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_MethodDescriptorProto *msg = google_protobuf_MethodDescriptorProto_new(env); + if (upb_decode(buf, msg, &google_protobuf_MethodDescriptorProto_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_MethodDescriptorProto_serialize(google_protobuf_MethodDescriptorProto *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, env, size); } upb_stringview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return msg->name; @@ -837,30 +839,30 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_FileOptions_submsgs }; static const upb_msglayout_fieldinit_v1 google_protobuf_FileOptions__fields[18] = { - {1, offsetof(google_protobuf_FileOptions, java_package), 10, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {8, offsetof(google_protobuf_FileOptions, java_outer_classname), 11, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {9, offsetof(google_protobuf_FileOptions, optimize_for), 0, UPB_NOT_IN_ONEOF, -1, 14, 1}, - {10, offsetof(google_protobuf_FileOptions, java_multiple_files), 1, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {11, offsetof(google_protobuf_FileOptions, go_package), 12, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {16, offsetof(google_protobuf_FileOptions, cc_generic_services), 2, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {17, offsetof(google_protobuf_FileOptions, java_generic_services), 3, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {18, offsetof(google_protobuf_FileOptions, py_generic_services), 4, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {20, offsetof(google_protobuf_FileOptions, java_generate_equals_and_hash), 5, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {23, offsetof(google_protobuf_FileOptions, deprecated), 6, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {27, offsetof(google_protobuf_FileOptions, java_string_check_utf8), 7, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {31, offsetof(google_protobuf_FileOptions, cc_enable_arenas), 8, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {36, offsetof(google_protobuf_FileOptions, objc_class_prefix), 13, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {37, offsetof(google_protobuf_FileOptions, csharp_namespace), 14, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {38, offsetof(google_protobuf_FileOptions, javanano_use_deprecated_package), 9, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {40, offsetof(google_protobuf_FileOptions, php_class_prefix), 15, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {41, offsetof(google_protobuf_FileOptions, php_namespace), 16, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {999, offsetof(google_protobuf_FileOptions, uninterpreted_option), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {1, offsetof(google_protobuf_FileOptions, java_package), 10, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {8, offsetof(google_protobuf_FileOptions, java_outer_classname), 11, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {9, offsetof(google_protobuf_FileOptions, optimize_for), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 14, 1}, + {10, offsetof(google_protobuf_FileOptions, java_multiple_files), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {11, offsetof(google_protobuf_FileOptions, go_package), 12, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {16, offsetof(google_protobuf_FileOptions, cc_generic_services), 2, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {17, offsetof(google_protobuf_FileOptions, java_generic_services), 3, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {18, offsetof(google_protobuf_FileOptions, py_generic_services), 4, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {20, offsetof(google_protobuf_FileOptions, java_generate_equals_and_hash), 5, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {23, offsetof(google_protobuf_FileOptions, deprecated), 6, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {27, offsetof(google_protobuf_FileOptions, java_string_check_utf8), 7, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {31, offsetof(google_protobuf_FileOptions, cc_enable_arenas), 8, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {36, offsetof(google_protobuf_FileOptions, objc_class_prefix), 13, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {37, offsetof(google_protobuf_FileOptions, csharp_namespace), 14, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {38, offsetof(google_protobuf_FileOptions, javanano_use_deprecated_package), 9, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {40, offsetof(google_protobuf_FileOptions, php_class_prefix), 15, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {41, offsetof(google_protobuf_FileOptions, php_namespace), 16, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {999, offsetof(google_protobuf_FileOptions, uninterpreted_option), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_FileOptions_msginit = { &google_protobuf_FileOptions_submsgs[0], &google_protobuf_FileOptions__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_FileOptions), 18, 0, false, true }; @@ -871,15 +873,15 @@ google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_env *env) { return msg; } google_protobuf_FileOptions *google_protobuf_FileOptions_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_FileOptions *msg = google_protobuf_FileOptions_new(env); + if (upb_decode(buf, msg, &google_protobuf_FileOptions_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_FileOptions_serialize(google_protobuf_FileOptions *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_FileOptions_msginit, env, size); } upb_stringview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return msg->java_package; @@ -1002,17 +1004,17 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_MessageOptions_subm }; static const upb_msglayout_fieldinit_v1 google_protobuf_MessageOptions__fields[5] = { - {1, offsetof(google_protobuf_MessageOptions, message_set_wire_format), 0, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {2, offsetof(google_protobuf_MessageOptions, no_standard_descriptor_accessor), 1, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {3, offsetof(google_protobuf_MessageOptions, deprecated), 2, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {7, offsetof(google_protobuf_MessageOptions, map_entry), 3, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {999, offsetof(google_protobuf_MessageOptions, uninterpreted_option), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {1, offsetof(google_protobuf_MessageOptions, message_set_wire_format), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {2, offsetof(google_protobuf_MessageOptions, no_standard_descriptor_accessor), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {3, offsetof(google_protobuf_MessageOptions, deprecated), 2, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {7, offsetof(google_protobuf_MessageOptions, map_entry), 3, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {999, offsetof(google_protobuf_MessageOptions, uninterpreted_option), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_MessageOptions_msginit = { &google_protobuf_MessageOptions_submsgs[0], &google_protobuf_MessageOptions__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_MessageOptions), 5, 0, false, true }; @@ -1023,15 +1025,15 @@ google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_env *env) return msg; } google_protobuf_MessageOptions *google_protobuf_MessageOptions_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_MessageOptions *msg = google_protobuf_MessageOptions_new(env); + if (upb_decode(buf, msg, &google_protobuf_MessageOptions_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_MessageOptions_serialize(google_protobuf_MessageOptions *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_MessageOptions_msginit, env, size); } bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return msg->message_set_wire_format; @@ -1078,19 +1080,19 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_FieldOptions_submsg }; static const upb_msglayout_fieldinit_v1 google_protobuf_FieldOptions__fields[7] = { - {1, offsetof(google_protobuf_FieldOptions, ctype), 0, UPB_NOT_IN_ONEOF, -1, 14, 1}, - {2, offsetof(google_protobuf_FieldOptions, packed), 2, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {3, offsetof(google_protobuf_FieldOptions, deprecated), 3, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {5, offsetof(google_protobuf_FieldOptions, lazy), 4, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {6, offsetof(google_protobuf_FieldOptions, jstype), 1, UPB_NOT_IN_ONEOF, -1, 14, 1}, - {10, offsetof(google_protobuf_FieldOptions, weak), 5, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {999, offsetof(google_protobuf_FieldOptions, uninterpreted_option), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {1, offsetof(google_protobuf_FieldOptions, ctype), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 14, 1}, + {2, offsetof(google_protobuf_FieldOptions, packed), 2, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {3, offsetof(google_protobuf_FieldOptions, deprecated), 3, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {5, offsetof(google_protobuf_FieldOptions, lazy), 4, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {6, offsetof(google_protobuf_FieldOptions, jstype), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 14, 1}, + {10, offsetof(google_protobuf_FieldOptions, weak), 5, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {999, offsetof(google_protobuf_FieldOptions, uninterpreted_option), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_FieldOptions_msginit = { &google_protobuf_FieldOptions_submsgs[0], &google_protobuf_FieldOptions__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_FieldOptions), 7, 0, false, true }; @@ -1101,15 +1103,15 @@ google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_env *env) { return msg; } google_protobuf_FieldOptions *google_protobuf_FieldOptions_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_FieldOptions *msg = google_protobuf_FieldOptions_new(env); + if (upb_decode(buf, msg, &google_protobuf_FieldOptions_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_FieldOptions_serialize(google_protobuf_FieldOptions *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_FieldOptions_msginit, env, size); } google_protobuf_FieldOptions_CType google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return msg->ctype; @@ -1164,15 +1166,15 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_EnumOptions_submsgs }; static const upb_msglayout_fieldinit_v1 google_protobuf_EnumOptions__fields[3] = { - {2, offsetof(google_protobuf_EnumOptions, allow_alias), 0, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {3, offsetof(google_protobuf_EnumOptions, deprecated), 1, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {999, offsetof(google_protobuf_EnumOptions, uninterpreted_option), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {2, offsetof(google_protobuf_EnumOptions, allow_alias), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {3, offsetof(google_protobuf_EnumOptions, deprecated), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {999, offsetof(google_protobuf_EnumOptions, uninterpreted_option), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_EnumOptions_msginit = { &google_protobuf_EnumOptions_submsgs[0], &google_protobuf_EnumOptions__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_EnumOptions), 3, 0, false, true }; @@ -1183,15 +1185,15 @@ google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_env *env) { return msg; } google_protobuf_EnumOptions *google_protobuf_EnumOptions_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_EnumOptions *msg = google_protobuf_EnumOptions_new(env); + if (upb_decode(buf, msg, &google_protobuf_EnumOptions_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_EnumOptions_serialize(google_protobuf_EnumOptions *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_EnumOptions_msginit, env, size); } bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return msg->allow_alias; @@ -1221,14 +1223,14 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_EnumValueOptions_su }; static const upb_msglayout_fieldinit_v1 google_protobuf_EnumValueOptions__fields[2] = { - {1, offsetof(google_protobuf_EnumValueOptions, deprecated), 0, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {999, offsetof(google_protobuf_EnumValueOptions, uninterpreted_option), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {1, offsetof(google_protobuf_EnumValueOptions, deprecated), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {999, offsetof(google_protobuf_EnumValueOptions, uninterpreted_option), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_EnumValueOptions_msginit = { &google_protobuf_EnumValueOptions_submsgs[0], &google_protobuf_EnumValueOptions__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_EnumValueOptions), 2, 0, false, true }; @@ -1239,15 +1241,15 @@ google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_env * return msg; } google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_EnumValueOptions *msg = google_protobuf_EnumValueOptions_new(env); + if (upb_decode(buf, msg, &google_protobuf_EnumValueOptions_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_EnumValueOptions_serialize(google_protobuf_EnumValueOptions *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, env, size); } bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return msg->deprecated; @@ -1271,14 +1273,14 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_ServiceOptions_subm }; static const upb_msglayout_fieldinit_v1 google_protobuf_ServiceOptions__fields[2] = { - {33, offsetof(google_protobuf_ServiceOptions, deprecated), 0, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {999, offsetof(google_protobuf_ServiceOptions, uninterpreted_option), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {33, offsetof(google_protobuf_ServiceOptions, deprecated), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {999, offsetof(google_protobuf_ServiceOptions, uninterpreted_option), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_ServiceOptions_msginit = { &google_protobuf_ServiceOptions_submsgs[0], &google_protobuf_ServiceOptions__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_ServiceOptions), 2, 0, false, true }; @@ -1289,15 +1291,15 @@ google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_env *env) return msg; } google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_ServiceOptions *msg = google_protobuf_ServiceOptions_new(env); + if (upb_decode(buf, msg, &google_protobuf_ServiceOptions_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_ServiceOptions_serialize(google_protobuf_ServiceOptions *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, env, size); } bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return msg->deprecated; @@ -1321,14 +1323,14 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_MethodOptions_subms }; static const upb_msglayout_fieldinit_v1 google_protobuf_MethodOptions__fields[2] = { - {33, offsetof(google_protobuf_MethodOptions, deprecated), 0, UPB_NOT_IN_ONEOF, -1, 8, 1}, - {999, offsetof(google_protobuf_MethodOptions, uninterpreted_option), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {33, offsetof(google_protobuf_MethodOptions, deprecated), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 1}, + {999, offsetof(google_protobuf_MethodOptions, uninterpreted_option), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_MethodOptions_msginit = { &google_protobuf_MethodOptions_submsgs[0], &google_protobuf_MethodOptions__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_MethodOptions), 2, 0, false, true }; @@ -1339,15 +1341,15 @@ google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_env *env) { return msg; } google_protobuf_MethodOptions *google_protobuf_MethodOptions_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_MethodOptions *msg = google_protobuf_MethodOptions_new(env); + if (upb_decode(buf, msg, &google_protobuf_MethodOptions_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_MethodOptions_serialize(google_protobuf_MethodOptions *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_MethodOptions_msginit, env, size); } bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return msg->deprecated; @@ -1376,19 +1378,19 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_UninterpretedOption }; static const upb_msglayout_fieldinit_v1 google_protobuf_UninterpretedOption__fields[7] = { - {2, offsetof(google_protobuf_UninterpretedOption, name), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, - {3, offsetof(google_protobuf_UninterpretedOption, identifier_value), 3, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {4, offsetof(google_protobuf_UninterpretedOption, positive_int_value), 0, UPB_NOT_IN_ONEOF, -1, 4, 1}, - {5, offsetof(google_protobuf_UninterpretedOption, negative_int_value), 1, UPB_NOT_IN_ONEOF, -1, 3, 1}, - {6, offsetof(google_protobuf_UninterpretedOption, double_value), 2, UPB_NOT_IN_ONEOF, -1, 1, 1}, - {7, offsetof(google_protobuf_UninterpretedOption, string_value), 4, UPB_NOT_IN_ONEOF, -1, 12, 1}, - {8, offsetof(google_protobuf_UninterpretedOption, aggregate_value), 5, UPB_NOT_IN_ONEOF, -1, 9, 1}, + {2, offsetof(google_protobuf_UninterpretedOption, name), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {3, offsetof(google_protobuf_UninterpretedOption, identifier_value), 3, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {4, offsetof(google_protobuf_UninterpretedOption, positive_int_value), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 4, 1}, + {5, offsetof(google_protobuf_UninterpretedOption, negative_int_value), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 3, 1}, + {6, offsetof(google_protobuf_UninterpretedOption, double_value), 2, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 1, 1}, + {7, offsetof(google_protobuf_UninterpretedOption, string_value), 4, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 12, 1}, + {8, offsetof(google_protobuf_UninterpretedOption, aggregate_value), 5, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, }; const upb_msglayout_msginit_v1 google_protobuf_UninterpretedOption_msginit = { &google_protobuf_UninterpretedOption_submsgs[0], &google_protobuf_UninterpretedOption__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_UninterpretedOption), 7, 0, false, true }; @@ -1399,15 +1401,15 @@ google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb return msg; } google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_UninterpretedOption *msg = google_protobuf_UninterpretedOption_new(env); + if (upb_decode(buf, msg, &google_protobuf_UninterpretedOption_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_UninterpretedOption_serialize(google_protobuf_UninterpretedOption *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, env, size); } upb_array* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg) { return msg->name; @@ -1457,14 +1459,14 @@ struct google_protobuf_UninterpretedOption_NamePart { }; static const upb_msglayout_fieldinit_v1 google_protobuf_UninterpretedOption_NamePart__fields[2] = { - {1, offsetof(google_protobuf_UninterpretedOption_NamePart, name_part), 1, UPB_NOT_IN_ONEOF, -1, 9, 2}, - {2, offsetof(google_protobuf_UninterpretedOption_NamePart, is_extension), 0, UPB_NOT_IN_ONEOF, -1, 8, 2}, + {1, offsetof(google_protobuf_UninterpretedOption_NamePart, name_part), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 2}, + {2, offsetof(google_protobuf_UninterpretedOption_NamePart, is_extension), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 8, 2}, }; const upb_msglayout_msginit_v1 google_protobuf_UninterpretedOption_NamePart_msginit = { NULL, &google_protobuf_UninterpretedOption_NamePart__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_UninterpretedOption_NamePart), 2, 0, false, true }; @@ -1475,15 +1477,15 @@ google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOptio return msg; } google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_UninterpretedOption_NamePart *msg = google_protobuf_UninterpretedOption_NamePart_new(env); + if (upb_decode(buf, msg, &google_protobuf_UninterpretedOption_NamePart_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_UninterpretedOption_NamePart_serialize(google_protobuf_UninterpretedOption_NamePart *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, env, size); } upb_stringview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return msg->name_part; @@ -1506,13 +1508,13 @@ static const upb_msglayout_msginit_v1 *const google_protobuf_SourceCodeInfo_subm }; static const upb_msglayout_fieldinit_v1 google_protobuf_SourceCodeInfo__fields[1] = { - {1, offsetof(google_protobuf_SourceCodeInfo, location), -1, UPB_NOT_IN_ONEOF, 0, 11, 3}, + {1, offsetof(google_protobuf_SourceCodeInfo, location), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, 0, 11, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_SourceCodeInfo_msginit = { &google_protobuf_SourceCodeInfo_submsgs[0], &google_protobuf_SourceCodeInfo__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_SourceCodeInfo), 1, 0, false, true }; @@ -1523,15 +1525,15 @@ google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_env *env) return msg; } google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_SourceCodeInfo *msg = google_protobuf_SourceCodeInfo_new(env); + if (upb_decode(buf, msg, &google_protobuf_SourceCodeInfo_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_SourceCodeInfo_serialize(google_protobuf_SourceCodeInfo *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, env, size); } upb_array* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg) { return msg->location; @@ -1548,17 +1550,17 @@ struct google_protobuf_SourceCodeInfo_Location { }; static const upb_msglayout_fieldinit_v1 google_protobuf_SourceCodeInfo_Location__fields[5] = { - {1, offsetof(google_protobuf_SourceCodeInfo_Location, path), -1, UPB_NOT_IN_ONEOF, -1, 5, 3}, - {2, offsetof(google_protobuf_SourceCodeInfo_Location, span), -1, UPB_NOT_IN_ONEOF, -1, 5, 3}, - {3, offsetof(google_protobuf_SourceCodeInfo_Location, leading_comments), 0, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {4, offsetof(google_protobuf_SourceCodeInfo_Location, trailing_comments), 1, UPB_NOT_IN_ONEOF, -1, 9, 1}, - {6, offsetof(google_protobuf_SourceCodeInfo_Location, leading_detached_comments), -1, UPB_NOT_IN_ONEOF, -1, 9, 3}, + {1, offsetof(google_protobuf_SourceCodeInfo_Location, path), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 3}, + {2, offsetof(google_protobuf_SourceCodeInfo_Location, span), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 5, 3}, + {3, offsetof(google_protobuf_SourceCodeInfo_Location, leading_comments), 0, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {4, offsetof(google_protobuf_SourceCodeInfo_Location, trailing_comments), 1, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 1}, + {6, offsetof(google_protobuf_SourceCodeInfo_Location, leading_detached_comments), UPB_NO_HASBIT, UPB_NOT_IN_ONEOF, UPB_NO_SUBMSG, 9, 3}, }; const upb_msglayout_msginit_v1 google_protobuf_SourceCodeInfo_Location_msginit = { NULL, &google_protobuf_SourceCodeInfo_Location__fields[0], - NULL, /* TODO. oneofs */ + NULL, NULL, /* TODO. default_msg */ UPB_ALIGNED_SIZEOF(google_protobuf_SourceCodeInfo_Location), 5, 0, false, true }; @@ -1569,15 +1571,15 @@ google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location return msg; } google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parsenew(upb_stringview buf, upb_env *env) { - UPB_UNUSED(buf); - UPB_UNUSED(env); - return NULL; + google_protobuf_SourceCodeInfo_Location *msg = google_protobuf_SourceCodeInfo_Location_new(env); + if (upb_decode(buf, msg, &google_protobuf_SourceCodeInfo_Location_msginit, env)) { + return msg; + } else { + return NULL; + } } char *google_protobuf_SourceCodeInfo_Location_serialize(google_protobuf_SourceCodeInfo_Location *msg, upb_env *env, size_t *size) { - UPB_UNUSED(msg); - UPB_UNUSED(env); - UPB_UNUSED(size); - return NULL; /* TODO. */ + return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, env, size); } upb_array* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg) { return msg->path; -- cgit v1.2.3 From 058a17f6a6c2487fd674511d5409497a03e83758 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 19 Jul 2017 00:52:37 +0200 Subject: Fix amalgamated build. --- upb/decode.c | 2 ++ upb/encode.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/upb/decode.c b/upb/decode.c index 8c3ecb4..3f0b6d1 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -578,3 +578,5 @@ bool upb_decode(upb_stringview buf, void *msg, return upb_decode_message(&state, buf.data + buf.size, 0, msg, l); } + +#undef CHK diff --git a/upb/encode.c b/upb/encode.c index cb72bf9..d41b0ed 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -390,3 +390,5 @@ char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *m, return e.ptr; } } + +#undef CHK -- cgit v1.2.3 From 72c333eb037da6fe63358efe9c6dc29547b0ab49 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 19 Jul 2017 01:05:25 +0200 Subject: Fixed amalgamated build. --- upb/decode.c | 12 ++++++------ upb/encode.c | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/upb/decode.c b/upb/decode.c index 3f0b6d1..3c76e0f 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -104,11 +104,11 @@ static bool upb_decode_tag(const char **ptr, const char *limit, return true; } -static int32_t upb_zzdec_32(uint32_t n) { +static int32_t upb_zzdecode_32(uint32_t n) { return (n >> 1) ^ -(int32_t)(n & 1); } -static int64_t upb_zzdec_64(uint64_t n) { +static int64_t upb_zzdecode_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); } @@ -317,12 +317,12 @@ static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame, break; } case UPB_DESCRIPTOR_TYPE_SINT32: { - int32_t decoded = upb_zzdec_32(val); + int32_t decoded = upb_zzdecode_32(val); memcpy(field_mem, &decoded, sizeof(decoded)); break; } case UPB_DESCRIPTOR_TYPE_SINT64: { - int64_t decoded = upb_zzdec_64(val); + int64_t decoded = upb_zzdecode_64(val); memcpy(field_mem, &decoded, sizeof(decoded)); break; } @@ -443,9 +443,9 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, case UPB_DESCRIPTOR_TYPE_BOOL: VARINT_CASE(bool, bool); case UPB_DESCRIPTOR_TYPE_SINT32: - VARINT_CASE(int32_t, upb_zzdec_32); + VARINT_CASE(int32_t, upb_zzdecode_32); case UPB_DESCRIPTOR_TYPE_SINT64: - VARINT_CASE(int64_t, upb_zzdec_64); + VARINT_CASE(int64_t, upb_zzdecode_64); case UPB_DESCRIPTOR_TYPE_MESSAGE: CHK(val.size <= (size_t)(frame->limit - val.data)); return upb_decode_submsg(d, frame, val.data + val.size, field, 0); diff --git a/upb/encode.c b/upb/encode.c index d41b0ed..5acb492 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -8,7 +8,7 @@ #define CHK(x) do { if (!(x)) { return false; } } while(0) /* Maps descriptor type -> upb field type. */ -static const uint8_t upb_desctype_to_fieldtype[] = { +static const uint8_t upb_desctype_to_fieldtype2[] = { UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ UPB_TYPE_DOUBLE, /* DOUBLE */ UPB_TYPE_FLOAT, /* FLOAT */ @@ -43,8 +43,8 @@ static size_t upb_encode_varint(uint64_t val, char *buf) { return i; } -static uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); } -static uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } +static uint32_t upb_zzencode_32(int32_t n) { return (n << 1) ^ (n >> 31); } +static uint64_t upb_zzencode_64(int64_t n) { return (n << 1) ^ (n >> 63); } typedef struct { upb_env *env; @@ -162,7 +162,7 @@ static bool upb_encode_array(upb_encstate *e, const char *field_mem, return true; } - UPB_ASSERT(arr->type == upb_desctype_to_fieldtype[f->type]); + UPB_ASSERT(arr->type == upb_desctype_to_fieldtype2[f->type]); #define VARINT_CASE(ctype, encode) { \ ctype *start = arr->data; \ @@ -202,9 +202,9 @@ do { ; } while(0) case UPB_DESCRIPTOR_TYPE_BOOL: VARINT_CASE(bool, *ptr); case UPB_DESCRIPTOR_TYPE_SINT32: - VARINT_CASE(int32_t, upb_zzenc_32(*ptr)); + VARINT_CASE(int32_t, upb_zzencode_32(*ptr)); case UPB_DESCRIPTOR_TYPE_SINT64: - VARINT_CASE(int64_t, upb_zzenc_64(*ptr)); + VARINT_CASE(int64_t, upb_zzencode_64(*ptr)); case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { upb_stringview *start = arr->data; @@ -288,9 +288,9 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, case UPB_DESCRIPTOR_TYPE_BOOL: CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val); case UPB_DESCRIPTOR_TYPE_SINT32: - CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzenc_32(val)); + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val)); case UPB_DESCRIPTOR_TYPE_SINT64: - CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzenc_64(val)); + CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val)); case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { upb_stringview view = *(upb_stringview*)field_mem; -- cgit v1.2.3