diff --git a/BUILD b/BUILD index cddda82d18c..202154c9d05 100644 --- a/BUILD +++ b/BUILD @@ -1,3 +1,7 @@ +load( + "@rules_proto//proto:defs.bzl", + "proto_library", +) load( "//bazel:build_defs.bzl", "generated_file_staleness_test", @@ -81,6 +85,7 @@ cc_library( "upb/decode.h", "upb/encode.h", "upb/upb.h", + "upb/upb.hpp", ], copts = select({ ":windows": [], @@ -115,7 +120,13 @@ cc_library( ) upb_proto_library( - name = "descriptor_upbproto", + name = "descriptor_upb_proto", + visibility = ["//visibility:public"], + deps = ["@com_google_protobuf//:descriptor_proto"], +) + +upb_proto_reflection_library( + name = "descriptor_upb_proto_reflection", visibility = ["//visibility:public"], deps = ["@com_google_protobuf//:descriptor_proto"], ) @@ -129,6 +140,7 @@ cc_library( ], hdrs = [ "upb/def.h", + "upb/def.hpp", "upb/reflection.h", ], copts = select({ @@ -137,7 +149,7 @@ cc_library( }), visibility = ["//visibility:public"], deps = [ - ":descriptor_upbproto", + ":descriptor_upb_proto", ":port", ":table", ":upb", @@ -233,7 +245,7 @@ cc_library( "//conditions:default": COPTS, }), deps = [ - ":descriptor_upbproto", + ":descriptor_upb_proto", ":handlers", ":port", ":reflection", @@ -270,7 +282,7 @@ cc_library( "upb/bindings/stdc++/string.h", ], deps = [ - ":descriptor_upbproto", + ":descriptor_upb_proto", ":handlers", ":port", ":upb", @@ -329,7 +341,7 @@ cc_binary( testonly = 1, srcs = ["tests/benchmark.cc"], deps = [ - ":descriptor_upbproto", + ":descriptor_upb_proto", ":descriptor_upbreflection", "@com_github_google_benchmark//:benchmark_main", ], @@ -381,7 +393,7 @@ proto_library( ) upb_proto_library( - name = "test_upbproto", + name = "test_upb_proto", testonly = 1, deps = [":test_proto"], ) @@ -392,7 +404,7 @@ cc_test( deps = [ ":test_messages_proto3_proto_upb", ":empty_upbdefs_proto", - ":test_upbproto", + ":test_upb_proto", ":upb_test", ], ) @@ -422,7 +434,7 @@ proto_library( ) upb_proto_reflection_library( - name = "test_decoder_upbproto", + name = "test_decoder_upb_proto", deps = [":test_decoder_proto"], ) @@ -439,7 +451,7 @@ cc_test( deps = [ ":handlers", ":port", - ":test_decoder_upbproto", + ":test_decoder_upb_proto", ":upb", ":upb_pb", ":upb_test", @@ -454,7 +466,7 @@ proto_library( ) upb_proto_reflection_library( - name = "test_cpp_upbproto", + name = "test_cpp_upb_proto", deps = ["test_cpp_proto"], ) @@ -469,7 +481,7 @@ cc_test( ":handlers", ":port", ":reflection", - ":test_cpp_upbproto", + ":test_cpp_upb_proto", ":upb", ":upb_pb", ":upb_test", @@ -508,7 +520,7 @@ cc_binary( ":fuzz": ["HAVE_FUZZER"], }), deps = [ - ":descriptor_upbproto", + ":descriptor_upb_proto", ":upb", ], ) @@ -522,7 +534,7 @@ cc_test( "//conditions:default": CPPOPTS, }), deps = [ - ":descriptor_upbproto", + ":descriptor_upb_proto", ":descriptor_upbreflection", ":upb", ":upb_cc_bindings", @@ -543,17 +555,17 @@ proto_library( ) upb_proto_reflection_library( - name = "test_json_upbprotoreflection", + name = "test_json_upb_proto_reflection", deps = ["test_json_proto"], ) upb_proto_library( - name = "test_json_enum_from_separate_upbproto", + name = "test_json_enum_from_separate_upb_proto", deps = [":test_json_enum_from_separate"], ) upb_proto_library( - name = "test_json_upbproto", + name = "test_json_upb_proto", deps = [":test_json_proto"], ) @@ -567,8 +579,8 @@ cc_test( "//conditions:default": CPPOPTS, }), deps = [ - ":test_json_upbproto", - ":test_json_upbprotoreflection", + ":test_json_upb_proto", + ":test_json_upb_proto_reflection", ":upb_json", ":upb_test", ], @@ -656,7 +668,7 @@ upb_amalgamation( amalgamator = ":amalgamate", libs = [ ":upb", - ":descriptor_upbproto", + ":descriptor_upb_proto", ":reflection", ":handlers", ":port", @@ -675,6 +687,34 @@ cc_library( }), ) +upb_amalgamation( + name = "gen_php_amalgamation", + prefix = "php-", + outs = [ + "php-upb.c", + "php-upb.h", + ], + amalgamator = ":amalgamate", + libs = [ + ":upb", + ":descriptor_upb_proto", + ":descriptor_upb_proto_reflection", + ":reflection", + ":port", + ":json", + ], +) + +cc_library( + name = "php_amalgamation", + srcs = ["php-upb.c"], + hdrs = ["php-upb.h"], + copts = select({ + ":windows": [], + "//conditions:default": COPTS, + }), +) + # Lua ########################################################################## cc_library( @@ -818,7 +858,7 @@ genrule( genrule( name = "copy_protos", - srcs = [":descriptor_upbproto"], + srcs = [":descriptor_upb_proto"], outs = [ "generated-in/generated_for_cmake/google/protobuf/descriptor.upb.c", "generated-in/generated_for_cmake/google/protobuf/descriptor.upb.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f6004543fe..4dd64543213 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,8 @@ add_library(upb upb/upb.c upb/decode.h upb/encode.h - upb/upb.h) + upb/upb.h + upb/upb.hpp) target_link_libraries(upb port) add_library(generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me INTERFACE) @@ -84,9 +85,10 @@ add_library(reflection upb/msg.h upb/reflection.c upb/def.h + upb/def.hpp upb/reflection.h) target_link_libraries(reflection - descriptor_upbproto + descriptor_upb_proto port table upb) @@ -132,7 +134,7 @@ add_library(upb_pb upb/pb/encoder.h upb/pb/textprinter.h) target_link_libraries(upb_pb - descriptor_upbproto + descriptor_upb_proto handlers port reflection @@ -148,7 +150,7 @@ target_link_libraries(upb_json upb_pb) add_library(upb_cc_bindings INTERFACE) target_link_libraries(upb_cc_bindings INTERFACE - descriptor_upbproto + descriptor_upb_proto handlers port upb) diff --git a/bazel/build_defs.bzl b/bazel/build_defs.bzl index 7544e125175..c51aded057d 100644 --- a/bazel/build_defs.bzl +++ b/bazel/build_defs.bzl @@ -135,7 +135,7 @@ def _upb_amalgamation(ctx): ctx.actions.run( inputs = inputs, outputs = ctx.outputs.outs, - arguments = [ctx.bin_dir.path + "/"] + [f.path for f in srcs] + ["-I" + root for root in _get_real_roots(inputs)], + arguments = [ctx.bin_dir.path + "/", ctx.attr.prefix] + [f.path for f in srcs] + ["-I" + root for root in _get_real_roots(inputs)], progress_message = "Making amalgamation", executable = ctx.executable.amalgamator, ) @@ -147,6 +147,9 @@ upb_amalgamation = rule( executable = True, cfg = "host", ), + "prefix": attr.string( + default = "", + ), "libs": attr.label_list(aspects = [_file_list_aspect]), "outs": attr.output_list(), }, diff --git a/bazel/upb_proto_library.bzl b/bazel/upb_proto_library.bzl index 596b9c4c41a..3499ea94860 100644 --- a/bazel/upb_proto_library.bzl +++ b/bazel/upb_proto_library.bzl @@ -5,6 +5,7 @@ load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") +load("@rules_proto//proto:defs.bzl", "ProtoInfo") # Generic support code ######################################################### diff --git a/bazel/workspace_deps.bzl b/bazel/workspace_deps.bzl index 2a7f88f495f..5e3e8a69005 100644 --- a/bazel/workspace_deps.bzl +++ b/bazel/workspace_deps.bzl @@ -7,16 +7,27 @@ def upb_deps(): maybe( git_repository, name = "com_google_absl", - commit = "070f6e47b33a2909d039e620c873204f78809492", + commit = "df3ea785d8c30a9503321a3d35ee7d35808f190d", # LTS 2020-02-25 remote = "https://github.com/abseil/abseil-cpp.git", - shallow_since = "1541627663 -0500", + shallow_since = "1583355457 -0500" ) maybe( git_repository, name = "com_google_protobuf", remote = "https://github.com/protocolbuffers/protobuf.git", - commit = "d41002663fd04325ead28439dfd5ce2822b0d6fb", + commit = "62832897c3cf14c93b91c412f7e64086cd272cb7", # Need to use Git until proto3 optional is released + ) + + maybe( + http_archive, + name = "rules_python", + sha256 = "e5470e92a18aa51830db99a4d9c492cc613761d5bdb7131c04bd92b9834380f6", + strip_prefix = "rules_python-4b84ad270387a7c439ebdccfd530e2339601ef27", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/rules_python/archive/4b84ad270387a7c439ebdccfd530e2339601ef27.tar.gz", + "https://github.com/bazelbuild/rules_python/archive/4b84ad270387a7c439ebdccfd530e2339601ef27.tar.gz", + ], ) maybe( diff --git a/benchmark.py b/benchmark.py new file mode 100755 index 00000000000..9c596743bf3 --- /dev/null +++ b/benchmark.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import json +import subprocess +import re + +def Run(cmd): + subprocess.check_call(cmd, shell=True) + +def RunAgainstBranch(branch, outfile, runs=12): + tmpfile = "/tmp/bench-output.json" + Run("rm -rf {}".format(tmpfile)) + Run("git checkout {}".format(branch)) + Run("bazel build -c opt :benchmark") + + Run("./bazel-bin/benchmark --benchmark_out_format=json --benchmark_out={} --benchmark_repetitions={}".format(tmpfile, runs)) + + with open(tmpfile) as f: + bench_json = json.load(f) + + with open(outfile, "w") as f: + for run in bench_json["benchmarks"]: + name = re.sub(r'^BM_', 'Benchmark', run["name"]) + if name.endswith("_mean") or name.endswith("_median") or name.endswith("_stddev"): + continue + values = (name, run["iterations"], run["cpu_time"]) + print("{} {} {} ns/op".format(*values), file=f) + +RunAgainstBranch("master", "/tmp/old.txt") +RunAgainstBranch("decoder", "/tmp/new.txt") + +Run("~/go/bin/benchstat /tmp/old.txt /tmp/new.txt") diff --git a/examples/bazel/BUILD b/examples/bazel/BUILD index 94bcfe64d4f..9fb5c1f4a64 100644 --- a/examples/bazel/BUILD +++ b/examples/bazel/BUILD @@ -1,4 +1,4 @@ - +load("@rules_proto//proto:defs.bzl", "proto_library") load("@upb//bazel:upb_proto_library.bzl", "upb_proto_library") proto_library( diff --git a/generated_for_cmake/google/protobuf/descriptor.upb.c b/generated_for_cmake/google/protobuf/descriptor.upb.c index 61b9299bb43..3c7363922e9 100644 --- a/generated_for_cmake/google/protobuf/descriptor.upb.c +++ b/generated_for_cmake/google/protobuf/descriptor.upb.c @@ -130,23 +130,24 @@ static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1 &google_protobuf_FieldOptions_msginit, }; -static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[10] = { - {1, UPB_SIZE(32, 32), 5, 0, 9, 1}, - {2, UPB_SIZE(40, 48), 6, 0, 9, 1}, +static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = { + {1, UPB_SIZE(36, 40), 6, 0, 9, 1}, + {2, UPB_SIZE(44, 56), 7, 0, 9, 1}, {3, UPB_SIZE(24, 24), 3, 0, 5, 1}, {4, UPB_SIZE(8, 8), 1, 0, 14, 1}, {5, UPB_SIZE(16, 16), 2, 0, 14, 1}, - {6, UPB_SIZE(48, 64), 7, 0, 9, 1}, - {7, UPB_SIZE(56, 80), 8, 0, 9, 1}, - {8, UPB_SIZE(72, 112), 10, 0, 11, 1}, + {6, UPB_SIZE(52, 72), 8, 0, 9, 1}, + {7, UPB_SIZE(60, 88), 9, 0, 9, 1}, + {8, UPB_SIZE(76, 120), 11, 0, 11, 1}, {9, UPB_SIZE(28, 28), 4, 0, 5, 1}, - {10, UPB_SIZE(64, 96), 9, 0, 9, 1}, + {10, UPB_SIZE(68, 104), 10, 0, 9, 1}, + {17, UPB_SIZE(32, 32), 5, 0, 8, 1}, }; const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = { &google_protobuf_FieldDescriptorProto_submsgs[0], &google_protobuf_FieldDescriptorProto__fields[0], - UPB_SIZE(80, 128), 10, false, + UPB_SIZE(80, 128), 11, false, }; static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = { @@ -441,8 +442,8 @@ const upb_msglayout google_protobuf_SourceCodeInfo_msginit = { }; static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = { - {1, UPB_SIZE(20, 40), 0, 0, 5, 3}, - {2, UPB_SIZE(24, 48), 0, 0, 5, 3}, + {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED}, + {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED}, {3, UPB_SIZE(4, 8), 1, 0, 9, 1}, {4, UPB_SIZE(12, 24), 2, 0, 9, 1}, {6, UPB_SIZE(28, 56), 0, 0, 9, 3}, @@ -469,7 +470,7 @@ const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = { }; static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = { - {1, UPB_SIZE(20, 32), 0, 0, 5, 3}, + {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED}, {2, UPB_SIZE(12, 16), 3, 0, 9, 1}, {3, UPB_SIZE(4, 4), 1, 0, 5, 1}, {4, UPB_SIZE(8, 8), 2, 0, 5, 1}, diff --git a/generated_for_cmake/google/protobuf/descriptor.upb.h b/generated_for_cmake/google/protobuf/descriptor.upb.h index 5baad088109..5316dd30516 100644 --- a/generated_for_cmake/google/protobuf/descriptor.upb.h +++ b/generated_for_cmake/google/protobuf/descriptor.upb.h @@ -167,6 +167,7 @@ UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protob return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len); } +UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) { @@ -198,30 +199,34 @@ UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_prot } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); } UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); } UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); } UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 4); } -UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FileOptions*, UPB_SIZE(28, 56)); } +UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_SourceCodeInfo*, UPB_SIZE(32, 64)); } +UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); } UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); } UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; } UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len); @@ -287,7 +292,7 @@ UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDesc } UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, google_protobuf_FileOptions*, UPB_SIZE(28, 56)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value; } UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg); @@ -300,7 +305,7 @@ UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorPro } UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, google_protobuf_SourceCodeInfo*, UPB_SIZE(32, 64)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value; } UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg); @@ -333,7 +338,7 @@ UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_p } UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; } /* google.protobuf.DescriptorProto */ @@ -351,21 +356,28 @@ UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf } UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); } UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); } UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); } UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); } UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_MessageOptions*, UPB_SIZE(12, 24)); } +UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); } UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); } UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); } UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); } UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) { return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); @@ -434,7 +446,7 @@ UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_Descript } UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, google_protobuf_MessageOptions*, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value; } UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) { struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg); @@ -497,23 +509,23 @@ UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const } UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return UPB_FIELD_AT(msg, const google_protobuf_ExtensionRangeOptions*, UPB_SIZE(12, 16)); } +UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); } UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, google_protobuf_ExtensionRangeOptions*, UPB_SIZE(12, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value; } UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) { struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg); @@ -540,17 +552,17 @@ UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const g } UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } /* google.protobuf.ExtensionRangeOptions */ @@ -567,6 +579,7 @@ UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_pr return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len); } +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) { @@ -597,58 +610,60 @@ UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_pro return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(24, 24)); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); } -UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FieldOptions*, UPB_SIZE(72, 112)); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 11); } +UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 120), const google_protobuf_FieldOptions*); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 4); } -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool); } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)) = value; + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)) = value; + _upb_sethas(msg, 7); + *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(24, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 7); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)) = value; + _upb_sethas(msg, 8); + *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 8); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)) = value; + _upb_sethas(msg, 9); + *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) { - _upb_sethas(msg, 10); - UPB_FIELD_AT(msg, google_protobuf_FieldOptions*, UPB_SIZE(72, 112)) = value; + _upb_sethas(msg, 11); + *UPB_PTR_AT(msg, UPB_SIZE(76, 120), google_protobuf_FieldOptions*) = value; } UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg); @@ -661,11 +676,15 @@ UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorP } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 9); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)) = value; + _upb_sethas(msg, 10); + *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool) = value; } /* google.protobuf.OneofDescriptorProto */ @@ -683,17 +702,17 @@ UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_pro } UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_OneofOptions*, UPB_SIZE(12, 24)); } +UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); } UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, google_protobuf_OneofOptions*, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value; } UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg); @@ -720,16 +739,18 @@ UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_prot } UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_EnumOptions*, UPB_SIZE(12, 24)); } +UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); } UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); @@ -746,7 +767,7 @@ UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_Enum } UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, google_protobuf_EnumOptions*, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value; } UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg); @@ -796,17 +817,17 @@ UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize } UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } /* google.protobuf.EnumValueDescriptorProto */ @@ -824,23 +845,23 @@ UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google } UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)); } +UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_EnumValueOptions*, UPB_SIZE(16, 24)); } +UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, google_protobuf_EnumValueOptions*, UPB_SIZE(16, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value; } UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg); @@ -867,14 +888,15 @@ UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_p } UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_ServiceOptions*, UPB_SIZE(12, 24)); } +UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); } UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); @@ -891,7 +913,7 @@ UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_Service } UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, google_protobuf_ServiceOptions*, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value; } UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg); @@ -918,33 +940,33 @@ UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_pr } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 4); } -UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 6); } -UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_MethodOptions*, UPB_SIZE(28, 56)); } +UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) { _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, google_protobuf_MethodOptions*, UPB_SIZE(28, 56)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value; } UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg); @@ -957,11 +979,11 @@ UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescripto } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; } /* google.protobuf.FileOptions */ @@ -979,126 +1001,127 @@ UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_Fil } UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 11); } -UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(28, 32)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 12); } -UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 48)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)); } +UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 13); } -UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 64)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(17, 17)); } +UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 4); } -UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(18, 18)); } +UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(19, 19)); } +UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 6); } -UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(20, 20)); } +UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 7); } -UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(21, 21)); } +UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 8); } -UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(22, 22)); } +UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 9); } -UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(23, 23)); } +UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 14); } -UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 80)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 15); } -UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 96)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 16); } -UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 112)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 17); } -UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(76, 128)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 18); } -UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(84, 144)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 10); } -UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)); } +UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 19); } -UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(92, 160)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 20); } -UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(100, 176)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(108, 192)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(108, 192), len); } UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 11); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(28, 32)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 12); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 48)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 13); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 64)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, bool, UPB_SIZE(17, 17)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, bool, UPB_SIZE(18, 18)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, bool, UPB_SIZE(19, 19)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, bool, UPB_SIZE(20, 20)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 7); - UPB_FIELD_AT(msg, bool, UPB_SIZE(21, 21)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 8); - UPB_FIELD_AT(msg, bool, UPB_SIZE(22, 22)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 9); - UPB_FIELD_AT(msg, bool, UPB_SIZE(23, 23)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 14); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 80)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 15); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 96)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 16); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 112)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 17); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(76, 128)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 18); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(84, 144)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 10); - UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 19); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(92, 160)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 20); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(100, 176)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 192), len); @@ -1129,30 +1152,31 @@ UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_ } UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); } +UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(3, 3)); } +UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); } UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 4); } -UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(4, 4)); } +UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); } UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; } UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, bool, UPB_SIZE(3, 3)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value; } UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, bool, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len); @@ -1183,42 +1207,43 @@ UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_Fi } UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)); } +UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); } UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 4); } -UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(25, 25)); } +UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool); } UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(26, 26)); } +UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool); } UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); } +UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); } UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 6); } -UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(27, 27)); } +UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 32)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(28, 32), len); } UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, bool, UPB_SIZE(25, 25)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, bool, UPB_SIZE(26, 26)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) { _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, bool, UPB_SIZE(27, 27)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 32), len); @@ -1248,6 +1273,7 @@ UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_On return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len); } +UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) { @@ -1279,18 +1305,19 @@ UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_Enu } UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); } +UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } +UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); @@ -1321,12 +1348,13 @@ UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobu } UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); @@ -1357,12 +1385,13 @@ UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ } UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); @@ -1393,18 +1422,19 @@ UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_M } UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)); } +UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); } UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } +UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 24)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(20, 24), len); } UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value; } UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 24), len); @@ -1434,19 +1464,20 @@ UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_prot return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); } UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 4); } -UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)); } +UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, int64_t, UPB_SIZE(16, 16)); } +UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, double, UPB_SIZE(24, 24)); } +UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 6); } -UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); } UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) { return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len); @@ -1463,27 +1494,27 @@ UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_ } UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int64_t, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, double, UPB_SIZE(24, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value; } /* google.protobuf.UninterpretedOption.NamePart */ @@ -1501,17 +1532,17 @@ UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const go } UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } /* google.protobuf.SourceCodeInfo */ @@ -1528,6 +1559,7 @@ UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_ return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len); } +UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) { @@ -1561,9 +1593,9 @@ UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_ UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)); } +UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); } UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { @@ -1588,11 +1620,11 @@ UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf } UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; } UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); @@ -1619,6 +1651,7 @@ UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protob return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) { @@ -1651,11 +1684,11 @@ UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const go UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); } UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 16)); } +UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); } UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len); @@ -1669,15 +1702,15 @@ UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_pro } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value; } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } #ifdef __cplusplus diff --git a/generated_for_cmake/upb/json/parser.c b/generated_for_cmake/upb/json/parser.c index 03087845d5f..1423add9c53 100644 --- a/generated_for_cmake/upb/json/parser.c +++ b/generated_for_cmake/upb/json/parser.c @@ -735,7 +735,9 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len, /* Note: this invalidates the accumulate buffer! Call only after reading its * contents. */ static void multipart_end(upb_json_parser *p) { - UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); + /* This is false sometimes. Probably a bug of some sort, but this code is + * intended for deletion soon. */ + /* UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); */ p->multipart_state = MULTIPART_INACTIVE; accumulate_clear(p); } @@ -1370,7 +1372,12 @@ static bool end_stringval_nontop(upb_json_parser *p) { upb_selector_t sel = parser_getsel(p); upb_sink_putint32(p->top->sink, sel, int_val); } else { - upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf); + if (p->ignore_json_unknown) { + ok = true; + /* TODO(teboring): Should also clean this field. */ + } else { + upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf); + } } break; @@ -1689,24 +1696,15 @@ static void start_timestamp_zone(upb_json_parser *p, const char *ptr) { capture_begin(p, ptr); } -static int div_round_up2(int n, int d) { - return (n + d - 1) / d; -} - /* epoch_days(1970, 1, 1) == 1970-01-01 == 0. */ static int epoch_days(int year, int month, int day) { static const uint16_t month_yday[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - int febs_since_0 = month > 2 ? year + 1 : year; - int leap_days_since_0 = div_round_up2(febs_since_0, 4) - - div_round_up2(febs_since_0, 100) + - div_round_up2(febs_since_0, 400); - int days_since_0 = - 365 * year + month_yday[month - 1] + (day - 1) + leap_days_since_0; - - /* Convert from 0-epoch (0001-01-01 BC) to Unix Epoch (1970-01-01 AD). - * Since the "BC" system does not have a year zero, 1 BC == year zero. */ - return days_since_0 - 719528; + uint32_t year_adj = year + 4800; /* Ensure positive year, multiple of 400. */ + uint32_t febs = year_adj - (month <= 2 ? 1 : 0); /* Februaries since base. */ + uint32_t leap_days = 1 + (febs / 4) - (febs / 100) + (febs / 400); + uint32_t days = 365 * year_adj + leap_days + month_yday[month - 1] + day - 1; + return days - 2472692; /* Adjust to Unix epoch. */ } static int64_t upb_timegm(const struct tm *tp) { @@ -2575,11 +2573,11 @@ static bool does_fieldmask_end(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 2780 "upb/json/parser.rl" +#line 2778 "upb/json/parser.rl" -#line 2583 "upb/json/parser.c" +#line 2581 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 1, 1, 3, 1, 4, 1, 6, 1, 7, 1, 8, 1, @@ -2834,7 +2832,7 @@ static const int json_en_value_machine = 78; static const int json_en_main = 1; -#line 2783 "upb/json/parser.rl" +#line 2781 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -2857,7 +2855,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 2861 "upb/json/parser.c" +#line 2859 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -2932,147 +2930,147 @@ _match: switch ( *_acts++ ) { case 1: -#line 2588 "upb/json/parser.rl" +#line 2586 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 2: -#line 2590 "upb/json/parser.rl" +#line 2588 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 23;goto _again;} } break; case 3: -#line 2594 "upb/json/parser.rl" +#line 2592 "upb/json/parser.rl" { start_text(parser, p); } break; case 4: -#line 2595 "upb/json/parser.rl" +#line 2593 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 5: -#line 2601 "upb/json/parser.rl" +#line 2599 "upb/json/parser.rl" { start_hex(parser); } break; case 6: -#line 2602 "upb/json/parser.rl" +#line 2600 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 7: -#line 2603 "upb/json/parser.rl" +#line 2601 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 8: -#line 2609 "upb/json/parser.rl" +#line 2607 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 9: -#line 2615 "upb/json/parser.rl" +#line 2613 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 10: -#line 2620 "upb/json/parser.rl" +#line 2618 "upb/json/parser.rl" { start_year(parser, p); } break; case 11: -#line 2621 "upb/json/parser.rl" +#line 2619 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_year(parser, p)); } break; case 12: -#line 2625 "upb/json/parser.rl" +#line 2623 "upb/json/parser.rl" { start_month(parser, p); } break; case 13: -#line 2626 "upb/json/parser.rl" +#line 2624 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_month(parser, p)); } break; case 14: -#line 2630 "upb/json/parser.rl" +#line 2628 "upb/json/parser.rl" { start_day(parser, p); } break; case 15: -#line 2631 "upb/json/parser.rl" +#line 2629 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_day(parser, p)); } break; case 16: -#line 2635 "upb/json/parser.rl" +#line 2633 "upb/json/parser.rl" { start_hour(parser, p); } break; case 17: -#line 2636 "upb/json/parser.rl" +#line 2634 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hour(parser, p)); } break; case 18: -#line 2640 "upb/json/parser.rl" +#line 2638 "upb/json/parser.rl" { start_minute(parser, p); } break; case 19: -#line 2641 "upb/json/parser.rl" +#line 2639 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_minute(parser, p)); } break; case 20: -#line 2645 "upb/json/parser.rl" +#line 2643 "upb/json/parser.rl" { start_second(parser, p); } break; case 21: -#line 2646 "upb/json/parser.rl" +#line 2644 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_second(parser, p)); } break; case 22: -#line 2651 "upb/json/parser.rl" +#line 2649 "upb/json/parser.rl" { start_duration_base(parser, p); } break; case 23: -#line 2652 "upb/json/parser.rl" +#line 2650 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_duration_base(parser, p)); } break; case 24: -#line 2654 "upb/json/parser.rl" +#line 2652 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 25: -#line 2659 "upb/json/parser.rl" +#line 2657 "upb/json/parser.rl" { start_timestamp_base(parser); } break; case 26: -#line 2661 "upb/json/parser.rl" +#line 2659 "upb/json/parser.rl" { start_timestamp_fraction(parser, p); } break; case 27: -#line 2662 "upb/json/parser.rl" +#line 2660 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } break; case 28: -#line 2664 "upb/json/parser.rl" +#line 2662 "upb/json/parser.rl" { start_timestamp_zone(parser, p); } break; case 29: -#line 2665 "upb/json/parser.rl" +#line 2663 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } break; case 30: -#line 2667 "upb/json/parser.rl" +#line 2665 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 31: -#line 2672 "upb/json/parser.rl" +#line 2670 "upb/json/parser.rl" { start_fieldmask_path_text(parser, p); } break; case 32: -#line 2673 "upb/json/parser.rl" +#line 2671 "upb/json/parser.rl" { end_fieldmask_path_text(parser, p); } break; case 33: -#line 2678 "upb/json/parser.rl" +#line 2676 "upb/json/parser.rl" { start_fieldmask_path(parser); } break; case 34: -#line 2679 "upb/json/parser.rl" +#line 2677 "upb/json/parser.rl" { end_fieldmask_path(parser); } break; case 35: -#line 2685 "upb/json/parser.rl" +#line 2683 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 36: -#line 2690 "upb/json/parser.rl" +#line 2688 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) { {stack[top++] = cs; cs = 47;goto _again;} @@ -3086,11 +3084,11 @@ _match: } break; case 37: -#line 2703 "upb/json/parser.rl" +#line 2701 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 78;goto _again;} } break; case 38: -#line 2708 "upb/json/parser.rl" +#line 2706 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_member(parser, p); @@ -3100,11 +3098,11 @@ _match: } break; case 39: -#line 2715 "upb/json/parser.rl" +#line 2713 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 40: -#line 2718 "upb/json/parser.rl" +#line 2716 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { end_any_member(parser, p); @@ -3114,7 +3112,7 @@ _match: } break; case 41: -#line 2729 "upb/json/parser.rl" +#line 2727 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_object(parser, p); @@ -3124,7 +3122,7 @@ _match: } break; case 42: -#line 2738 "upb/json/parser.rl" +#line 2736 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { CHECK_RETURN_TOP(end_any_object(parser, p)); @@ -3134,54 +3132,54 @@ _match: } break; case 43: -#line 2750 "upb/json/parser.rl" +#line 2748 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 44: -#line 2754 "upb/json/parser.rl" +#line 2752 "upb/json/parser.rl" { end_array(parser); } break; case 45: -#line 2759 "upb/json/parser.rl" +#line 2757 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_number(parser, p)); } break; case 46: -#line 2760 "upb/json/parser.rl" +#line 2758 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 47: -#line 2762 "upb/json/parser.rl" +#line 2760 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 48: -#line 2763 "upb/json/parser.rl" +#line 2761 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 49: -#line 2765 "upb/json/parser.rl" +#line 2763 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 50: -#line 2767 "upb/json/parser.rl" +#line 2765 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 51: -#line 2769 "upb/json/parser.rl" +#line 2767 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 52: -#line 2771 "upb/json/parser.rl" +#line 2769 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject_full(parser)); } break; case 53: -#line 2772 "upb/json/parser.rl" +#line 2770 "upb/json/parser.rl" { end_subobject_full(parser); } break; case 54: -#line 2777 "upb/json/parser.rl" +#line 2775 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 3185 "upb/json/parser.c" +#line 3183 "upb/json/parser.c" } } @@ -3198,32 +3196,32 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 0: -#line 2586 "upb/json/parser.rl" +#line 2584 "upb/json/parser.rl" { p--; {cs = stack[--top]; if ( p == pe ) goto _test_eof; goto _again;} } break; case 46: -#line 2760 "upb/json/parser.rl" +#line 2758 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 49: -#line 2765 "upb/json/parser.rl" +#line 2763 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 50: -#line 2767 "upb/json/parser.rl" +#line 2765 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 51: -#line 2769 "upb/json/parser.rl" +#line 2767 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 53: -#line 2772 "upb/json/parser.rl" +#line 2770 "upb/json/parser.rl" { end_subobject_full(parser); } break; -#line 3227 "upb/json/parser.c" +#line 3225 "upb/json/parser.c" } } } @@ -3231,7 +3229,7 @@ goto _again;} } _out: {} } -#line 2805 "upb/json/parser.rl" +#line 2803 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -3274,13 +3272,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 3278 "upb/json/parser.c" +#line 3276 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 2847 "upb/json/parser.rl" +#line 2845 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -3337,9 +3335,6 @@ upb_json_parser *upb_json_parser_create(upb_arena *arena, upb_sink output, upb_status *status, bool ignore_json_unknown) { -#ifndef NDEBUG - const size_t size_before = upb_arena_bytesallocated(arena); -#endif upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser)); if (!p) return false; @@ -3366,10 +3361,6 @@ upb_json_parser *upb_json_parser_create(upb_arena *arena, p->ignore_json_unknown = ignore_json_unknown; - /* If this fails, uncomment and increase the value in parser.h. */ - /* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */ - UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <= - UPB_JSON_PARSER_SIZE); return p; } diff --git a/kokoro/ubuntu/build.sh b/kokoro/ubuntu/build.sh index ad8122b1bdb..e73deef0ab8 100644 --- a/kokoro/ubuntu/build.sh +++ b/kokoro/ubuntu/build.sh @@ -14,3 +14,9 @@ bazel version cd $(dirname $0)/../.. bazel test --test_output=errors :all + +if [[ $(uname) = "Linux" ]]; then + # Verify the ASAN build. Have to exclude test_conformance_upb as protobuf + # currently leaks memory in the conformance test runner. + bazel test --copt=-fsanitize=address --linkopt=-fsanitize=address --test_output=errors -- :all -:test_conformance_upb +fi diff --git a/tests/benchmark.cc b/tests/benchmark.cc index bcb4ec78b63..c1d6e063d64 100644 --- a/tests/benchmark.cc +++ b/tests/benchmark.cc @@ -9,15 +9,25 @@ upb_strview descriptor = google_protobuf_descriptor_proto_upbdefinit.descriptor; /* A buffer big enough to parse descriptor.proto without going to heap. */ char buf[65535]; -static void BM_CreateArena(benchmark::State& state) { +static void BM_ArenaOneAlloc(benchmark::State& state) { + for (auto _ : state) { + upb_arena* arena = upb_arena_new(); + upb_arena_malloc(arena, 1); + upb_arena_free(arena); + } +} +BENCHMARK(BM_ArenaOneAlloc); + +static void BM_ArenaInitialBlockOneAlloc(benchmark::State& state) { for (auto _ : state) { upb_arena* arena = upb_arena_init(buf, sizeof(buf), NULL); + upb_arena_malloc(arena, 1); upb_arena_free(arena); } } -BENCHMARK(BM_CreateArena); +BENCHMARK(BM_ArenaInitialBlockOneAlloc); -static void BM_ParseDescriptor(benchmark::State& state) { +static void BM_ParseDescriptorNoHeap(benchmark::State& state) { size_t bytes = 0; for (auto _ : state) { upb_arena* arena = upb_arena_init(buf, sizeof(buf), NULL); @@ -33,4 +43,22 @@ static void BM_ParseDescriptor(benchmark::State& state) { } state.SetBytesProcessed(state.iterations() * descriptor.size); } +BENCHMARK(BM_ParseDescriptorNoHeap); + +static void BM_ParseDescriptor(benchmark::State& state) { + size_t bytes = 0; + for (auto _ : state) { + upb_arena* arena = upb_arena_new(); + google_protobuf_FileDescriptorProto* set = + google_protobuf_FileDescriptorProto_parse(descriptor.data, + descriptor.size, arena); + if (!set) { + printf("Failed to parse.\n"); + exit(1); + } + bytes += descriptor.size; + upb_arena_free(arena); + } + state.SetBytesProcessed(state.iterations() * descriptor.size); +} BENCHMARK(BM_ParseDescriptor); diff --git a/tests/bindings/lua/test_upb.lua b/tests/bindings/lua/test_upb.lua index eaaf7e40859..d1c32b16746 100644 --- a/tests/bindings/lua/test_upb.lua +++ b/tests/bindings/lua/test_upb.lua @@ -467,6 +467,36 @@ function test_foo() assert_equal(set.file[1].name, "google/protobuf/descriptor.proto") end +function test_gc() + local top = test_messages_proto3.TestAllTypesProto3() + local n = 100 + local m + + for i=1,n do + local inner = test_messages_proto3.TestAllTypesProto3() + m = inner + for j=1,n do + local tmp = m + m = test_messages_proto3.TestAllTypesProto3() + -- This will cause the arenas to fuse. But we stop referring to the child, + -- so the Lua object is eligible for collection (and therefore its original + -- arena can be collected too). Only the fusing will keep the C mem alivd. + m.recursive_message = tmp + + end + top.recursive_message = m + end + + collectgarbage() + + for i=1,n do + -- Verify we can touch all the messages again and without accessing freed + -- memory. + m = m.recursive_message + assert_not_nil(m) + end +end + local stats = lunit.main() if stats.failed > 0 or stats.errors > 0 then diff --git a/tests/conformance_upb.c b/tests/conformance_upb.c index 1d87060095f..4a04adf8e49 100644 --- a/tests/conformance_upb.c +++ b/tests/conformance_upb.c @@ -19,6 +19,8 @@ #include "upb/json_encode.h" #include "upb/text_encode.h" +#include "upb/port_def.inc" + int test_count = 0; bool verbose = false; /* Set to true to get req/resp printed on stderr. */ @@ -94,7 +96,7 @@ void serialize_text(const upb_msg *msg, const upb_msgdef *m, const ctx *c) { len = upb_text_encode(msg, m, c->symtab, opts, NULL, 0); data = upb_arena_malloc(c->arena, len + 1); len2 = upb_text_encode(msg, m, c->symtab, opts, data, len + 1); - assert(len == len2); + UPB_ASSERT(len == len2); conformance_ConformanceResponse_set_text_payload( c->response, upb_strview_make(data, len)); } @@ -149,7 +151,7 @@ void serialize_json(const upb_msg *msg, const upb_msgdef *m, const ctx *c) { data = upb_arena_malloc(c->arena, len + 1); len2 = upb_json_encode(msg, m, c->symtab, opts, data, len + 1, &status); - assert(len == len2); + UPB_ASSERT(len == len2); conformance_ConformanceResponse_set_json_payload( c->response, upb_strview_make(data, len)); } diff --git a/tests/file_descriptor_parsenew_fuzzer.cc b/tests/file_descriptor_parsenew_fuzzer.cc index 057e62d8bf8..966a468063a 100644 --- a/tests/file_descriptor_parsenew_fuzzer.cc +++ b/tests/file_descriptor_parsenew_fuzzer.cc @@ -1,7 +1,7 @@ #include #include "google/protobuf/descriptor.upb.h" -#include "upb/upb.h" +#include "upb/upb.hpp" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { upb::Arena arena; diff --git a/tests/json/test_json.cc b/tests/json/test_json.cc index 66508179b3f..e5f01035842 100644 --- a/tests/json/test_json.cc +++ b/tests/json/test_json.cc @@ -3,18 +3,18 @@ * A set of tests for JSON parsing and serialization. */ +#include + +#include "tests/json/test.upb.h" // Test that it compiles for C++. #include "tests/json/test.upbdefs.h" -#include "tests/json/test.upb.h" // Test that it compiles for C++. #include "tests/test_util.h" #include "tests/upb_test.h" +#include "upb/def.hpp" #include "upb/handlers.h" #include "upb/json/parser.h" #include "upb/json/printer.h" -#include "upb/upb.h" - -#include - #include "upb/port_def.inc" +#include "upb/upb.h" // Macros for readability in test case list: allows us to give TEST("...") / // EXPECT("...") pairs. @@ -138,6 +138,21 @@ static TestCase kTestRoundtripMessagesPreserve[] = { TEST_SENTINEL }; +static TestCase kTestSkipUnknown[] = { + { + TEST("{\"optionalEnum\":\"UNKNOWN_ENUM_VALUE\"}"), + EXPECT("{}"), + }, + TEST_SENTINEL +}; + +static TestCase kTestFailure[] = { + { + TEST("{\"optionalEnum\":\"UNKNOWN_ENUM_VALUE\"}"), + }, + TEST_SENTINEL +}; + class StringSink { public: StringSink() { @@ -173,13 +188,15 @@ void test_json_roundtrip_message(const char* json_src, const char* json_expected, const upb::Handlers* serialize_handlers, const upb::json::ParserMethodPtr parser_method, - int seam) { + int seam, + bool ignore_unknown) { VerboseParserEnvironment env(verbose); StringSink data_sink; upb::json::PrinterPtr printer = upb::json::PrinterPtr::Create( env.arena(), serialize_handlers, data_sink.Sink()); upb::json::ParserPtr parser = upb::json::ParserPtr::Create( - env.arena(), parser_method, NULL, printer.input(), env.status(), false); + env.arena(), parser_method, NULL, printer.input(), + env.status(), ignore_unknown); env.ResetBytesSink(parser.input()); env.Reset(json_src, strlen(json_src), false, false); @@ -196,8 +213,8 @@ void test_json_roundtrip_message(const char* json_src, data_sink.Data().size())) { fprintf(stderr, "JSON parse/serialize roundtrip result differs:\n" - "Original:\n%s\nParsed/Serialized:\n%s\n", - json_src, data_sink.Data().c_str()); + "Expected:\n%s\nParsed/Serialized:\n%s\n", + json_expected, data_sink.Data().c_str()); abort(); } } @@ -225,7 +242,23 @@ void test_json_roundtrip() { for (size_t i = 0; i < strlen(test_case->input); i++) { test_json_roundtrip_message(test_case->input, expected, - serialize_handlers, parser_method, i); + serialize_handlers, parser_method, i, + false); + } + } + + // Tests ignore unknown. + for (const TestCase* test_case = kTestSkipUnknown; + test_case->input != NULL; test_case++) { + const char *expected = + (test_case->expected == EXPECT_SAME) ? + test_case->input : + test_case->expected; + + for (size_t i = 0; i < strlen(test_case->input); i++) { + test_json_roundtrip_message(test_case->input, expected, + serialize_handlers, parser_method, i, + true); } } @@ -241,7 +274,52 @@ void test_json_roundtrip() { for (size_t i = 0; i < strlen(test_case->input); i++) { test_json_roundtrip_message(test_case->input, expected, - serialize_handlers, parser_method, i); + serialize_handlers, parser_method, i, + false); + } + } +} + +void test_json_parse_failure(const char* json_src, + const upb::Handlers* serialize_handlers, + const upb::json::ParserMethodPtr parser_method, + int seam) { + VerboseParserEnvironment env(verbose); + StringSink data_sink; + upb::json::PrinterPtr printer = upb::json::PrinterPtr::Create( + env.arena(), serialize_handlers, data_sink.Sink()); + upb::json::ParserPtr parser = upb::json::ParserPtr::Create( + env.arena(), parser_method, NULL, printer.input(), env.status(), false); + env.ResetBytesSink(parser.input()); + env.Reset(json_src, strlen(json_src), false, true); + + bool ok = env.Start() && + env.ParseBuffer(seam) && + env.ParseBuffer(-1) && + env.End(); + + ASSERT(!ok); + ASSERT(env.CheckConsistency()); +} + +// Starts with a proto message in JSON format, parses and expects failre. +void test_json_failure() { + upb::SymbolTable symtab; + upb::HandlerCache serialize_handlercache( + upb::json::PrinterPtr::NewCache(false)); + upb::json::CodeCache parse_codecache; + + upb::MessageDefPtr md(upb_test_json_TestMessage_getmsgdef(symtab.ptr())); + ASSERT(md); + const upb::Handlers* serialize_handlers = serialize_handlercache.Get(md); + const upb::json::ParserMethodPtr parser_method = parse_codecache.Get(md); + ASSERT(serialize_handlers); + + for (const TestCase* test_case = kTestFailure; + test_case->input != NULL; test_case++) { + for (size_t i = 0; i < strlen(test_case->input); i++) { + test_json_parse_failure(test_case->input, serialize_handlers, + parser_method, i); } } } @@ -251,6 +329,7 @@ int run_tests(int argc, char *argv[]) { UPB_UNUSED(argc); UPB_UNUSED(argv); test_json_roundtrip(); + test_json_failure(); return 0; } } diff --git a/tests/pb/test_encoder.cc b/tests/pb/test_encoder.cc index c6544beea57..aeca1b39caa 100644 --- a/tests/pb/test_encoder.cc +++ b/tests/pb/test_encoder.cc @@ -1,14 +1,15 @@ +#include + +#include "google/protobuf/descriptor.upb.h" +#include "google/protobuf/descriptor.upbdefs.h" #include "tests/test_util.h" #include "tests/upb_test.h" #include "upb/bindings/stdc++/string.h" -#include "google/protobuf/descriptor.upb.h" -#include "google/protobuf/descriptor.upbdefs.h" #include "upb/pb/decoder.h" #include "upb/pb/encoder.h" - #include "upb/port_def.inc" -#include +#include "upb/upb.hpp" void test_pb_roundtrip() { std::string input( diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index abbafdabc8f..55cc077c880 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -914,6 +914,31 @@ void TestIteration() { ASSERT(oneof_count == md.oneof_count()); } +void TestArena() { + int n = 100000; + + struct Decrementer { + Decrementer(int* _p) : p(_p) {} + ~Decrementer() { (*p)--; } + int* p; + }; + + { + upb::Arena arena; + for (int i = 0; i < n; i++) { + arena.Own(new Decrementer(&n)); + + // Intersperse allocation and ensure we can write to it. + int* val = static_cast(upb_arena_malloc(arena.ptr(), sizeof(int))); + *val = i; + } + + // Test a large allocation. + upb_arena_malloc(arena.ptr(), 1000000); + } + ASSERT(n == 0); +} + extern "C" { int run_tests(int argc, char *argv[]) { @@ -950,6 +975,7 @@ int run_tests(int argc, char *argv[]) { TestHandlerDataDestruction(); TestIteration(); + TestArena(); return 0; } diff --git a/tests/test_generated_code.c b/tests/test_generated_code.c index 7fd958104e2..25fbf77ce8d 100644 --- a/tests/test_generated_code.c +++ b/tests/test_generated_code.c @@ -7,6 +7,8 @@ #include "tests/upb_test.h" #include "tests/test.upb.h" +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + const char test_str[] = "abcdefg"; const char test_str2[] = "12345678910"; const char test_str3[] = "rstlnezxcvbnm"; @@ -123,6 +125,11 @@ static void test_string_double_map() { double val; upb_test_MapTest_map_string_double_set(msg, test_str_view, 1.5, arena); + ASSERT(msg); + ASSERT(upb_test_MapTest_map_string_double_get(msg, test_str_view, &val)); + ASSERT(val == 1.5); + val = 0; + serialized.data = upb_test_MapTest_serialize(msg, arena, &serialized.size); ASSERT(serialized.data); @@ -349,6 +356,36 @@ void test_null_decode_buf() { ASSERT(msg); protobuf_test_messages_proto3_TestAllTypesProto3_serialize(msg, arena, &size); ASSERT(size == 0); + upb_arena_free(arena); +} + +void test_status_truncation() { + int i, j; + upb_status status; + upb_status status2; + for (i = 0; i < UPB_STATUS_MAX_MESSAGE + 20; i++) { + char *msg = malloc(i + 1); + int end; + char ch = (i % 96) + 33; /* Cycle through printable chars. */ + + for (j = 0; j < i; j++) { + msg[j] = ch; + } + msg[i] = '\0'; + + upb_status_seterrmsg(&status, msg); + upb_status_seterrf(&status2, "%s", msg); + end = MIN(i, UPB_STATUS_MAX_MESSAGE - 1); + ASSERT(strlen(status.msg) == end); + ASSERT(strlen(status2.msg) == end); + + for (j = 0; j < end; j++) { + ASSERT(status.msg[j] == ch); + ASSERT(status2.msg[j] == ch); + } + + free(msg); + } } int run_tests(int argc, char *argv[]) { @@ -358,5 +395,6 @@ int run_tests(int argc, char *argv[]) { test_int32_map(); test_repeated(); test_null_decode_buf(); + test_status_truncation(); return 0; } diff --git a/tools/amalgamate.py b/tools/amalgamate.py index bc083b38962..b244eff8e86 100755 --- a/tools/amalgamate.py +++ b/tools/amalgamate.py @@ -11,14 +11,14 @@ def parse_include(line): return match.groups()[0] if match else None class Amalgamator: - def __init__(self, output_path): + def __init__(self, output_path, prefix): self.include_paths = ["."] self.included = set(["upb/port_def.inc", "upb/port_undef.inc"]) - self.output_h = open(output_path + "upb.h", "w") - self.output_c = open(output_path + "upb.c", "w") + self.output_h = open(output_path + prefix + "upb.h", "w") + self.output_c = open(output_path + prefix + "upb.c", "w") self.output_c.write("/* Amalgamated source file */\n") - self.output_c.write('#include "upb.h"\n') + self.output_c.write('#include "%supb.h"\n' % (prefix)) self.output_c.write(open("upb/port_def.inc").read()) self.output_h.write("/* Amalgamated source file */\n") @@ -45,15 +45,25 @@ class Amalgamator: raise RuntimeError("Couldn't open file " + infile_name) for line in file: - include = parse_include(line) - if include is not None and (include.startswith("upb") or - include.startswith("google")): - if include not in self.included: - self.included.add(include) - self._add_header(include) - else: + if not self._process_include(line, outfile): outfile.write(line) + def _process_include(self, line, outfile): + include = parse_include(line) + if not include: + return False + if not (include.startswith("upb") or include.startswith("google")): + return False + if include.endswith("hpp"): + # Skip, we don't support the amalgamation from C++. + return True + else: + # Include this upb header inline. + if include not in self.included: + self.included.add(include) + self._add_header(include) + return True + def _add_header(self, filename): self._process_file(filename, self.output_h) @@ -63,10 +73,11 @@ class Amalgamator: # ---- main ---- output_path = sys.argv[1] -amalgamator = Amalgamator(output_path) +prefix = sys.argv[2] +amalgamator = Amalgamator(output_path, prefix) files = [] -for arg in sys.argv[2:]: +for arg in sys.argv[3:]: arg = arg.strip() if arg.startswith("-I"): amalgamator.add_include_path(arg[2:]) diff --git a/tools/make_cmakelists.py b/tools/make_cmakelists.py index 76e3ee15981..c31b413a898 100755 --- a/tools/make_cmakelists.py +++ b/tools/make_cmakelists.py @@ -36,7 +36,9 @@ class BuildFileFunctions(object): pass def cc_library(self, **kwargs): - if kwargs["name"] == "amalgamation" or kwargs["name"] == "upbc_generator": + if kwargs["name"].endswith("amalgamation"): + return + if kwargs["name"] == "upbc_generator": return if kwargs["name"] == "lupb": return diff --git a/upb/bindings/lua/msg.c b/upb/bindings/lua/msg.c index 6bf393f7736..df9f009d768 100644 --- a/upb/bindings/lua/msg.c +++ b/upb/bindings/lua/msg.c @@ -42,34 +42,29 @@ * the wrappers can be collected if they are no longer needed. A new wrapper * object can always be recreated later. * - * arena - * +->group - * | - * V +-----+ + * +-----+ * lupb_arena |cache|-weak-+ * | ^ +-----+ | * | | V * Lua level | +------------lupb_msg - * ----------------|-----------------|------------------------------------------- + * ----------------|-----------------|------------------------------------------ * upb level | | * | +----V------------------------------+ * +->upb_arena | upb_msg ...(empty arena storage) | * +-----------------------------------+ * * If the user creates a reference between two objects that have different - * arenas, we need to merge the arenas into a single, bigger arena group. The - * arena group will reference both arenas, and will inherit the longest lifetime - * of anything in the arena. + * arenas, we need to fuse the two arenas together, so that the blocks will + * outlive both arenas. * - * arena - * +--------------------------->group<-----------------+ + * +-------------------------->(fused)<----------------+ * | | * V +-----+ V * lupb_arena +-weak-|cache|-weak-+ lupb_arena * | ^ | +-----+ | ^ | * | | V V | | * Lua level | +------------lupb_msg lupb_msg----+ | - * ----------------|-----------------|-------------------------|---------|------- + * ----------------|-----------------|-------------------------|---------|------ * upb level | | | | * | +----V----+ +----V----+ V * +->upb_arena | upb_msg | | upb_msg | upb_arena @@ -77,7 +72,7 @@ * +---------------------+ * Key invariants: * 1. every wrapper references the arena that contains it. - * 2. every arena group references all arenas that own upb objects reachable + * 2. every fused arena includes all arenas that own upb objects reachable * from that arena. In other words, when a wrapper references an arena, * this is sufficient to ensure that any upb object reachable from that * wrapper will stay alive. @@ -85,12 +80,6 @@ * Additionally, every message object contains a strong reference to the * corresponding Descriptor object. Likewise, array/map objects reference a * Descriptor object if they are typed to store message values. - * - * (The object cache could be per-arena-group. This would keep individual cache - * tables smaller, and when an arena group is freed the entire cache table(s) could - * be collected in one fell swoop. However this makes merging another arena - * into the group an O(n) operation, since all entries would need to be copied - * from the existing cache table.) */ #define LUPB_ARENA "lupb.arena" @@ -170,14 +159,8 @@ static void lupb_cacheset(lua_State *L, const void *key) { /* lupb_arena only exists to wrap a upb_arena. It is never exposed to users; it * is an internal memory management detail. Other wrapper objects refer to this * object from their userdata to keep the arena-owned data alive. - * - * The arena userval is a table representing the arena group. Every arena in - * the group points to the same table, and the table references all arenas in - * the group. */ -#define LUPB_ARENAGROUP_INDEX 1 - typedef struct { upb_arena *arena; } lupb_arena; @@ -190,63 +173,18 @@ static upb_arena *lupb_arena_check(lua_State *L, int narg) { upb_arena *lupb_arena_pushnew(lua_State *L) { lupb_arena *a = lupb_newuserdata(L, sizeof(lupb_arena), 1, LUPB_ARENA); a->arena = upb_arena_new(); - - /* Create arena group table and add this arena to it. */ - lua_createtable(L, 0, 1); - lua_pushvalue(L, -2); - lua_rawseti(L, -2, 1); - - /* Set arena group as this object's userval. */ - lua_setiuservalue(L, -2, LUPB_ARENAGROUP_INDEX); - return a->arena; } /** - * lupb_arena_merge() + * lupb_arena_fuse() * * Merges |from| into |to| so that there is a single arena group that contains * both, and both arenas will point at this new table. */ -static void lupb_arena_merge(lua_State *L, int to, int from) { - int i, from_count, to_count; - lua_getiuservalue(L, to, LUPB_ARENAGROUP_INDEX); - lua_getiuservalue(L, from, LUPB_ARENAGROUP_INDEX); - - if (lua_rawequal(L, -1, -2)) { - /* These arenas are already in the same group. */ - lua_pop(L, 2); - return; - } - - to_count = lua_rawlen(L, -2); - from_count = lua_rawlen(L, -1); - - /* Add everything in |from|'s arena group. */ - for (i = 1; i <= from_count; i++) { - lua_rawgeti(L, -1, i); - lua_rawseti(L, -3, i + to_count); - } - - /* Make |from| point to |to|'s table. */ - lua_pop(L, 1); - lua_setiuservalue(L, from, LUPB_ARENAGROUP_INDEX); -} - -/** - * lupb_arena_addobj() - * - * Creates a reference from the arena in |narg| to the object at the top of the - * stack, and pops it. This will guarantee that the object lives as long as - * the arena. - * - * This is mainly useful for pinning strings we have parsed protobuf data from. - * It will allow us to point directly to string data in the original string. */ -static void lupb_arena_addobj(lua_State *L, int narg) { - lua_getiuservalue(L, narg, LUPB_ARENAGROUP_INDEX); - int n = lua_rawlen(L, -1); - lua_pushvalue(L, -2); - lua_rawseti(L, -2, n + 1); - lua_pop(L, 2); /* obj, arena group. */ +static void lupb_arena_fuse(lua_State *L, int to, int from) { + upb_arena *to_arena = lupb_arena_check(L, to); + upb_arena *from_arena = lupb_arena_check(L, from); + upb_arena_fuse(to_arena, from_arena); } static int lupb_arena_gc(lua_State *L) { @@ -877,7 +815,7 @@ static int lupb_msg_newindex(lua_State *L) { if (merge_arenas) { lua_getiuservalue(L, 1, LUPB_ARENA_INDEX); lua_getiuservalue(L, 3, LUPB_ARENA_INDEX); - lupb_arena_merge(L, lua_absindex(L, -2), lua_absindex(L, -1)); + lupb_arena_fuse(L, lua_absindex(L, -2), lua_absindex(L, -1)); lua_pop(L, 2); } @@ -940,6 +878,7 @@ static int lupb_decode(lua_State *L) { const upb_msgdef *m = lupb_msgdef_check(L, 1); const char *pb = lua_tolstring(L, 2, &len); const upb_msglayout *layout = upb_msgdef_layout(m); + char *buf; upb_msg *msg; upb_arena *arena; bool ok; @@ -952,13 +891,13 @@ static int lupb_decode(lua_State *L) { lua_getiuservalue(L, -1, LUPB_ARENA_INDEX); arena = lupb_arena_check(L, -1); - - /* Pin string data so we can reference it. */ - lua_pushvalue(L, 2); - lupb_arena_addobj(L, -2); lua_pop(L, 1); - ok = upb_decode(pb, len, msg, layout, arena); + /* Copy input data to arena, message will reference it. */ + buf = upb_arena_malloc(arena, len); + memcpy(buf, pb, len); + + ok = upb_decode(buf, len, msg, layout, arena); if (!ok) { lua_pushstring(L, "Error decoding protobuf."); diff --git a/upb/decode.c b/upb/decode.c index 8a7f64d1453..b78451c9dff 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -1,616 +1,553 @@ +#include #include -#include "upb/upb.h" + #include "upb/decode.h" +#include "upb/upb.h" #include "upb/port_def.inc" /* Maps descriptor type -> upb field type. */ static const uint8_t desctype_to_fieldtype[] = { - -1, /* invalid descriptor type */ - 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 */ + -1, /* invalid descriptor type */ + 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 */ }; /* Maps descriptor type -> upb map size. */ static const uint8_t desctype_to_mapsize[] = { - -1, /* invalid descriptor type */ - 8, /* DOUBLE */ - 4, /* FLOAT */ - 8, /* INT64 */ - 8, /* UINT64 */ - 4, /* INT32 */ - 8, /* FIXED64 */ - 4, /* FIXED32 */ - 1, /* BOOL */ - UPB_MAPTYPE_STRING, /* STRING */ - sizeof(void*), /* GROUP */ - sizeof(void*), /* MESSAGE */ - UPB_MAPTYPE_STRING, /* BYTES */ - 4, /* UINT32 */ - 4, /* ENUM */ - 4, /* SFIXED32 */ - 8, /* SFIXED64 */ - 4, /* SINT32 */ - 8, /* SINT64 */ + -1, /* invalid descriptor type */ + 8, /* DOUBLE */ + 4, /* FLOAT */ + 8, /* INT64 */ + 8, /* UINT64 */ + 4, /* INT32 */ + 8, /* FIXED64 */ + 4, /* FIXED32 */ + 1, /* BOOL */ + UPB_MAPTYPE_STRING, /* STRING */ + sizeof(void *), /* GROUP */ + sizeof(void *), /* MESSAGE */ + UPB_MAPTYPE_STRING, /* BYTES */ + 4, /* UINT32 */ + 4, /* ENUM */ + 4, /* SFIXED32 */ + 8, /* SFIXED64 */ + 4, /* SINT32 */ + 8, /* SINT64 */ +}; + +static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) | + (1 << UPB_DTYPE_FIXED32) | + (1 << UPB_DTYPE_SFIXED32); + +static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) | + (1 << UPB_DTYPE_FIXED64) | + (1 << UPB_DTYPE_SFIXED64); + +/* Op: an action to be performed for a wire-type/field-type combination. */ +#define OP_SCALAR_LG2(n) (n) +#define OP_FIXPCK_LG2(n) (n + 4) +#define OP_VARPCK_LG2(n) (n + 8) +#define OP_STRING 4 +#define OP_SUBMSG 5 + +static const int8_t varint_ops[19] = { + -1, /* field not found */ + -1, /* DOUBLE */ + -1, /* FLOAT */ + OP_SCALAR_LG2(3), /* INT64 */ + OP_SCALAR_LG2(3), /* UINT64 */ + OP_SCALAR_LG2(2), /* INT32 */ + -1, /* FIXED64 */ + -1, /* FIXED32 */ + OP_SCALAR_LG2(0), /* BOOL */ + -1, /* STRING */ + -1, /* GROUP */ + -1, /* MESSAGE */ + -1, /* BYTES */ + OP_SCALAR_LG2(2), /* UINT32 */ + OP_SCALAR_LG2(2), /* ENUM */ + -1, /* SFIXED32 */ + -1, /* SFIXED64 */ + OP_SCALAR_LG2(2), /* SINT32 */ + OP_SCALAR_LG2(3), /* SINT64 */ +}; + +static const int8_t delim_ops[37] = { + /* For non-repeated field type. */ + -1, /* field not found */ + -1, /* DOUBLE */ + -1, /* FLOAT */ + -1, /* INT64 */ + -1, /* UINT64 */ + -1, /* INT32 */ + -1, /* FIXED64 */ + -1, /* FIXED32 */ + -1, /* BOOL */ + OP_STRING, /* STRING */ + -1, /* GROUP */ + OP_SUBMSG, /* MESSAGE */ + OP_STRING, /* BYTES */ + -1, /* UINT32 */ + -1, /* ENUM */ + -1, /* SFIXED32 */ + -1, /* SFIXED64 */ + -1, /* SINT32 */ + -1, /* SINT64 */ + /* For repeated field type. */ + OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */ + OP_FIXPCK_LG2(2), /* REPEATED FLOAT */ + OP_VARPCK_LG2(3), /* REPEATED INT64 */ + OP_VARPCK_LG2(3), /* REPEATED UINT64 */ + OP_VARPCK_LG2(2), /* REPEATED INT32 */ + OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */ + OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */ + OP_VARPCK_LG2(0), /* REPEATED BOOL */ + OP_STRING, /* REPEATED STRING */ + OP_SUBMSG, /* REPEATED GROUP */ + OP_SUBMSG, /* REPEATED MESSAGE */ + OP_STRING, /* REPEATED BYTES */ + OP_VARPCK_LG2(2), /* REPEATED UINT32 */ + OP_VARPCK_LG2(2), /* REPEATED ENUM */ + OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */ + OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */ + OP_VARPCK_LG2(2), /* REPEATED SINT32 */ + OP_VARPCK_LG2(3), /* REPEATED SINT64 */ }; /* Data pertaining to the parse. */ typedef struct { - const char *field_start; /* Start of this field. */ - const char *limit; /* End of delimited region or end of buffer. */ + const char *limit; /* End of delimited region or end of buffer. */ upb_arena *arena; int depth; - uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */ + uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */ + jmp_buf err; } upb_decstate; -#define CHK(x) if (!(x)) { return 0; } -#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs) +typedef union { + bool bool_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + upb_strview str_val; +} wireval; + +static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout); + +UPB_NORETURN static void decode_err(upb_decstate *d) { longjmp(d->err, 1); } -static const char *upb_decode_message(const char *ptr, const upb_msglayout *l, - upb_msg *msg, upb_decstate *d); +static bool decode_reserve(upb_decstate *d, upb_array *arr, int elem) { + bool need_realloc = arr->size - arr->len < elem; + if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, d->arena)) { + decode_err(d); + } + return need_realloc; +} -static const char *upb_decode_varint(const char *ptr, const char *limit, - uint64_t *val) { +UPB_NOINLINE +static const char *decode_longvarint64(upb_decstate *d, const char *ptr, + const char *limit, uint64_t *val) { uint8_t byte; int bitpos = 0; - *val = 0; + uint64_t out = 0; do { - CHK(bitpos < 70 && ptr < limit); + if (bitpos >= 70 || ptr == limit) decode_err(d); byte = *ptr; - *val |= (uint64_t)(byte & 0x7F) << bitpos; + out |= (uint64_t)(byte & 0x7F) << bitpos; ptr++; bitpos += 7; } while (byte & 0x80); + *val = out; return ptr; } -static const char *upb_decode_varint32(const char *ptr, const char *limit, - uint32_t *val) { - uint64_t u64; - CHK(ptr = upb_decode_varint(ptr, limit, &u64)) - CHK(u64 <= UINT32_MAX); - *val = (uint32_t)u64; - return ptr; -} - -static const char *upb_decode_64bit(const char *ptr, const char *limit, - uint64_t *val) { - CHK(limit - ptr >= 8); - memcpy(val, ptr, 8); - return ptr + 8; -} - -static const char *upb_decode_32bit(const char *ptr, const char *limit, - uint32_t *val) { - CHK(limit - ptr >= 4); - memcpy(val, ptr, 4); - return ptr + 4; -} - -static int32_t upb_zzdecode_32(uint32_t n) { - return (n >> 1) ^ -(int32_t)(n & 1); -} - -static int64_t upb_zzdecode_64(uint64_t n) { - return (n >> 1) ^ -(int64_t)(n & 1); -} - -static const char *upb_decode_string(const char *ptr, const char *limit, - int *outlen) { - uint32_t len; - - CHK(ptr = upb_decode_varint32(ptr, limit, &len)); - CHK(len < INT32_MAX); - CHK(limit - ptr >= (int32_t)len); - - *outlen = len; - return ptr; -} - -static void upb_set32(void *msg, size_t ofs, uint32_t val) { - memcpy((char*)msg + ofs, &val, sizeof(val)); +UPB_FORCEINLINE +static const char *decode_varint64(upb_decstate *d, const char *ptr, + const char *limit, uint64_t *val) { + if (UPB_LIKELY(ptr < limit && (*ptr & 0x80) == 0)) { + *val = (uint8_t)*ptr; + return ptr + 1; + } else { + return decode_longvarint64(d, ptr, limit, val); + } } -static const char *upb_append_unknown(const char *ptr, upb_msg *msg, - upb_decstate *d) { - upb_msg_addunknown(msg, d->field_start, ptr - d->field_start, d->arena); +static const char *decode_varint32(upb_decstate *d, const char *ptr, + const char *limit, uint32_t *val) { + uint64_t u64; + ptr = decode_varint64(d, ptr, limit, &u64); + if (u64 > UINT32_MAX) decode_err(d); + *val = (uint32_t)u64; return ptr; } -static const char *upb_skip_unknownfielddata(const char *ptr, upb_decstate *d, - uint32_t tag) { - switch (tag & 7) { - case UPB_WIRE_TYPE_VARINT: { - uint64_t val; - return upb_decode_varint(ptr, d->limit, &val); - } - case UPB_WIRE_TYPE_32BIT: { - uint32_t val; - return upb_decode_32bit(ptr, d->limit, &val); - } - case UPB_WIRE_TYPE_64BIT: { - uint64_t val; - return upb_decode_64bit(ptr, d->limit, &val); - } - case UPB_WIRE_TYPE_DELIMITED: { - int len; - CHK(ptr = upb_decode_string(ptr, d->limit, &len)); - return ptr + len; +static void decode_munge(int type, wireval *val) { + switch (type) { + case UPB_DESCRIPTOR_TYPE_BOOL: + val->bool_val = val->uint64_val != 0; + break; + case UPB_DESCRIPTOR_TYPE_SINT32: { + uint32_t n = val->uint32_val; + val->int32_val = (n >> 1) ^ -(int32_t)(n & 1); + break; } - case UPB_WIRE_TYPE_START_GROUP: { - uint32_t field_number = tag >> 3; - while (ptr < d->limit && d->end_group == 0) { - uint32_t tag = 0; - CHK(ptr = upb_decode_varint32(ptr, d->limit, &tag)); - CHK(ptr = upb_skip_unknownfielddata(ptr, d, tag)); - } - CHK(d->end_group == field_number); - d->end_group = 0; - return ptr; + case UPB_DESCRIPTOR_TYPE_SINT64: { + uint64_t n = val->uint64_val; + val->int64_val = (n >> 1) ^ -(int64_t)(n & 1); + break; } - case UPB_WIRE_TYPE_END_GROUP: - d->end_group = tag >> 3; - return ptr; - } - return false; -} - -static void *upb_array_reserve(upb_array *arr, size_t elements, - size_t elem_size, upb_arena *arena) { - if (arr->size - arr->len < elements) { - CHK(_upb_array_realloc(arr, arr->len + elements, arena)); } - return (char*)_upb_array_ptr(arr) + (arr->len * elem_size); } -bool upb_array_add(upb_array *arr, size_t elements, size_t elem_size, - const void *data, upb_arena *arena) { - void *dest = upb_array_reserve(arr, elements, elem_size, arena); - - CHK(dest); - arr->len += elements; - memcpy(dest, data, elements * elem_size); - - return true; -} - -static upb_array *upb_getarr(upb_msg *msg, const upb_msglayout_field *field) { - UPB_ASSERT(field->label == UPB_LABEL_REPEATED); - return *PTR_AT(msg, field->offset, upb_array*); -} - -static upb_array *upb_getorcreatearr(upb_msg *msg, - const upb_msglayout_field *field, - upb_decstate *d) { - upb_array *arr = upb_getarr(msg, field); - - if (!arr) { - upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype]; - arr = _upb_array_new(d->arena, type); - CHK(arr); - *PTR_AT(msg, field->offset, upb_array*) = arr; - } - - return arr; -} - -static upb_msg *upb_getorcreatemsg(upb_msg *msg, - const upb_msglayout_field *field, - const upb_msglayout *layout, - upb_decstate *d) { - upb_msg **submsg = PTR_AT(msg, field->offset, upb_msg*); - - UPB_ASSERT(field->label != UPB_LABEL_REPEATED); - - if (!*submsg) { - *submsg = _upb_msg_new(layout, d->arena); - CHK(*submsg); - } - - return *submsg; -} - -static upb_msg *upb_addmsg(upb_msg *msg, - const upb_msglayout_field *field, - const upb_msglayout *layout, - upb_decstate *d) { - upb_msg *submsg; - upb_array *arr = upb_getorcreatearr(msg, field, d); - - UPB_ASSERT(field->label == UPB_LABEL_REPEATED); - UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || - field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP); - - submsg = _upb_msg_new(layout, d->arena); - CHK(submsg); - upb_array_add(arr, 1, sizeof(submsg), &submsg, d->arena); - - return submsg; -} - -static void upb_sethasbit(upb_msg *msg, const upb_msglayout_field *field) { - int32_t hasbit = field->presence; - UPB_ASSERT(field->presence > 0); - *PTR_AT(msg, hasbit / 8, char) |= (1 << (hasbit % 8)); -} - -static void upb_setoneofcase(upb_msg *msg, const upb_msglayout_field *field) { - UPB_ASSERT(field->presence < 0); - upb_set32(msg, ~field->presence, field->number); -} - -static bool upb_decode_addval(upb_msg *msg, const upb_msglayout_field *field, - void *val, size_t size, upb_decstate *d) { - char *field_mem = PTR_AT(msg, field->offset, char); - upb_array *arr; +static const upb_msglayout_field *upb_find_field(const upb_msglayout *l, + uint32_t field_number) { + static upb_msglayout_field none = {0}; - if (field->label == UPB_LABEL_REPEATED) { - arr = upb_getorcreatearr(msg, field, d); - CHK(arr); - field_mem = upb_array_reserve(arr, 1, size, d->arena); - CHK(field_mem); + /* Lots of optimization opportunities here. */ + int i; + if (l == NULL) return &none; + for (i = 0; i < l->field_count; i++) { + if (l->fields[i].number == field_number) { + return &l->fields[i]; + } } - memcpy(field_mem, val, size); - return true; + return &none; /* Unknown field. */ } -static void upb_decode_setpresent(upb_msg *msg, - const upb_msglayout_field *field) { - if (field->label == UPB_LABEL_REPEATED) { - upb_array *arr = upb_getarr(msg, field); - UPB_ASSERT(arr->len < arr->size); - arr->len++; - } else if (field->presence < 0) { - upb_setoneofcase(msg, field); - } else if (field->presence > 0) { - upb_sethasbit(msg, field); - } +static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout, + const upb_msglayout_field *field) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + return _upb_msg_new(subl, d->arena); } -static const char *upb_decode_msgfield(const char *ptr, - const upb_msglayout *layout, int limit, - upb_msg *msg, upb_decstate *d) { - const char* saved_limit = d->limit; - d->limit = ptr + limit; - CHK(--d->depth >= 0); - ptr = upb_decode_message(ptr, layout, msg, d); - d->depth++; +static void decode_tosubmsg(upb_decstate *d, upb_msg *submsg, + const upb_msglayout *layout, + const upb_msglayout_field *field, upb_strview val) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + const char *saved_limit = d->limit; + if (--d->depth < 0) decode_err(d); + d->limit = val.data + val.size; + decode_msg(d, val.data, submsg, subl); d->limit = saved_limit; - CHK(d->end_group == 0); - return ptr; + if (d->end_group != 0) decode_err(d); + d->depth++; } -static const char *upb_decode_groupfield(const char *ptr, - const upb_msglayout *layout, - int field_number, upb_msg *msg, - upb_decstate *d) { - CHK(--d->depth >= 0); - ptr = upb_decode_message(ptr, layout, msg, d); - d->depth++; - CHK(d->end_group == field_number); +static const char *decode_group(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *subl, + uint32_t number) { + if (--d->depth < 0) decode_err(d); + ptr = decode_msg(d, ptr, submsg, subl); + if (d->end_group != number) decode_err(d); d->end_group = 0; + d->depth++; return ptr; } -static const char *upb_decode_varintfield(const char *ptr, upb_msg *msg, - const upb_msglayout_field *field, - upb_decstate *d) { - uint64_t val; - CHK(ptr = upb_decode_varint(ptr, d->limit, &val)); - - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_UINT64: - CHK(upb_decode_addval(msg, field, &val, sizeof(val), d)); - break; - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_ENUM: { - uint32_t val32 = (uint32_t)val; - CHK(upb_decode_addval(msg, field, &val32, sizeof(val32), d)); - break; - } - case UPB_DESCRIPTOR_TYPE_BOOL: { - bool valbool = val != 0; - CHK(upb_decode_addval(msg, field, &valbool, sizeof(valbool), d)); - break; - } - case UPB_DESCRIPTOR_TYPE_SINT32: { - int32_t decoded = upb_zzdecode_32((uint32_t)val); - CHK(upb_decode_addval(msg, field, &decoded, sizeof(decoded), d)); - break; - } - case UPB_DESCRIPTOR_TYPE_SINT64: { - int64_t decoded = upb_zzdecode_64(val); - CHK(upb_decode_addval(msg, field, &decoded, sizeof(decoded), d)); - break; - } - default: - return upb_append_unknown(ptr, msg, d); - } - - upb_decode_setpresent(msg, field); - return ptr; +static const char *decode_togroup(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *layout, + const upb_msglayout_field *field) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + return decode_group(d, ptr, submsg, subl, field->number); } -static const char *upb_decode_64bitfield(const char *ptr, - const upb_msglayout_field *field, - upb_msg *msg, upb_decstate *d) { - uint64_t val; - CHK(ptr = upb_decode_64bit(ptr, d->limit, &val)); - - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_DOUBLE: - case UPB_DESCRIPTOR_TYPE_FIXED64: - case UPB_DESCRIPTOR_TYPE_SFIXED64: - CHK(upb_decode_addval(msg, field, &val, sizeof(val), d)); - break; - default: - return upb_append_unknown(ptr, msg, d); - } - - upb_decode_setpresent(msg, field); - return ptr; -} +static const char *decode_toarray(upb_decstate *d, const char *ptr, + upb_msg *msg, const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val, + int op) { + upb_array **arrp = UPB_PTR_AT(msg, field->offset, void); + upb_array *arr = *arrp; + void *mem; -static const char *upb_decode_32bitfield(const char *ptr, - const upb_msglayout_field *field, - upb_msg *msg, upb_decstate *d) { - uint32_t val; - CHK(ptr = upb_decode_32bit(ptr, d->limit, &val)); - - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_FLOAT: - case UPB_DESCRIPTOR_TYPE_FIXED32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - CHK(upb_decode_addval(msg, field, &val, sizeof(val), d)); - break; - default: - return upb_append_unknown(ptr, msg, d); + if (!arr) { + upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype]; + arr = _upb_array_new(d->arena, type); + if (!arr) decode_err(d); + *arrp = arr; } - upb_decode_setpresent(msg, field); - return ptr; -} - -static const char *upb_decode_fixedpacked(const char *ptr, upb_decstate *d, - upb_array *arr, uint32_t len, - int elem_size) { - size_t elements = len / elem_size; - - CHK((size_t)(elements * elem_size) == len); - CHK(upb_array_add(arr, elements, elem_size, ptr, d->arena)); - return ptr + len; -} - -static const char *upb_decode_strfield(const char *ptr, upb_decstate *d, - uint32_t len, upb_strview *str) { - str->data = ptr; - str->size = len; - return ptr + len; -} + decode_reserve(d, arr, 1); -static const char *upb_decode_toarray(const char *ptr, - const upb_msglayout *layout, - const upb_msglayout_field *field, int len, - upb_msg *msg, upb_decstate *d) { - upb_array *arr = upb_getorcreatearr(msg, field, d); - CHK(arr); - -#define VARINT_CASE(ctype, decode) \ - VARINT_CASE_EX(ctype, decode, decode) - -#define VARINT_CASE_EX(ctype, decode, dtype) \ - { \ - const char *limit = ptr + len; \ - while (ptr < limit) { \ - uint64_t val; \ - ctype decoded; \ - CHK(ptr = upb_decode_varint(ptr, limit, &val)); \ - decoded = (decode)((dtype)val); \ - CHK(upb_array_add(arr, 1, sizeof(decoded), &decoded, d->arena)); \ - } \ - return ptr; \ - } - - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_STRING: - case UPB_DESCRIPTOR_TYPE_BYTES: { - upb_strview str; - ptr = upb_decode_strfield(ptr, d, len, &str); - CHK(upb_array_add(arr, 1, sizeof(str), &str, d->arena)); + switch (op) { + case OP_SCALAR_LG2(0): + case OP_SCALAR_LG2(2): + case OP_SCALAR_LG2(3): + /* Append scalar value. */ + mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void); + arr->len++; + memcpy(mem, &val, 1 << op); + return ptr; + case OP_STRING: + /* Append string. */ + mem = + UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(upb_strview), void); + arr->len++; + memcpy(mem, &val, sizeof(upb_strview)); + return ptr; + case OP_SUBMSG: { + /* Append submessage / group. */ + upb_msg *submsg = decode_newsubmsg(d, layout, field); + *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) = + submsg; + arr->len++; + if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) { + ptr = decode_togroup(d, ptr, submsg, layout, field); + } else { + decode_tosubmsg(d, submsg, layout, field, val.str_val); + } return ptr; } - case UPB_DESCRIPTOR_TYPE_FLOAT: - case UPB_DESCRIPTOR_TYPE_FIXED32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - return upb_decode_fixedpacked(ptr, d, arr, len, sizeof(int32_t)); - case UPB_DESCRIPTOR_TYPE_DOUBLE: - case UPB_DESCRIPTOR_TYPE_FIXED64: - case UPB_DESCRIPTOR_TYPE_SFIXED64: - return upb_decode_fixedpacked(ptr, d, arr, len, sizeof(int64_t)); - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_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_EX(int32_t, upb_zzdecode_32, uint32_t); - case UPB_DESCRIPTOR_TYPE_SINT64: - VARINT_CASE_EX(int64_t, upb_zzdecode_64, uint64_t); - case UPB_DESCRIPTOR_TYPE_MESSAGE: { - const upb_msglayout *subl = layout->submsgs[field->submsg_index]; - upb_msg *submsg = upb_addmsg(msg, field, subl, d); - CHK(submsg); - return upb_decode_msgfield(ptr, subl, len, submsg, d); + case OP_FIXPCK_LG2(2): + case OP_FIXPCK_LG2(3): { + /* Fixed packed. */ + int lg2 = op - OP_FIXPCK_LG2(0); + int mask = (1 << lg2) - 1; + int count = val.str_val.size >> lg2; + if ((val.str_val.size & mask) != 0) { + decode_err(d); /* Length isn't a round multiple of elem size. */ + } + decode_reserve(d, arr, count); + mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + arr->len += count; + memcpy(mem, val.str_val.data, val.str_val.size); + return ptr; + } + case OP_VARPCK_LG2(0): + case OP_VARPCK_LG2(2): + case OP_VARPCK_LG2(3): { + /* Varint packed. */ + int lg2 = op - OP_VARPCK_LG2(0); + int scale = 1 << lg2; + const char *ptr = val.str_val.data; + const char *end = ptr + val.str_val.size; + char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + while (ptr < end) { + wireval elem; + ptr = decode_varint64(d, ptr, end, &elem.uint64_val); + decode_munge(field->descriptortype, &elem); + if (decode_reserve(d, arr, 1)) { + out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + } + arr->len++; + memcpy(out, &elem, scale); + out += scale; + } + if (ptr != end) decode_err(d); + return ptr; } - case UPB_DESCRIPTOR_TYPE_GROUP: - return upb_append_unknown(ptr, msg, d); + default: + UPB_UNREACHABLE(); } -#undef VARINT_CASE - UPB_UNREACHABLE(); } -static const char *upb_decode_mapfield(const char *ptr, - const upb_msglayout *layout, - const upb_msglayout_field *field, - int len, upb_msg *msg, upb_decstate *d) { - upb_map *map = *PTR_AT(msg, field->offset, upb_map*); - const upb_msglayout *entry = layout->submsgs[field->submsg_index]; +static void decode_tomap(upb_decstate *d, upb_msg *msg, + const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val) { + upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *); + upb_map *map = *map_p; upb_map_entry ent; + const upb_msglayout *entry = layout->submsgs[field->submsg_index]; if (!map) { /* Lazily create map. */ + const upb_msglayout *entry = layout->submsgs[field->submsg_index]; const upb_msglayout_field *key_field = &entry->fields[0]; const upb_msglayout_field *val_field = &entry->fields[1]; char key_size = desctype_to_mapsize[key_field->descriptortype]; char val_size = desctype_to_mapsize[val_field->descriptortype]; - UPB_ASSERT(key_field->number == 1); - UPB_ASSERT(val_field->number == 2); UPB_ASSERT(key_field->offset == 0); UPB_ASSERT(val_field->offset == sizeof(upb_strview)); map = _upb_map_new(d->arena, key_size, val_size); - *PTR_AT(msg, field->offset, upb_map*) = map; + *map_p = map; } /* Parse map entry. */ memset(&ent, 0, sizeof(ent)); - CHK(ptr = upb_decode_msgfield(ptr, entry, len, &ent.k, d)); + + if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || + entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) { + /* Create proactively to handle the case where it doesn't appear. */ + ent.v.val.val = (uint64_t)_upb_msg_new(entry->submsgs[0], d->arena); + } + + decode_tosubmsg(d, &ent.k, layout, field, val.str_val); /* Insert into map. */ _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena); - return ptr; } -static const char *upb_decode_delimitedfield(const char *ptr, - const upb_msglayout *layout, - const upb_msglayout_field *field, - upb_msg *msg, upb_decstate *d) { - int len; - - CHK(ptr = upb_decode_string(ptr, d->limit, &len)); +static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val, + int op) { + void *mem = UPB_PTR_AT(msg, field->offset, void); + int type = field->descriptortype; - if (field->label == UPB_LABEL_REPEATED) { - return upb_decode_toarray(ptr, layout, field, len, msg, d); - } else if (field->label == UPB_LABEL_MAP) { - return upb_decode_mapfield(ptr, layout, field, len, msg, d); - } else { - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_STRING: - case UPB_DESCRIPTOR_TYPE_BYTES: { - upb_strview str; - ptr = upb_decode_strfield(ptr, d, len, &str); - CHK(upb_decode_addval(msg, field, &str, sizeof(str), d)); - break; - } - case UPB_DESCRIPTOR_TYPE_MESSAGE: { - const upb_msglayout *subl = layout->submsgs[field->submsg_index]; - upb_msg *submsg = upb_getorcreatemsg(msg, field, subl, d); - CHK(submsg); - CHK(ptr = upb_decode_msgfield(ptr, subl, len, submsg, d)); - break; - } - default: - /* TODO(haberman): should we accept the last element of a packed? */ - return upb_append_unknown(ptr + len, msg, d); + /* Set presence if necessary. */ + if (field->presence < 0) { + /* Oneof case */ + int32_t *oneof_case = UPB_PTR_AT(msg, -field->presence, int32_t); + if (op == OP_SUBMSG && *oneof_case != field->number) { + memset(mem, 0, sizeof(void*)); } - upb_decode_setpresent(msg, field); - return ptr; + *oneof_case = field->number; + } else if (field->presence > 0) { + /* Hasbit */ + uint32_t hasbit = field->presence; + *UPB_PTR_AT(msg, hasbit / 8, uint8_t) |= (1 << (hasbit % 8)); } -} -static const upb_msglayout_field *upb_find_field(const upb_msglayout *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]; + /* Store into message. */ + switch (op) { + case OP_SUBMSG: { + upb_msg **submsgp = mem; + upb_msg *submsg = *submsgp; + if (!submsg) { + submsg = decode_newsubmsg(d, layout, field); + *submsgp = submsg; + } + if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) { + ptr = decode_togroup(d, ptr, submsg, layout, field); + } else { + decode_tosubmsg(d, submsg, layout, field, val.str_val); + } + break; } + case OP_STRING: + memcpy(mem, &val, sizeof(upb_strview)); + break; + case OP_SCALAR_LG2(3): + memcpy(mem, &val, 8); + break; + case OP_SCALAR_LG2(2): + memcpy(mem, &val, 4); + break; + case OP_SCALAR_LG2(0): + memcpy(mem, &val, 1); + break; + default: + UPB_UNREACHABLE(); } - return NULL; /* Unknown field. */ + return ptr; } -static const char *upb_decode_field(const char *ptr, - const upb_msglayout *layout, upb_msg *msg, - upb_decstate *d) { - uint32_t tag; - const upb_msglayout_field *field; - int field_number; +static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout) { + while (ptr < d->limit) { + uint32_t tag; + const upb_msglayout_field *field; + int field_number; + int wire_type; + const char *field_start = ptr; + wireval val; + int op; + + ptr = decode_varint32(d, ptr, d->limit, &tag); + field_number = tag >> 3; + wire_type = tag & 7; - d->field_start = ptr; - CHK(ptr = upb_decode_varint32(ptr, d->limit, &tag)); - field_number = tag >> 3; - field = upb_find_field(layout, field_number); + field = upb_find_field(layout, field_number); - if (field) { - switch (tag & 7) { + switch (wire_type) { case UPB_WIRE_TYPE_VARINT: - return upb_decode_varintfield(ptr, msg, field, d); + ptr = decode_varint64(d, ptr, d->limit, &val.uint64_val); + op = varint_ops[field->descriptortype]; + decode_munge(field->descriptortype, &val); + break; case UPB_WIRE_TYPE_32BIT: - return upb_decode_32bitfield(ptr, field, msg, d); + if (d->limit - ptr < 4) decode_err(d); + memcpy(&val, ptr, 4); + ptr += 4; + op = OP_SCALAR_LG2(2); + if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown; + break; case UPB_WIRE_TYPE_64BIT: - return upb_decode_64bitfield(ptr, field, msg, d); - case UPB_WIRE_TYPE_DELIMITED: - return upb_decode_delimitedfield(ptr, layout, field, msg, d); - case UPB_WIRE_TYPE_START_GROUP: { - const upb_msglayout *subl = layout->submsgs[field->submsg_index]; - upb_msg *group; - - if (field->label == UPB_LABEL_REPEATED) { - group = upb_addmsg(msg, field, subl, d); - } else { - group = upb_getorcreatemsg(msg, field, subl, d); + if (d->limit - ptr < 8) decode_err(d); + memcpy(&val, ptr, 8); + ptr += 8; + op = OP_SCALAR_LG2(3); + if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown; + break; + case UPB_WIRE_TYPE_DELIMITED: { + uint32_t size; + int ndx = field->descriptortype; + if (_upb_isrepeated(field)) ndx += 18; + ptr = decode_varint32(d, ptr, d->limit, &size); + if (size >= INT32_MAX || (size_t)(d->limit - ptr) < size) { + decode_err(d); /* Length overflow. */ } - - return upb_decode_groupfield(ptr, subl, field_number, group, d); + val.str_val.data = ptr; + val.str_val.size = size; + ptr += size; + op = delim_ops[ndx]; + break; } + case UPB_WIRE_TYPE_START_GROUP: + val.int32_val = field_number; + op = OP_SUBMSG; + if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown; + break; case UPB_WIRE_TYPE_END_GROUP: d->end_group = field_number; return ptr; default: - CHK(false); + decode_err(d); } - } else { - CHK(field_number != 0); - CHK(ptr = upb_skip_unknownfielddata(ptr, d, tag)); - CHK(ptr = upb_append_unknown(ptr, msg, d)); - return ptr; - } - UPB_UNREACHABLE(); -} -static const char *upb_decode_message(const char *ptr, const upb_msglayout *l, - upb_msg *msg, upb_decstate *d) { - while (ptr < d->limit) { - CHK(ptr = upb_decode_field(ptr, l, msg, d)); + if (op >= 0) { + /* Parse, using op for dispatch. */ + switch (field->label) { + case UPB_LABEL_REPEATED: + case _UPB_LABEL_PACKED: + ptr = decode_toarray(d, ptr, msg, layout, field, val, op); + break; + case _UPB_LABEL_MAP: + decode_tomap(d, msg, layout, field, val); + break; + default: + ptr = decode_tomsg(d, ptr, msg, layout, field, val, op); + break; + } + } else { + unknown: + /* Skip unknown field. */ + if (field_number == 0) decode_err(d); + if (wire_type == UPB_WIRE_TYPE_START_GROUP) { + ptr = decode_group(d, ptr, NULL, NULL, field_number); + } + if (msg) { + if (!_upb_msg_addunknown(msg, field_start, ptr - field_start, + d->arena)) { + decode_err(d); + } + } + } } + if (ptr != d->limit) decode_err(d); return ptr; } @@ -622,12 +559,16 @@ bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l, state.depth = 64; state.end_group = 0; - /* Early exit required for buf==NULL case. */ + if (setjmp(state.err)) return false; + if (size == 0) return true; + decode_msg(&state, buf, msg, l); - CHK(upb_decode_message(buf, l, msg, &state)); return state.end_group == 0; } -#undef CHK -#undef PTR_AT +#undef OP_SCALAR_LG2 +#undef OP_FIXPCK_LG2 +#undef OP_VARPCK_LG2 +#undef OP_STRING +#undef OP_SUBMSG diff --git a/upb/def.c b/upb/def.c index f1b477bdc90..50dccd8ff1e 100644 --- a/upb/def.c +++ b/upb/def.c @@ -49,6 +49,7 @@ struct upb_fielddef { bool is_extension_; bool lazy_; bool packed_; + bool proto3_optional_; upb_descriptortype_t type_; upb_label_t label_; }; @@ -68,6 +69,7 @@ struct upb_msgdef { const upb_oneofdef *oneofs; int field_count; int oneof_count; + int real_oneof_count; /* Is this a map-entry message? */ bool map_entry; @@ -239,11 +241,14 @@ static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { return ret; } +static void upb_status_setoom(upb_status *status) { + upb_status_seterrmsg(status, "out of memory"); +} + static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the * lowest indexes, but we do not publicly guarantee this. */ upb_msg_field_iter j; - upb_msg_oneof_iter k; int i; uint32_t selector; int n = upb_msgdef_numfields(m); @@ -284,14 +289,38 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { } m->selector_count = selector; - for(upb_msg_oneof_begin(&k, m), i = 0; - !upb_msg_oneof_done(&k); - upb_msg_oneof_next(&k), i++) { - upb_oneofdef *o = (upb_oneofdef*)upb_msg_iter_oneof(&k); - o->index = i; + upb_gfree(fields); + return true; +} + +static bool check_oneofs(upb_msgdef *m, upb_status *s) { + int i; + int first_synthetic = -1; + upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs; + + for (i = 0; i < m->oneof_count; i++) { + mutable_oneofs[i].index = i; + + if (upb_oneofdef_issynthetic(&mutable_oneofs[i])) { + if (first_synthetic == -1) { + first_synthetic = i; + } + } else { + if (first_synthetic != -1) { + upb_status_seterrf( + s, "Synthetic oneofs must be after all other oneofs: %s", + upb_oneofdef_name(&mutable_oneofs[i])); + return false; + } + } + } + + if (first_synthetic == -1) { + m->real_oneof_count = m->oneof_count; + } else { + m->real_oneof_count = first_synthetic; } - upb_gfree(fields); return true; } @@ -476,6 +505,10 @@ uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) { return f->selector_base; } +const upb_filedef *upb_fielddef_file(const upb_fielddef *f) { + return f->file; +} + const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) { return f->msgdef; } @@ -484,6 +517,11 @@ const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) { return f->oneof; } +const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) { + if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL; + return f->oneof; +} + static void chkdefaulttype(const upb_fielddef *f, int ctype) { UPB_UNUSED(f); UPB_UNUSED(ctype); @@ -539,13 +577,11 @@ const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) { } const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) { - UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_MESSAGE); - return f->sub.msgdef; + return upb_fielddef_type(f) == UPB_TYPE_MESSAGE ? f->sub.msgdef : NULL; } const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) { - UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_ENUM); - return f->sub.enumdef; + return upb_fielddef_type(f) == UPB_TYPE_ENUM ? f->sub.enumdef : NULL; } const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) { @@ -580,9 +616,8 @@ bool upb_fielddef_hassubdef(const upb_fielddef *f) { bool upb_fielddef_haspresence(const upb_fielddef *f) { if (upb_fielddef_isseq(f)) return false; - if (upb_fielddef_issubmsg(f)) return true; - if (upb_fielddef_containingoneof(f)) return true; - return f->file->syntax == UPB_SYNTAX_PROTO2; + return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) || + f->file->syntax == UPB_SYNTAX_PROTO2; } static bool between(int32_t x, int32_t low, int32_t high) { @@ -687,6 +722,10 @@ int upb_msgdef_numoneofs(const upb_msgdef *m) { return m->oneof_count; } +int upb_msgdef_numrealoneofs(const upb_msgdef *m) { + return m->real_oneof_count; +} + const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) { return m->layout; } @@ -710,6 +749,12 @@ bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) { type <= UPB_WELLKNOWN_UINT32VALUE; } +bool upb_msgdef_iswrapper(const upb_msgdef *m) { + upb_wellknowntype_t type = upb_msgdef_wellknowntype(m); + return type >= UPB_WELLKNOWN_DOUBLEVALUE && + type <= UPB_WELLKNOWN_BOOLVALUE; +} + void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) { upb_inttable_begin(iter, &m->itof); } @@ -785,6 +830,16 @@ uint32_t upb_oneofdef_index(const upb_oneofdef *o) { return o->index; } +bool upb_oneofdef_issynthetic(const upb_oneofdef *o) { + upb_inttable_iter iter; + const upb_fielddef *f; + upb_inttable_begin(&iter, &o->itof); + if (upb_oneofdef_numfields(o) != 1) return false; + f = upb_value_getptr(upb_inttable_iter_value(&iter)); + UPB_ASSERT(f); + return f->proto3_optional_; +} + const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, const char *name, size_t length) { upb_value val; @@ -820,16 +875,6 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter) { /* Dynamic Layout Generation. *************************************************/ -static bool is_power_of_two(size_t val) { - return (val & (val - 1)) == 0; -} - -/* Align up to the given power of 2. */ -static size_t align_up(size_t val, size_t align) { - UPB_ASSERT(is_power_of_two(align)); - return (val + align - 1) & ~(align - 1); -} - static size_t div_round_up(size_t n, size_t d) { return (n + d - 1) / d; } @@ -871,7 +916,7 @@ static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) { static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) { uint32_t ret; - l->size = align_up(l->size, size); + l->size = UPB_ALIGN_UP(l->size, size); ret = l->size; l->size += size; return ret; @@ -926,7 +971,8 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { } l->field_count = 2; - l->size = 2 * sizeof(upb_strview);align_up(l->size, 8); + l->size = 2 * sizeof(upb_strview); + l->size = UPB_ALIGN_UP(l->size, 8); return true; } @@ -952,7 +998,9 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { field->label = upb_fielddef_label(f); if (upb_fielddef_ismap(f)) { - field->label = UPB_LABEL_MAP; + field->label = _UPB_LABEL_MAP; + } else if (upb_fielddef_packed(f)) { + field->label = _UPB_LABEL_PACKED; } /* TODO: we probably should sort the fields by field number to match the @@ -965,7 +1013,7 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { submsgs[field->submsg_index] = subm->layout; } - if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { + if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) { /* We don't use hasbit 0, so that 0 can indicate "no presence" in the * table. This wastes one hasbit, but we don't worry about it for now. */ field->presence = ++hasbit; @@ -984,7 +1032,7 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { size_t field_size = upb_msg_fielddefsize(f); size_t index = upb_fielddef_index(f); - if (upb_fielddef_containingoneof(f)) { + if (upb_fielddef_realcontainingoneof(f)) { /* Oneofs are handled separately below. */ continue; } @@ -1004,6 +1052,8 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { uint32_t case_offset; uint32_t data_offset; + if (upb_oneofdef_issynthetic(o)) continue; + /* Calculate field size: the max of all field sizes. */ for (upb_oneof_begin(&fit, o); !upb_oneof_done(&fit); @@ -1027,7 +1077,7 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { /* Size of the entire structure should be a multiple of its greatest * alignment. TODO: track overall alignment for real? */ - l->size = align_up(l->size, 8); + l->size = UPB_ALIGN_UP(l->size, 8); return true; } @@ -1145,7 +1195,7 @@ static bool resolvename(const upb_strtable *t, const upb_fielddef *f, const char *base, upb_strview sym, upb_deftype_t type, upb_status *status, const void **def) { - if(sym.size == 0) return NULL; + if(sym.size == 0) return false; if(sym.data[0] == '.') { /* Symbols starting with '.' are absolute, so we do a single lookup. * Slice to omit the leading '.' */ @@ -1433,6 +1483,8 @@ static bool create_fielddef( f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto); f->number_ = field_number; f->oneof = NULL; + f->proto3_optional_ = + google_protobuf_FieldDescriptorProto_proto3_optional(field_proto); /* We can't resolve the subdef or (in the case of extensions) the containing * message yet, because it may not have been defined yet. We stash a pointer @@ -1609,6 +1661,7 @@ static bool create_msgdef(symtab_addctx *ctx, const char *prefix, } CHK(assign_msg_indices(m, ctx->status)); + CHK(check_oneofs(m, ctx->status)); assign_msg_wellknowntype(m); upb_inttable_compact2(&m->itof, ctx->alloc); @@ -1993,6 +2046,13 @@ const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) : NULL; } +const upb_filedef *upb_symtab_lookupfile2( + const upb_symtab *s, const char *name, size_t len) { + upb_value v; + return upb_strtable_lookup2(&s->files, name, len, &v) ? + upb_value_getconstptr(v) : NULL; +} + int upb_symtab_filecount(const upb_symtab *s) { return (int)upb_strtable_count(&s->files); } diff --git a/upb/def.h b/upb/def.h index 48e113dffee..a7ce5d0b3c7 100644 --- a/upb/def.h +++ b/upb/def.h @@ -2,16 +2,13 @@ ** Defs are upb's internal representation of the constructs that can appear ** in a .proto file: ** -** - upb::MessageDefPtr (upb_msgdef): describes a "message" construct. -** - upb::FieldDefPtr (upb_fielddef): describes a message field. -** - upb::FileDefPtr (upb_filedef): describes a .proto file and its defs. -** - upb::EnumDefPtr (upb_enumdef): describes an enum. -** - upb::OneofDefPtr (upb_oneofdef): describes a oneof. +** - upb_msgdef: describes a "message" construct. +** - upb_fielddef: describes a message field. +** - upb_filedef: describes a .proto file and its defs. +** - upb_enumdef: describes an enum. +** - upb_oneofdef: describes a oneof. ** ** TODO: definitions of services. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. */ #ifndef UPB_DEF_H_ @@ -21,24 +18,12 @@ #include "upb/table.int.h" #include "google/protobuf/descriptor.upb.h" -#ifdef __cplusplus -#include -#include -#include -#include - -namespace upb { -class EnumDefPtr; -class FieldDefPtr; -class FileDefPtr; -class MessageDefPtr; -class OneofDefPtr; -class SymbolTable; -} -#endif - #include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + struct upb_enumdef; typedef struct upb_enumdef upb_enumdef; struct upb_fielddef; @@ -89,10 +74,6 @@ typedef enum { * protobuf wire format. */ #define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) -#ifdef __cplusplus -extern "C" { -#endif - const char *upb_fielddef_fullname(const upb_fielddef *f); upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f); upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f); @@ -103,8 +84,10 @@ const char *upb_fielddef_jsonname(const upb_fielddef *f); bool upb_fielddef_isextension(const upb_fielddef *f); bool upb_fielddef_lazy(const upb_fielddef *f); bool upb_fielddef_packed(const upb_fielddef *f); +const upb_filedef *upb_fielddef_file(const upb_fielddef *f); const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); +const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f); uint32_t upb_fielddef_index(const upb_fielddef *f); bool upb_fielddef_issubmsg(const upb_fielddef *f); bool upb_fielddef_isstring(const upb_fielddef *f); @@ -128,129 +111,15 @@ const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f); /* Internal only. */ uint32_t upb_fielddef_selectorbase(const upb_fielddef *f); -#ifdef __cplusplus -} /* extern "C" */ - -/* A upb_fielddef describes a single field in a message. It is most often - * found as a part of a upb_msgdef, but can also stand alone to represent - * an extension. */ -class upb::FieldDefPtr { - public: - FieldDefPtr() : ptr_(nullptr) {} - explicit FieldDefPtr(const upb_fielddef *ptr) : ptr_(ptr) {} - - const upb_fielddef* ptr() const { return ptr_; } - explicit operator bool() const { return ptr_ != nullptr; } - - typedef upb_fieldtype_t Type; - typedef upb_label_t Label; - typedef upb_descriptortype_t DescriptorType; - - const char* full_name() const { return upb_fielddef_fullname(ptr_); } - - Type type() const { return upb_fielddef_type(ptr_); } - Label label() const { return upb_fielddef_label(ptr_); } - const char* name() const { return upb_fielddef_name(ptr_); } - const char* json_name() const { return upb_fielddef_jsonname(ptr_); } - uint32_t number() const { return upb_fielddef_number(ptr_); } - bool is_extension() const { return upb_fielddef_isextension(ptr_); } - - /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false, - * indicates whether this field should have lazy parsing handlers that yield - * the unparsed string for the submessage. - * - * TODO(haberman): I think we want to move this into a FieldOptions container - * when we add support for custom options (the FieldOptions struct will - * contain both regular FieldOptions like "lazy" *and* custom options). */ - bool lazy() const { return upb_fielddef_lazy(ptr_); } - - /* For non-string, non-submessage fields, this indicates whether binary - * protobufs are encoded in packed or non-packed format. - * - * TODO(haberman): see note above about putting options like this into a - * FieldOptions container. */ - bool packed() const { return upb_fielddef_packed(ptr_); } - - /* An integer that can be used as an index into an array of fields for - * whatever message this field belongs to. Guaranteed to be less than - * f->containing_type()->field_count(). May only be accessed once the def has - * been finalized. */ - uint32_t index() const { return upb_fielddef_index(ptr_); } - - /* The MessageDef to which this field belongs. - * - * If this field has been added to a MessageDef, that message can be retrieved - * directly (this is always the case for frozen FieldDefs). - * - * If the field has not yet been added to a MessageDef, you can set the name - * of the containing type symbolically instead. This is mostly useful for - * extensions, where the extension is declared separately from the message. */ - MessageDefPtr containing_type() const; - - /* The OneofDef to which this field belongs, or NULL if this field is not part - * of a oneof. */ - OneofDefPtr containing_oneof() const; - - /* The field's type according to the enum in descriptor.proto. This is not - * the same as UPB_TYPE_*, because it distinguishes between (for example) - * INT32 and SINT32, whereas our "type" enum does not. This return of - * descriptor_type() is a function of type(), integer_format(), and - * is_tag_delimited(). */ - DescriptorType descriptor_type() const { - return upb_fielddef_descriptortype(ptr_); - } - - /* Convenient field type tests. */ - bool IsSubMessage() const { return upb_fielddef_issubmsg(ptr_); } - bool IsString() const { return upb_fielddef_isstring(ptr_); } - bool IsSequence() const { return upb_fielddef_isseq(ptr_); } - bool IsPrimitive() const { return upb_fielddef_isprimitive(ptr_); } - bool IsMap() const { return upb_fielddef_ismap(ptr_); } - - /* Returns the non-string default value for this fielddef, which may either - * be something the client set explicitly or the "default default" (0 for - * numbers, empty for strings). The field's type indicates the type of the - * returned value, except for enum fields that are still mutable. - * - * Requires that the given function matches the field's current type. */ - int64_t default_int64() const { return upb_fielddef_defaultint64(ptr_); } - int32_t default_int32() const { return upb_fielddef_defaultint32(ptr_); } - uint64_t default_uint64() const { return upb_fielddef_defaultuint64(ptr_); } - uint32_t default_uint32() const { return upb_fielddef_defaultuint32(ptr_); } - bool default_bool() const { return upb_fielddef_defaultbool(ptr_); } - float default_float() const { return upb_fielddef_defaultfloat(ptr_); } - double default_double() const { return upb_fielddef_defaultdouble(ptr_); } - - /* The resulting string is always NULL-terminated. If non-NULL, the length - * will be stored in *len. */ - const char *default_string(size_t * len) const { - return upb_fielddef_defaultstr(ptr_, len); - } - - /* Returns the enum or submessage def for this field, if any. The field's - * type must match (ie. you may only call enum_subdef() for fields where - * type() == UPB_TYPE_ENUM). */ - EnumDefPtr enum_subdef() const; - MessageDefPtr message_subdef() const; - - private: - const upb_fielddef *ptr_; -}; - -#endif /* __cplusplus */ - /* upb_oneofdef ***************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - typedef upb_inttable_iter upb_oneof_iter; const char *upb_oneofdef_name(const upb_oneofdef *o); const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); int upb_oneofdef_numfields(const upb_oneofdef *o); uint32_t upb_oneofdef_index(const upb_oneofdef *o); +bool upb_oneofdef_issynthetic(const upb_oneofdef *o); /* Oneof lookups: * - ntof: look up a field by name. @@ -277,92 +146,6 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter); bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1, const upb_oneof_iter *iter2); -#ifdef __cplusplus -} /* extern "C" */ - -/* Class that represents a oneof. */ -class upb::OneofDefPtr { - public: - OneofDefPtr() : ptr_(nullptr) {} - explicit OneofDefPtr(const upb_oneofdef *ptr) : ptr_(ptr) {} - - const upb_oneofdef* ptr() const { return ptr_; } - explicit operator bool() { return ptr_ != nullptr; } - - /* Returns the MessageDef that owns this OneofDef. */ - MessageDefPtr containing_type() const; - - /* Returns the name of this oneof. This is the name used to look up the oneof - * by name once added to a message def. */ - const char* name() const { return upb_oneofdef_name(ptr_); } - - /* Returns the number of fields currently defined in the oneof. */ - int field_count() const { return upb_oneofdef_numfields(ptr_); } - - /* Looks up by name. */ - FieldDefPtr FindFieldByName(const char *name, size_t len) const { - return FieldDefPtr(upb_oneofdef_ntof(ptr_, name, len)); - } - FieldDefPtr FindFieldByName(const char* name) const { - return FieldDefPtr(upb_oneofdef_ntofz(ptr_, name)); - } - - template - FieldDefPtr FindFieldByName(const T& str) const { - return FindFieldByName(str.c_str(), str.size()); - } - - /* Looks up by tag number. */ - FieldDefPtr FindFieldByNumber(uint32_t num) const { - return FieldDefPtr(upb_oneofdef_itof(ptr_, num)); - } - - class const_iterator - : public std::iterator { - public: - void operator++() { upb_oneof_next(&iter_); } - - FieldDefPtr operator*() const { - return FieldDefPtr(upb_oneof_iter_field(&iter_)); - } - - bool operator!=(const const_iterator& other) const { - return !upb_oneof_iter_isequal(&iter_, &other.iter_); - } - - bool operator==(const const_iterator& other) const { - return upb_oneof_iter_isequal(&iter_, &other.iter_); - } - - private: - friend class OneofDefPtr; - - const_iterator() {} - explicit const_iterator(OneofDefPtr o) { - upb_oneof_begin(&iter_, o.ptr()); - } - static const_iterator end() { - const_iterator iter; - upb_oneof_iter_setdone(&iter.iter_); - return iter; - } - - upb_oneof_iter iter_; - }; - - const_iterator begin() const { return const_iterator(*this); } - const_iterator end() const { return const_iterator::end(); } - - private: - const upb_oneofdef *ptr_; -}; - -inline upb::OneofDefPtr upb::FieldDefPtr::containing_oneof() const { - return OneofDefPtr(upb_fielddef_containingoneof(ptr_)); -} - -#endif /* __cplusplus */ - /* upb_msgdef *****************************************************************/ typedef upb_inttable_iter upb_msg_field_iter; @@ -384,26 +167,22 @@ typedef upb_strtable_iter upb_msg_oneof_iter; #define UPB_TIMESTAMP_SECONDS 1 #define UPB_TIMESTAMP_NANOS 2 -#ifdef __cplusplus -extern "C" { -#endif - const char *upb_msgdef_fullname(const upb_msgdef *m); const upb_filedef *upb_msgdef_file(const upb_msgdef *m); const char *upb_msgdef_name(const upb_msgdef *m); +int upb_msgdef_numfields(const upb_msgdef *m); int upb_msgdef_numoneofs(const upb_msgdef *m); +int upb_msgdef_numrealoneofs(const upb_msgdef *m); upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m); bool upb_msgdef_mapentry(const upb_msgdef *m); upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m); +bool upb_msgdef_iswrapper(const upb_msgdef *m); bool upb_msgdef_isnumberwrapper(const upb_msgdef *m); -bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax); const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i); const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, size_t len); const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, size_t len); -int upb_msgdef_numfields(const upb_msgdef *m); -int upb_msgdef_numoneofs(const upb_msgdef *m); const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m); const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i); @@ -468,194 +247,6 @@ void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter); bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, const upb_msg_oneof_iter *iter2); -#ifdef __cplusplus -} /* extern "C" */ - -/* Structure that describes a single .proto message type. */ -class upb::MessageDefPtr { - public: - MessageDefPtr() : ptr_(nullptr) {} - explicit MessageDefPtr(const upb_msgdef *ptr) : ptr_(ptr) {} - - const upb_msgdef *ptr() const { return ptr_; } - explicit operator bool() const { return ptr_ != nullptr; } - - const char* full_name() const { return upb_msgdef_fullname(ptr_); } - const char* name() const { return upb_msgdef_name(ptr_); } - - /* The number of fields that belong to the MessageDef. */ - int field_count() const { return upb_msgdef_numfields(ptr_); } - - /* The number of oneofs that belong to the MessageDef. */ - int oneof_count() const { return upb_msgdef_numoneofs(ptr_); } - - upb_syntax_t syntax() const { return upb_msgdef_syntax(ptr_); } - - /* These return null pointers if the field is not found. */ - FieldDefPtr FindFieldByNumber(uint32_t number) const { - return FieldDefPtr(upb_msgdef_itof(ptr_, number)); - } - FieldDefPtr FindFieldByName(const char* name, size_t len) const { - return FieldDefPtr(upb_msgdef_ntof(ptr_, name, len)); - } - FieldDefPtr FindFieldByName(const char *name) const { - return FieldDefPtr(upb_msgdef_ntofz(ptr_, name)); - } - - template - FieldDefPtr FindFieldByName(const T& str) const { - return FindFieldByName(str.c_str(), str.size()); - } - - OneofDefPtr FindOneofByName(const char* name, size_t len) const { - return OneofDefPtr(upb_msgdef_ntoo(ptr_, name, len)); - } - - OneofDefPtr FindOneofByName(const char *name) const { - return OneofDefPtr(upb_msgdef_ntooz(ptr_, name)); - } - - template - OneofDefPtr FindOneofByName(const T &str) const { - return FindOneofByName(str.c_str(), str.size()); - } - - /* Is this message a map entry? */ - bool mapentry() const { return upb_msgdef_mapentry(ptr_); } - - /* Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for - * non-well-known message. */ - upb_wellknowntype_t wellknowntype() const { - return upb_msgdef_wellknowntype(ptr_); - } - - /* Whether is a number wrapper. */ - bool isnumberwrapper() const { return upb_msgdef_isnumberwrapper(ptr_); } - - /* Iteration over fields. The order is undefined. */ - class const_field_iterator - : public std::iterator { - public: - void operator++() { upb_msg_field_next(&iter_); } - - FieldDefPtr operator*() const { - return FieldDefPtr(upb_msg_iter_field(&iter_)); - } - - bool operator!=(const const_field_iterator &other) const { - return !upb_msg_field_iter_isequal(&iter_, &other.iter_); - } - - bool operator==(const const_field_iterator &other) const { - return upb_msg_field_iter_isequal(&iter_, &other.iter_); - } - - private: - friend class MessageDefPtr; - - explicit const_field_iterator() {} - - explicit const_field_iterator(MessageDefPtr msg) { - upb_msg_field_begin(&iter_, msg.ptr()); - } - - static const_field_iterator end() { - const_field_iterator iter; - upb_msg_field_iter_setdone(&iter.iter_); - return iter; - } - - upb_msg_field_iter iter_; - }; - - /* Iteration over oneofs. The order is undefined. */ - class const_oneof_iterator - : public std::iterator { - public: - - void operator++() { upb_msg_oneof_next(&iter_); } - - OneofDefPtr operator*() const { - return OneofDefPtr(upb_msg_iter_oneof(&iter_)); - } - - bool operator!=(const const_oneof_iterator& other) const { - return !upb_msg_oneof_iter_isequal(&iter_, &other.iter_); - } - - bool operator==(const const_oneof_iterator &other) const { - return upb_msg_oneof_iter_isequal(&iter_, &other.iter_); - } - - private: - friend class MessageDefPtr; - - const_oneof_iterator() {} - - explicit const_oneof_iterator(MessageDefPtr msg) { - upb_msg_oneof_begin(&iter_, msg.ptr()); - } - - static const_oneof_iterator end() { - const_oneof_iterator iter; - upb_msg_oneof_iter_setdone(&iter.iter_); - return iter; - } - - upb_msg_oneof_iter iter_; - }; - - class ConstFieldAccessor { - public: - explicit ConstFieldAccessor(const upb_msgdef* md) : md_(md) {} - const_field_iterator begin() { return MessageDefPtr(md_).field_begin(); } - const_field_iterator end() { return MessageDefPtr(md_).field_end(); } - private: - const upb_msgdef* md_; - }; - - class ConstOneofAccessor { - public: - explicit ConstOneofAccessor(const upb_msgdef* md) : md_(md) {} - const_oneof_iterator begin() { return MessageDefPtr(md_).oneof_begin(); } - const_oneof_iterator end() { return MessageDefPtr(md_).oneof_end(); } - private: - const upb_msgdef* md_; - }; - - const_field_iterator field_begin() const { - return const_field_iterator(*this); - } - - const_field_iterator field_end() const { return const_field_iterator::end(); } - - const_oneof_iterator oneof_begin() const { - return const_oneof_iterator(*this); - } - - const_oneof_iterator oneof_end() const { return const_oneof_iterator::end(); } - - ConstFieldAccessor fields() const { return ConstFieldAccessor(ptr()); } - ConstOneofAccessor oneofs() const { return ConstOneofAccessor(ptr()); } - - private: - const upb_msgdef* ptr_; -}; - -inline upb::MessageDefPtr upb::FieldDefPtr::message_subdef() const { - return MessageDefPtr(upb_fielddef_msgsubdef(ptr_)); -} - -inline upb::MessageDefPtr upb::FieldDefPtr::containing_type() const { - return MessageDefPtr(upb_fielddef_containingtype(ptr_)); -} - -inline upb::MessageDefPtr upb::OneofDefPtr::containing_type() const { - return MessageDefPtr(upb_oneofdef_containingtype(ptr_)); -} - -#endif /* __cplusplus */ - /* upb_enumdef ****************************************************************/ typedef upb_strtable_iter upb_enum_iter; @@ -690,75 +281,8 @@ bool upb_enum_done(upb_enum_iter *iter); const char *upb_enum_iter_name(upb_enum_iter *iter); int32_t upb_enum_iter_number(upb_enum_iter *iter); -#ifdef __cplusplus - -class upb::EnumDefPtr { - public: - EnumDefPtr() : ptr_(nullptr) {} - explicit EnumDefPtr(const upb_enumdef* ptr) : ptr_(ptr) {} - - const upb_enumdef* ptr() const { return ptr_; } - explicit operator bool() const { return ptr_ != nullptr; } - - const char* full_name() const { return upb_enumdef_fullname(ptr_); } - const char* name() const { return upb_enumdef_name(ptr_); } - - /* The value that is used as the default when no field default is specified. - * If not set explicitly, the first value that was added will be used. - * The default value must be a member of the enum. - * Requires that value_count() > 0. */ - int32_t default_value() const { return upb_enumdef_default(ptr_); } - - /* Returns the number of values currently defined in the enum. Note that - * multiple names can refer to the same number, so this may be greater than - * the total number of unique numbers. */ - int value_count() const { return upb_enumdef_numvals(ptr_); } - - /* Lookups from name to integer, returning true if found. */ - bool FindValueByName(const char *name, int32_t *num) const { - return upb_enumdef_ntoiz(ptr_, name, num); - } - - /* Finds the name corresponding to the given number, or NULL if none was - * found. If more than one name corresponds to this number, returns the - * first one that was added. */ - const char *FindValueByNumber(int32_t num) const { - return upb_enumdef_iton(ptr_, num); - } - - /* Iteration over name/value pairs. The order is undefined. - * Adding an enum val invalidates any iterators. - * - * TODO: make compatible with range-for, with elements as pairs? */ - class Iterator { - public: - explicit Iterator(EnumDefPtr e) { upb_enum_begin(&iter_, e.ptr()); } - - int32_t number() { return upb_enum_iter_number(&iter_); } - const char *name() { return upb_enum_iter_name(&iter_); } - bool Done() { return upb_enum_done(&iter_); } - void Next() { return upb_enum_next(&iter_); } - - private: - upb_enum_iter iter_; - }; - - private: - const upb_enumdef *ptr_; -}; - -inline upb::EnumDefPtr upb::FieldDefPtr::enum_subdef() const { - return EnumDefPtr(upb_fielddef_enumsubdef(ptr_)); -} - -#endif /* __cplusplus */ - /* upb_filedef ****************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - const char *upb_filedef_name(const upb_filedef *f); const char *upb_filedef_package(const upb_filedef *f); const char *upb_filedef_phpprefix(const upb_filedef *f); @@ -771,57 +295,8 @@ const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i); const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i); const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i); -#ifdef __cplusplus -} /* extern "C" */ - -/* Class that represents a .proto file with some things defined in it. - * - * Many users won't care about FileDefs, but they are necessary if you want to - * read the values of file-level options. */ -class upb::FileDefPtr { - public: - explicit FileDefPtr(const upb_filedef *ptr) : ptr_(ptr) {} - - const upb_filedef* ptr() const { return ptr_; } - explicit operator bool() const { return ptr_ != nullptr; } - - /* Get/set name of the file (eg. "foo/bar.proto"). */ - const char* name() const { return upb_filedef_name(ptr_); } - - /* Package name for definitions inside the file (eg. "foo.bar"). */ - const char* package() const { return upb_filedef_package(ptr_); } - - /* Sets the php class prefix which is prepended to all php generated classes - * from this .proto. Default is empty. */ - const char* phpprefix() const { return upb_filedef_phpprefix(ptr_); } - - /* Use this option to change the namespace of php generated classes. Default - * is empty. When this option is empty, the package name will be used for - * determining the namespace. */ - const char* phpnamespace() const { return upb_filedef_phpnamespace(ptr_); } - - /* Syntax for the file. Defaults to proto2. */ - upb_syntax_t syntax() const { return upb_filedef_syntax(ptr_); } - - /* Get the list of dependencies from the file. These are returned in the - * order that they were added to the FileDefPtr. */ - int dependency_count() const { return upb_filedef_depcount(ptr_); } - const FileDefPtr dependency(int index) const { - return FileDefPtr(upb_filedef_dep(ptr_, index)); - } - - private: - const upb_filedef* ptr_; -}; - -#endif /* __cplusplus */ - /* upb_symtab *****************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - upb_symtab *upb_symtab_new(void); void upb_symtab_free(upb_symtab* s); const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); @@ -829,6 +304,8 @@ const upb_msgdef *upb_symtab_lookupmsg2( const upb_symtab *s, const char *sym, size_t len); const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name); +const upb_filedef *upb_symtab_lookupfile2( + const upb_symtab *s, const char *name, size_t len); int upb_symtab_filecount(const upb_symtab *s); const upb_filedef *upb_symtab_addfile( upb_symtab *s, const google_protobuf_FileDescriptorProto *file, @@ -844,52 +321,10 @@ typedef struct upb_def_init { bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init); +#include "upb/port_undef.inc" + #ifdef __cplusplus } /* extern "C" */ - -/* Non-const methods in upb::SymbolTable are NOT thread-safe. */ -class upb::SymbolTable { - public: - SymbolTable() : ptr_(upb_symtab_new(), upb_symtab_free) {} - explicit SymbolTable(upb_symtab* s) : ptr_(s, upb_symtab_free) {} - - const upb_symtab* ptr() const { return ptr_.get(); } - upb_symtab* ptr() { return ptr_.get(); } - - /* Finds an entry in the symbol table with this exact name. If not found, - * returns NULL. */ - MessageDefPtr LookupMessage(const char *sym) const { - return MessageDefPtr(upb_symtab_lookupmsg(ptr_.get(), sym)); - } - - EnumDefPtr LookupEnum(const char *sym) const { - return EnumDefPtr(upb_symtab_lookupenum(ptr_.get(), sym)); - } - - FileDefPtr LookupFile(const char *name) const { - return FileDefPtr(upb_symtab_lookupfile(ptr_.get(), name)); - } - - /* TODO: iteration? */ - - /* Adds the given serialized FileDescriptorProto to the pool. */ - FileDefPtr AddFile(const google_protobuf_FileDescriptorProto *file_proto, - Status *status) { - return FileDefPtr( - upb_symtab_addfile(ptr_.get(), file_proto, status->ptr())); - } - - private: - std::unique_ptr ptr_; -}; - -UPB_INLINE const char* upb_safecstr(const std::string& str) { - UPB_ASSERT(str.size() == std::strlen(str.c_str())); - return str.c_str(); -} - #endif /* __cplusplus */ -#include "upb/port_undef.inc" - #endif /* UPB_DEF_H_ */ diff --git a/upb/def.hpp b/upb/def.hpp new file mode 100644 index 00000000000..62d06bba6d2 --- /dev/null +++ b/upb/def.hpp @@ -0,0 +1,525 @@ + +#ifndef UPB_DEF_HPP_ +#define UPB_DEF_HPP_ + +#include +#include +#include +#include + +#include "upb/def.h" +#include "upb/upb.hpp" + +namespace upb { + +class EnumDefPtr; +class MessageDefPtr; +class OneofDefPtr; + +// A upb::FieldDefPtr describes a single field in a message. It is most often +// found as a part of a upb_msgdef, but can also stand alone to represent +// an extension. +class FieldDefPtr { + public: + FieldDefPtr() : ptr_(nullptr) {} + explicit FieldDefPtr(const upb_fielddef* ptr) : ptr_(ptr) {} + + const upb_fielddef* ptr() const { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } + + typedef upb_fieldtype_t Type; + typedef upb_label_t Label; + typedef upb_descriptortype_t DescriptorType; + + const char* full_name() const { return upb_fielddef_fullname(ptr_); } + + Type type() const { return upb_fielddef_type(ptr_); } + Label label() const { return upb_fielddef_label(ptr_); } + const char* name() const { return upb_fielddef_name(ptr_); } + const char* json_name() const { return upb_fielddef_jsonname(ptr_); } + uint32_t number() const { return upb_fielddef_number(ptr_); } + bool is_extension() const { return upb_fielddef_isextension(ptr_); } + + // For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false, + // indicates whether this field should have lazy parsing handlers that yield + // the unparsed string for the submessage. + // + // TODO(haberman): I think we want to move this into a FieldOptions container + // when we add support for custom options (the FieldOptions struct will + // contain both regular FieldOptions like "lazy" *and* custom options). + bool lazy() const { return upb_fielddef_lazy(ptr_); } + + // For non-string, non-submessage fields, this indicates whether binary + // protobufs are encoded in packed or non-packed format. + // + // TODO(haberman): see note above about putting options like this into a + // FieldOptions container. + bool packed() const { return upb_fielddef_packed(ptr_); } + + // An integer that can be used as an index into an array of fields for + // whatever message this field belongs to. Guaranteed to be less than + // f->containing_type()->field_count(). May only be accessed once the def has + // been finalized. + uint32_t index() const { return upb_fielddef_index(ptr_); } + + // The MessageDef to which this field belongs. + // + // If this field has been added to a MessageDef, that message can be retrieved + // directly (this is always the case for frozen FieldDefs). + // + // If the field has not yet been added to a MessageDef, you can set the name + // of the containing type symbolically instead. This is mostly useful for + // extensions, where the extension is declared separately from the message. + MessageDefPtr containing_type() const; + + // The OneofDef to which this field belongs, or NULL if this field is not part + // of a oneof. + OneofDefPtr containing_oneof() const; + + // The field's type according to the enum in descriptor.proto. This is not + // the same as UPB_TYPE_*, because it distinguishes between (for example) + // INT32 and SINT32, whereas our "type" enum does not. This return of + // descriptor_type() is a function of type(), integer_format(), and + // is_tag_delimited(). + DescriptorType descriptor_type() const { + return upb_fielddef_descriptortype(ptr_); + } + + // Convenient field type tests. + bool IsSubMessage() const { return upb_fielddef_issubmsg(ptr_); } + bool IsString() const { return upb_fielddef_isstring(ptr_); } + bool IsSequence() const { return upb_fielddef_isseq(ptr_); } + bool IsPrimitive() const { return upb_fielddef_isprimitive(ptr_); } + bool IsMap() const { return upb_fielddef_ismap(ptr_); } + + // Returns the non-string default value for this fielddef, which may either + // be something the client set explicitly or the "default default" (0 for + // numbers, empty for strings). The field's type indicates the type of the + // returned value, except for enum fields that are still mutable. + // + // Requires that the given function matches the field's current type. + int64_t default_int64() const { return upb_fielddef_defaultint64(ptr_); } + int32_t default_int32() const { return upb_fielddef_defaultint32(ptr_); } + uint64_t default_uint64() const { return upb_fielddef_defaultuint64(ptr_); } + uint32_t default_uint32() const { return upb_fielddef_defaultuint32(ptr_); } + bool default_bool() const { return upb_fielddef_defaultbool(ptr_); } + float default_float() const { return upb_fielddef_defaultfloat(ptr_); } + double default_double() const { return upb_fielddef_defaultdouble(ptr_); } + + // The resulting string is always NULL-terminated. If non-NULL, the length + // will be stored in *len. + const char* default_string(size_t* len) const { + return upb_fielddef_defaultstr(ptr_, len); + } + + // Returns the enum or submessage def for this field, if any. The field's + // type must match (ie. you may only call enum_subdef() for fields where + // type() == UPB_TYPE_ENUM). + EnumDefPtr enum_subdef() const; + MessageDefPtr message_subdef() const; + + private: + const upb_fielddef* ptr_; +}; + +// Class that represents a oneof. +class OneofDefPtr { + public: + OneofDefPtr() : ptr_(nullptr) {} + explicit OneofDefPtr(const upb_oneofdef* ptr) : ptr_(ptr) {} + + const upb_oneofdef* ptr() const { return ptr_; } + explicit operator bool() { return ptr_ != nullptr; } + + // Returns the MessageDef that owns this OneofDef. + MessageDefPtr containing_type() const; + + // Returns the name of this oneof. This is the name used to look up the oneof + // by name once added to a message def. + const char* name() const { return upb_oneofdef_name(ptr_); } + + // Returns the number of fields currently defined in the oneof. + int field_count() const { return upb_oneofdef_numfields(ptr_); } + + // Looks up by name. + FieldDefPtr FindFieldByName(const char* name, size_t len) const { + return FieldDefPtr(upb_oneofdef_ntof(ptr_, name, len)); + } + FieldDefPtr FindFieldByName(const char* name) const { + return FieldDefPtr(upb_oneofdef_ntofz(ptr_, name)); + } + + template + FieldDefPtr FindFieldByName(const T& str) const { + return FindFieldByName(str.c_str(), str.size()); + } + + // Looks up by tag number. + FieldDefPtr FindFieldByNumber(uint32_t num) const { + return FieldDefPtr(upb_oneofdef_itof(ptr_, num)); + } + + class const_iterator + : public std::iterator { + public: + void operator++() { upb_oneof_next(&iter_); } + + FieldDefPtr operator*() const { + return FieldDefPtr(upb_oneof_iter_field(&iter_)); + } + + bool operator!=(const const_iterator& other) const { + return !upb_oneof_iter_isequal(&iter_, &other.iter_); + } + + bool operator==(const const_iterator& other) const { + return upb_oneof_iter_isequal(&iter_, &other.iter_); + } + + private: + friend class OneofDefPtr; + + const_iterator() {} + explicit const_iterator(OneofDefPtr o) { upb_oneof_begin(&iter_, o.ptr()); } + static const_iterator end() { + const_iterator iter; + upb_oneof_iter_setdone(&iter.iter_); + return iter; + } + + upb_oneof_iter iter_; + }; + + const_iterator begin() const { return const_iterator(*this); } + const_iterator end() const { return const_iterator::end(); } + + private: + const upb_oneofdef* ptr_; +}; + +// Structure that describes a single .proto message type. +class MessageDefPtr { + public: + MessageDefPtr() : ptr_(nullptr) {} + explicit MessageDefPtr(const upb_msgdef* ptr) : ptr_(ptr) {} + + const upb_msgdef* ptr() const { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } + + const char* full_name() const { return upb_msgdef_fullname(ptr_); } + const char* name() const { return upb_msgdef_name(ptr_); } + + // The number of fields that belong to the MessageDef. + int field_count() const { return upb_msgdef_numfields(ptr_); } + + // The number of oneofs that belong to the MessageDef. + int oneof_count() const { return upb_msgdef_numoneofs(ptr_); } + + upb_syntax_t syntax() const { return upb_msgdef_syntax(ptr_); } + + // These return null pointers if the field is not found. + FieldDefPtr FindFieldByNumber(uint32_t number) const { + return FieldDefPtr(upb_msgdef_itof(ptr_, number)); + } + FieldDefPtr FindFieldByName(const char* name, size_t len) const { + return FieldDefPtr(upb_msgdef_ntof(ptr_, name, len)); + } + FieldDefPtr FindFieldByName(const char* name) const { + return FieldDefPtr(upb_msgdef_ntofz(ptr_, name)); + } + + template + FieldDefPtr FindFieldByName(const T& str) const { + return FindFieldByName(str.c_str(), str.size()); + } + + OneofDefPtr FindOneofByName(const char* name, size_t len) const { + return OneofDefPtr(upb_msgdef_ntoo(ptr_, name, len)); + } + + OneofDefPtr FindOneofByName(const char* name) const { + return OneofDefPtr(upb_msgdef_ntooz(ptr_, name)); + } + + template + OneofDefPtr FindOneofByName(const T& str) const { + return FindOneofByName(str.c_str(), str.size()); + } + + // Is this message a map entry? + bool mapentry() const { return upb_msgdef_mapentry(ptr_); } + + // Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for + // non-well-known message. + upb_wellknowntype_t wellknowntype() const { + return upb_msgdef_wellknowntype(ptr_); + } + + // Whether is a number wrapper. + bool isnumberwrapper() const { return upb_msgdef_isnumberwrapper(ptr_); } + + // Iteration over fields. The order is undefined. + class const_field_iterator + : public std::iterator { + public: + void operator++() { upb_msg_field_next(&iter_); } + + FieldDefPtr operator*() const { + return FieldDefPtr(upb_msg_iter_field(&iter_)); + } + + bool operator!=(const const_field_iterator& other) const { + return !upb_msg_field_iter_isequal(&iter_, &other.iter_); + } + + bool operator==(const const_field_iterator& other) const { + return upb_msg_field_iter_isequal(&iter_, &other.iter_); + } + + private: + friend class MessageDefPtr; + + explicit const_field_iterator() {} + + explicit const_field_iterator(MessageDefPtr msg) { + upb_msg_field_begin(&iter_, msg.ptr()); + } + + static const_field_iterator end() { + const_field_iterator iter; + upb_msg_field_iter_setdone(&iter.iter_); + return iter; + } + + upb_msg_field_iter iter_; + }; + + // Iteration over oneofs. The order is undefined. + class const_oneof_iterator + : public std::iterator { + public: + void operator++() { upb_msg_oneof_next(&iter_); } + + OneofDefPtr operator*() const { + return OneofDefPtr(upb_msg_iter_oneof(&iter_)); + } + + bool operator!=(const const_oneof_iterator& other) const { + return !upb_msg_oneof_iter_isequal(&iter_, &other.iter_); + } + + bool operator==(const const_oneof_iterator& other) const { + return upb_msg_oneof_iter_isequal(&iter_, &other.iter_); + } + + private: + friend class MessageDefPtr; + + const_oneof_iterator() {} + + explicit const_oneof_iterator(MessageDefPtr msg) { + upb_msg_oneof_begin(&iter_, msg.ptr()); + } + + static const_oneof_iterator end() { + const_oneof_iterator iter; + upb_msg_oneof_iter_setdone(&iter.iter_); + return iter; + } + + upb_msg_oneof_iter iter_; + }; + + class ConstFieldAccessor { + public: + explicit ConstFieldAccessor(const upb_msgdef* md) : md_(md) {} + const_field_iterator begin() { return MessageDefPtr(md_).field_begin(); } + const_field_iterator end() { return MessageDefPtr(md_).field_end(); } + + private: + const upb_msgdef* md_; + }; + + class ConstOneofAccessor { + public: + explicit ConstOneofAccessor(const upb_msgdef* md) : md_(md) {} + const_oneof_iterator begin() { return MessageDefPtr(md_).oneof_begin(); } + const_oneof_iterator end() { return MessageDefPtr(md_).oneof_end(); } + + private: + const upb_msgdef* md_; + }; + + const_field_iterator field_begin() const { + return const_field_iterator(*this); + } + + const_field_iterator field_end() const { return const_field_iterator::end(); } + + const_oneof_iterator oneof_begin() const { + return const_oneof_iterator(*this); + } + + const_oneof_iterator oneof_end() const { return const_oneof_iterator::end(); } + + ConstFieldAccessor fields() const { return ConstFieldAccessor(ptr()); } + ConstOneofAccessor oneofs() const { return ConstOneofAccessor(ptr()); } + + private: + const upb_msgdef* ptr_; +}; + +class EnumDefPtr { + public: + EnumDefPtr() : ptr_(nullptr) {} + explicit EnumDefPtr(const upb_enumdef* ptr) : ptr_(ptr) {} + + const upb_enumdef* ptr() const { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } + + const char* full_name() const { return upb_enumdef_fullname(ptr_); } + const char* name() const { return upb_enumdef_name(ptr_); } + + // The value that is used as the default when no field default is specified. + // If not set explicitly, the first value that was added will be used. + // The default value must be a member of the enum. + // Requires that value_count() > 0. + int32_t default_value() const { return upb_enumdef_default(ptr_); } + + // Returns the number of values currently defined in the enum. Note that + // multiple names can refer to the same number, so this may be greater than + // the total number of unique numbers. + int value_count() const { return upb_enumdef_numvals(ptr_); } + + // Lookups from name to integer, returning true if found. + bool FindValueByName(const char* name, int32_t* num) const { + return upb_enumdef_ntoiz(ptr_, name, num); + } + + // Finds the name corresponding to the given number, or NULL if none was + // found. If more than one name corresponds to this number, returns the + // first one that was added. + const char* FindValueByNumber(int32_t num) const { + return upb_enumdef_iton(ptr_, num); + } + + // Iteration over name/value pairs. The order is undefined. + // Adding an enum val invalidates any iterators. + // + // TODO: make compatible with range-for, with elements as pairs? + class Iterator { + public: + explicit Iterator(EnumDefPtr e) { upb_enum_begin(&iter_, e.ptr()); } + + int32_t number() { return upb_enum_iter_number(&iter_); } + const char* name() { return upb_enum_iter_name(&iter_); } + bool Done() { return upb_enum_done(&iter_); } + void Next() { return upb_enum_next(&iter_); } + + private: + upb_enum_iter iter_; + }; + + private: + const upb_enumdef* ptr_; +}; + +// Class that represents a .proto file with some things defined in it. +// +// Many users won't care about FileDefs, but they are necessary if you want to +// read the values of file-level options. +class FileDefPtr { + public: + explicit FileDefPtr(const upb_filedef* ptr) : ptr_(ptr) {} + + const upb_filedef* ptr() const { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } + + // Get/set name of the file (eg. "foo/bar.proto"). + const char* name() const { return upb_filedef_name(ptr_); } + + // Package name for definitions inside the file (eg. "foo.bar"). + const char* package() const { return upb_filedef_package(ptr_); } + + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + const char* phpprefix() const { return upb_filedef_phpprefix(ptr_); } + + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + const char* phpnamespace() const { return upb_filedef_phpnamespace(ptr_); } + + // Syntax for the file. Defaults to proto2. + upb_syntax_t syntax() const { return upb_filedef_syntax(ptr_); } + + // Get the list of dependencies from the file. These are returned in the + // order that they were added to the FileDefPtr. + int dependency_count() const { return upb_filedef_depcount(ptr_); } + const FileDefPtr dependency(int index) const { + return FileDefPtr(upb_filedef_dep(ptr_, index)); + } + + private: + const upb_filedef* ptr_; +}; + +// Non-const methods in upb::SymbolTable are NOT thread-safe. +class SymbolTable { + public: + SymbolTable() : ptr_(upb_symtab_new(), upb_symtab_free) {} + explicit SymbolTable(upb_symtab* s) : ptr_(s, upb_symtab_free) {} + + const upb_symtab* ptr() const { return ptr_.get(); } + upb_symtab* ptr() { return ptr_.get(); } + + // Finds an entry in the symbol table with this exact name. If not found, + // returns NULL. + MessageDefPtr LookupMessage(const char* sym) const { + return MessageDefPtr(upb_symtab_lookupmsg(ptr_.get(), sym)); + } + + EnumDefPtr LookupEnum(const char* sym) const { + return EnumDefPtr(upb_symtab_lookupenum(ptr_.get(), sym)); + } + + FileDefPtr LookupFile(const char* name) const { + return FileDefPtr(upb_symtab_lookupfile(ptr_.get(), name)); + } + + // TODO: iteration? + + // Adds the given serialized FileDescriptorProto to the pool. + FileDefPtr AddFile(const google_protobuf_FileDescriptorProto* file_proto, + Status* status) { + return FileDefPtr( + upb_symtab_addfile(ptr_.get(), file_proto, status->ptr())); + } + + private: + std::unique_ptr ptr_; +}; + +inline MessageDefPtr FieldDefPtr::message_subdef() const { + return MessageDefPtr(upb_fielddef_msgsubdef(ptr_)); +} + +inline MessageDefPtr FieldDefPtr::containing_type() const { + return MessageDefPtr(upb_fielddef_containingtype(ptr_)); +} + +inline MessageDefPtr OneofDefPtr::containing_type() const { + return MessageDefPtr(upb_oneofdef_containingtype(ptr_)); +} + +inline OneofDefPtr FieldDefPtr::containing_oneof() const { + return OneofDefPtr(upb_fielddef_containingoneof(ptr_)); +} + +inline EnumDefPtr FieldDefPtr::enum_subdef() const { + return EnumDefPtr(upb_fielddef_enumsubdef(ptr_)); +} + +} // namespace upb + +#endif // UPB_DEF_HPP_ diff --git a/upb/encode.c b/upb/encode.c index d9adbff596f..28a5602b239 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -113,15 +113,14 @@ static bool upb_put_float(upb_encstate *e, float d) { static uint32_t upb_readcase(const char *msg, const upb_msglayout_field *f) { uint32_t ret; - uint32_t offset = ~f->presence; - memcpy(&ret, msg + offset, sizeof(ret)); + memcpy(&ret, msg - f->presence, sizeof(ret)); return ret; } static bool upb_readhasbit(const char *msg, const upb_msglayout_field *f) { uint32_t hasbit = f->presence; UPB_ASSERT(f->presence > 0); - return msg[hasbit / 8] & (1 << (hasbit % 8)); + return (*UPB_PTR_AT(msg, hasbit / 8, uint8_t)) & (1 << (hasbit % 8)); } static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) { @@ -129,10 +128,20 @@ 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; - const void* data = _upb_array_constptr(arr); - return upb_put_bytes(e, data, bytes) && upb_put_varint(e, bytes); + size_t elem_size, uint32_t tag) { + size_t bytes = arr->len * elem_size; + const char* data = _upb_array_constptr(arr); + const char* ptr = data + bytes - elem_size; + if (tag) { + while (true) { + CHK(upb_put_bytes(e, ptr, elem_size) && upb_put_varint(e, tag)); + if (ptr == data) break; + ptr -= elem_size; + } + return true; + } else { + return upb_put_bytes(e, data, bytes) && upb_put_varint(e, bytes); + } } bool upb_encode_message(upb_encstate *e, const char *msg, @@ -218,38 +227,46 @@ static bool upb_encode_array(upb_encstate *e, const char *field_mem, const upb_msglayout *m, const upb_msglayout_field *f) { const upb_array *arr = *(const upb_array**)field_mem; + bool packed = f->label == _UPB_LABEL_PACKED; if (arr == NULL || arr->len == 0) { return true; } -#define VARINT_CASE(ctype, encode) { \ - const ctype *start = _upb_array_constptr(arr); \ - const ctype *ptr = start + arr->len; \ - size_t pre_len = e->limit - e->ptr; \ - do { \ - ptr--; \ - CHK(upb_put_varint(e, encode)); \ - } while (ptr != start); \ - CHK(upb_put_varint(e, e->limit - e->ptr - pre_len)); \ -} \ -break; \ -do { ; } while(0) +#define VARINT_CASE(ctype, encode) \ + { \ + const ctype *start = _upb_array_constptr(arr); \ + const ctype *ptr = start + arr->len; \ + size_t pre_len = e->limit - e->ptr; \ + uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \ + do { \ + ptr--; \ + CHK(upb_put_varint(e, encode)); \ + if (tag) CHK(upb_put_varint(e, tag)); \ + } while (ptr != start); \ + if (!tag) CHK(upb_put_varint(e, e->limit - e->ptr - pre_len)); \ + } \ + break; \ + do { \ + ; \ + } while (0) + +#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type)) switch (f->descriptortype) { case UPB_DESCRIPTOR_TYPE_DOUBLE: - CHK(upb_put_fixedarray(e, arr, sizeof(double))); + CHK(upb_put_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT))); break; case UPB_DESCRIPTOR_TYPE_FLOAT: - CHK(upb_put_fixedarray(e, arr, sizeof(float))); + CHK(upb_put_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT))); break; case UPB_DESCRIPTOR_TYPE_SFIXED64: case UPB_DESCRIPTOR_TYPE_FIXED64: - CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t))); + CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT))); break; case UPB_DESCRIPTOR_TYPE_FIXED32: case UPB_DESCRIPTOR_TYPE_SFIXED32: - CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t))); + CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT))); break; case UPB_DESCRIPTOR_TYPE_INT64: case UPB_DESCRIPTOR_TYPE_UINT64: @@ -306,9 +323,9 @@ do { ; } while(0) } #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)); + if (packed) { + CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); + } return true; } @@ -362,9 +379,9 @@ bool upb_encode_message(upb_encstate *e, const char *msg, for (i = m->field_count - 1; i >= 0; i--) { const upb_msglayout_field *f = &m->fields[i]; - if (f->label == UPB_LABEL_REPEATED) { + if (_upb_isrepeated(f)) { CHK(upb_encode_array(e, msg + f->offset, m, f)); - } else if (f->label == UPB_LABEL_MAP) { + } else if (f->label == _UPB_LABEL_MAP) { CHK(upb_encode_map(e, msg + f->offset, m, f)); } else { bool skip_empty = false; diff --git a/upb/handlers.h b/upb/handlers.h index 2d2380b634b..9ed70e959c6 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -25,6 +25,7 @@ #include "upb/port_def.inc" #ifdef __cplusplus +#include "upb/def.hpp" namespace upb { class HandlersPtr; class HandlerCache; diff --git a/upb/json/parser.rl b/upb/json/parser.rl index 19022df298a..eccd53039ff 100644 --- a/upb/json/parser.rl +++ b/upb/json/parser.rl @@ -733,7 +733,9 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len, /* Note: this invalidates the accumulate buffer! Call only after reading its * contents. */ static void multipart_end(upb_json_parser *p) { - UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); + /* This is false sometimes. Probably a bug of some sort, but this code is + * intended for deletion soon. */ + /* UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); */ p->multipart_state = MULTIPART_INACTIVE; accumulate_clear(p); } @@ -1368,7 +1370,12 @@ static bool end_stringval_nontop(upb_json_parser *p) { upb_selector_t sel = parser_getsel(p); upb_sink_putint32(p->top->sink, sel, int_val); } else { - upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf); + if (p->ignore_json_unknown) { + ok = true; + /* TODO(teboring): Should also clean this field. */ + } else { + upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf); + } } break; @@ -1687,24 +1694,15 @@ static void start_timestamp_zone(upb_json_parser *p, const char *ptr) { capture_begin(p, ptr); } -static int div_round_up2(int n, int d) { - return (n + d - 1) / d; -} - /* epoch_days(1970, 1, 1) == 1970-01-01 == 0. */ static int epoch_days(int year, int month, int day) { static const uint16_t month_yday[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - int febs_since_0 = month > 2 ? year + 1 : year; - int leap_days_since_0 = div_round_up2(febs_since_0, 4) - - div_round_up2(febs_since_0, 100) + - div_round_up2(febs_since_0, 400); - int days_since_0 = - 365 * year + month_yday[month - 1] + (day - 1) + leap_days_since_0; - - /* Convert from 0-epoch (0001-01-01 BC) to Unix Epoch (1970-01-01 AD). - * Since the "BC" system does not have a year zero, 1 BC == year zero. */ - return days_since_0 - 719528; + uint32_t year_adj = year + 4800; /* Ensure positive year, multiple of 400. */ + uint32_t febs = year_adj - (month <= 2 ? 1 : 0); /* Februaries since base. */ + uint32_t leap_days = 1 + (febs / 4) - (febs / 100) + (febs / 400); + uint32_t days = 365 * year_adj + leap_days + month_yday[month - 1] + day - 1; + return days - 2472692; /* Adjust to Unix epoch. */ } static int64_t upb_timegm(const struct tm *tp) { @@ -2900,9 +2898,6 @@ upb_json_parser *upb_json_parser_create(upb_arena *arena, upb_sink output, upb_status *status, bool ignore_json_unknown) { -#ifndef NDEBUG - const size_t size_before = upb_arena_bytesallocated(arena); -#endif upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser)); if (!p) return false; @@ -2929,10 +2924,6 @@ upb_json_parser *upb_json_parser_create(upb_arena *arena, p->ignore_json_unknown = ignore_json_unknown; - /* If this fails, uncomment and increase the value in parser.h. */ - /* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */ - UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <= - UPB_JSON_PARSER_SIZE); return p; } diff --git a/upb/json/printer.c b/upb/json/printer.c index b0030e0e525..3a8821982f2 100644 --- a/upb/json/printer.c +++ b/upb/json/printer.c @@ -1367,10 +1367,6 @@ static void json_printer_reset(upb_json_printer *p) { upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h, upb_bytessink output) { -#ifndef NDEBUG - size_t size_before = upb_arena_bytesallocated(a); -#endif - upb_json_printer *p = upb_arena_malloc(a, sizeof(upb_json_printer)); if (!p) return NULL; @@ -1380,9 +1376,6 @@ upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h, p->seconds = 0; p->nanos = 0; - /* If this fails, increase the value in printer.h. */ - UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <= - UPB_JSON_PRINTER_SIZE); return p; } diff --git a/upb/json_decode.c b/upb/json_decode.c index 54a55ad135c..2949e2d237e 100644 --- a/upb/json_decode.c +++ b/upb/json_decode.c @@ -157,15 +157,11 @@ static void jsondec_push(jsondec *d) { } static bool jsondec_seqnext(jsondec *d, char end_ch) { + bool is_first = d->is_first; + d->is_first = false; jsondec_skipws(d); if (*d->ptr == end_ch) return false; - - if (d->is_first) { - d->is_first = false; - } else { - jsondec_parselit(d, ","); - } - + if (!is_first) jsondec_parselit(d, ","); return true; } @@ -405,7 +401,9 @@ static upb_strview jsondec_string(jsondec *d) { switch (ch) { case '"': { - upb_strview ret = {buf, end - buf}; + upb_strview ret; + ret.data = buf; + ret.size = end - buf; return ret; } case '\\': @@ -413,7 +411,7 @@ static upb_strview jsondec_string(jsondec *d) { if (*d->ptr == 'u') { d->ptr++; if (buf_end - end < 4) { - // Allow space for maximum-sized code point (4 bytes). + /* Allow space for maximum-sized code point (4 bytes). */ jsondec_resize(d, &buf, &end, &buf_end); } end += jsondec_unicode(d, end); @@ -770,7 +768,12 @@ static upb_msgval jsondec_enum(jsondec *d, const upb_fielddef *f) { upb_strview str = jsondec_string(d); upb_msgval val; if (!upb_enumdef_ntoi(e, str.data, str.size, &val.int32_val)) { - jsondec_err(d, "Unknown enumerator"); + if (d->options & UPB_JSONDEC_IGNOREUNKNOWN) { + val.int32_val = 0; + } else { + jsondec_errf(d, "Unknown enumerator: '" UPB_STRVIEW_FORMAT "'", + UPB_STRVIEW_ARGS(str)); + } } return val; } else { @@ -875,20 +878,22 @@ static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) { if (!f) { if ((d->options & UPB_JSONDEC_IGNOREUNKNOWN) == 0) { - jsondec_err(d, "Unknown field"); + jsondec_errf(d, "Unknown field: '" UPB_STRVIEW_FORMAT "'", + UPB_STRVIEW_ARGS(name)); } jsondec_skipval(d); return; } if (upb_fielddef_containingoneof(f) && - upb_msg_hasoneof(msg, upb_fielddef_containingoneof(f))) { + upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) { jsondec_err(d, "More than one field for this oneof."); } if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) { /* JSON "null" indicates a default value, so no need to set anything. */ - return jsondec_null(d); + jsondec_null(d); + return; } preserved = d->debug_field; @@ -912,7 +917,9 @@ static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) { static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m) { jsondec_objstart(d); - while (jsondec_objnext(d)) jsondec_field(d, msg, m); + while (jsondec_objnext(d)) { + jsondec_field(d, msg, m); + } jsondec_objend(d); } @@ -979,18 +986,16 @@ static int jsondec_nanos(jsondec *d, const char **ptr, const char *end) { return nanos; } -// jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0 -static int jsondec_epochdays(int y, int m, int d) { - unsigned year_base = 4800; /* Before minimum year, divisible by 100 & 400 */ - unsigned epoch = 2472632; /* Days between year_base and 1970 (Unix epoch) */ - unsigned carry = (unsigned)m - 3 > m; - unsigned m_adj = m - 3 + (carry ? 12 : 0); /* Month, counting from March */ - unsigned y_adj = y + year_base - carry; /* Year, positive and March-based */ - unsigned base_days = (365 * 4 + 1) * y_adj / 4; /* Approx days for year */ - unsigned centuries = y_adj / 100; - unsigned extra_leap_days = (3 * centuries + 3) / 4; /* base_days correction */ - unsigned year_days = (367 * (m_adj + 1)) / 12 - 30; /* Counting from March */ - return base_days - extra_leap_days + year_days + (d - 1) - epoch; +/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */ +int jsondec_epochdays(int y, int m, int d) { + const uint32_t year_base = 4800; /* Before min year, multiple of 400. */ + const uint32_t m_adj = m - 3; /* March-based month. */ + const uint32_t carry = m_adj > m ? 1 : 0; + const uint32_t adjust = carry ? 12 : 0; + const uint32_t y_adj = y + year_base - carry; + const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048; + const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400; + return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632; } static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) { @@ -1007,7 +1012,7 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) { if (str.size < 20) goto malformed; { - // 1972-01-01T01:00:00 + /* 1972-01-01T01:00:00 */ int year = jsondec_tsdigits(d, &ptr, 4, "-"); int mon = jsondec_tsdigits(d, &ptr, 2, "-"); int day = jsondec_tsdigits(d, &ptr, 2, "T"); @@ -1021,7 +1026,7 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) { nanos.int32_val = jsondec_nanos(d, &ptr, end); { - // [+-]08:00 or Z + /* [+-]08:00 or Z */ int ofs = 0; bool neg = false; @@ -1064,7 +1069,7 @@ static void jsondec_duration(jsondec *d, upb_msg *msg, const upb_msgdef *m) { const char *ptr = str.data; const char *end = ptr + str.size; - // "3.000000001s", "3s", etc. + /* "3.000000001s", "3s", etc. */ ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val); nanos.int32_val = jsondec_nanos(d, &ptr, end); @@ -1313,10 +1318,10 @@ static void jsondec_any(jsondec *d, upb_msg *msg, const upb_msgdef *m) { if (pre_type_data) { size_t len = pre_type_end - pre_type_data + 1; char *tmp = upb_arena_malloc(d->arena, len); - memcpy(tmp, pre_type_data, len - 1); - tmp[len - 1] = '}'; const char *saved_ptr = d->ptr; const char *saved_end = d->end; + memcpy(tmp, pre_type_data, len - 1); + tmp[len - 1] = '}'; d->ptr = tmp; d->end = tmp + len; d->is_first = true; @@ -1400,6 +1405,6 @@ bool upb_json_decode(const char *buf, size_t size, upb_msg *msg, if (setjmp(d.err)) return false; - jsondec_object(&d, msg, m); + jsondec_tomsg(&d, msg, m); return true; } diff --git a/upb/json_encode.c b/upb/json_encode.c index 285bcecea5f..04c9594ed7b 100644 --- a/upb/json_encode.c +++ b/upb/json_encode.c @@ -318,16 +318,16 @@ static void jsonenc_any(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) { jsonenc_err(e, "Error decoding message in Any"); } - jsonenc_putstr(e, "{\"@type\": "); + jsonenc_putstr(e, "{\"@type\":"); jsonenc_string(e, type_url); - jsonenc_putstr(e, ", "); + jsonenc_putstr(e, ","); if (upb_msgdef_wellknowntype(any_m) == UPB_WELLKNOWN_UNSPECIFIED) { - /* Regular messages: {"@type": "...", "foo": 1, "bar": 2} */ + /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */ jsonenc_msgfields(e, any, any_m); } else { - /* Well-known type: {"@type": "...", "value": } */ - jsonenc_putstr(e, "value: "); + /* Well-known type: {"@type": "...","value": } */ + jsonenc_putstr(e, "\"value\":"); jsonenc_msgfield(e, any, any_m); } @@ -393,14 +393,16 @@ static void jsonenc_struct(jsonenc *e, const upb_msg *msg, jsonenc_putstr(e, "{"); - while (upb_mapiter_next(fields, &iter)) { - upb_msgval key = upb_mapiter_key(fields, iter); - upb_msgval val = upb_mapiter_value(fields, iter); + if (fields) { + while (upb_mapiter_next(fields, &iter)) { + upb_msgval key = upb_mapiter_key(fields, iter); + upb_msgval val = upb_mapiter_value(fields, iter); - jsonenc_putsep(e, ", ", &first); - jsonenc_string(e, key.str_val); - jsonenc_putstr(e, ": "); - jsonenc_value(e, val.msg_val, upb_fielddef_msgsubdef(value_f)); + jsonenc_putsep(e, ",", &first); + jsonenc_string(e, key.str_val); + jsonenc_putstr(e, ":"); + jsonenc_value(e, val.msg_val, upb_fielddef_msgsubdef(value_f)); + } } jsonenc_putstr(e, "}"); @@ -411,17 +413,19 @@ static void jsonenc_listvalue(jsonenc *e, const upb_msg *msg, const upb_fielddef *values_f = upb_msgdef_itof(m, 1); const upb_msgdef *values_m = upb_fielddef_msgsubdef(values_f); const upb_array *values = upb_msg_get(msg, values_f).array_val; - const size_t size = upb_array_size(values); size_t i; bool first = true; jsonenc_putstr(e, "["); - for (i = 0; i < size; i++) { - upb_msgval elem = upb_array_get(values, i); + if (values) { + const size_t size = upb_array_size(values); + for (i = 0; i < size; i++) { + upb_msgval elem = upb_array_get(values, i); - jsonenc_putsep(e, ", ", &first); - jsonenc_value(e, elem.msg_val, values_m); + jsonenc_putsep(e, ",", &first); + jsonenc_value(e, elem.msg_val, values_m); + } } jsonenc_putstr(e, "]"); @@ -564,7 +568,7 @@ static void jsonenc_mapkey(jsonenc *e, upb_msgval val, const upb_fielddef *f) { UPB_UNREACHABLE(); } - jsonenc_putstr(e, "\": "); + jsonenc_putstr(e, "\":"); } static void jsonenc_array(jsonenc *e, const upb_array *arr, @@ -576,7 +580,7 @@ static void jsonenc_array(jsonenc *e, const upb_array *arr, jsonenc_putstr(e, "["); for (i = 0; i < size; i++) { - jsonenc_putsep(e, ", ", &first); + jsonenc_putsep(e, ",", &first); jsonenc_scalar(e, upb_array_get(arr, i), f); } @@ -593,7 +597,7 @@ static void jsonenc_map(jsonenc *e, const upb_map *map, const upb_fielddef *f) { jsonenc_putstr(e, "{"); while (upb_mapiter_next(map, &iter)) { - jsonenc_putsep(e, ", ", &first); + jsonenc_putsep(e, ",", &first); jsonenc_mapkey(e, upb_mapiter_key(map, iter), key_f); jsonenc_scalar(e, upb_mapiter_value(map, iter), val_f); } @@ -611,8 +615,8 @@ static void jsonenc_fieldval(jsonenc *e, const upb_fielddef *f, name = upb_fielddef_jsonname(f); } - jsonenc_putsep(e, ", ", first); - jsonenc_printf(e, "\"%s\": ", name); + jsonenc_putsep(e, ",", first); + jsonenc_printf(e, "\"%s\":", name); if (upb_fielddef_ismap(f)) { jsonenc_map(e, val.map_val, f); @@ -679,7 +683,7 @@ size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m, if (setjmp(e.err)) return -1; - jsonenc_msg(&e, msg, m); + jsonenc_msgfield(&e, msg, m); if (e.arena) upb_arena_free(e.arena); return jsonenc_nullz(&e, size); } diff --git a/upb/msg.c b/upb/msg.c index 8df9d7a1f76..fd6c59b0b2d 100644 --- a/upb/msg.c +++ b/upb/msg.c @@ -5,8 +5,6 @@ #include "upb/port_def.inc" -#define VOIDPTR_AT(msg, ofs) (void*)((char*)msg + (int)ofs) - /** upb_msg *******************************************************************/ static const char _upb_fieldtype_to_sizelg2[12] = { @@ -38,59 +36,52 @@ static size_t upb_msg_sizeof(const upb_msglayout *l) { } static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) { - return VOIDPTR_AT(msg, -sizeof(upb_msg_internal)); + return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal); } static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) { - return VOIDPTR_AT(msg, -sizeof(upb_msg_internal)); + return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal); } -static upb_msg_internal_withext *upb_msg_getinternalwithext( - upb_msg *msg, const upb_msglayout *l) { - UPB_ASSERT(l->extendable); - return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext)); +void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l) { + size_t internal = upb_msg_internalsize(l); + void *mem = UPB_PTR_AT(msg, -internal, char); + memset(mem, 0, l->size + internal); } upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) { - upb_alloc *alloc = upb_arena_alloc(a); - void *mem = upb_malloc(alloc, upb_msg_sizeof(l)); - upb_msg_internal *in; + void *mem = upb_arena_malloc(a, upb_msg_sizeof(l)); upb_msg *msg; if (!mem) { return NULL; } - msg = VOIDPTR_AT(mem, upb_msg_internalsize(l)); - - /* Initialize normal members. */ - memset(msg, 0, l->size); - - /* Initialize internal members. */ - in = upb_msg_getinternal(msg); - in->unknown = NULL; - in->unknown_len = 0; - in->unknown_size = 0; - - if (l->extendable) { - upb_msg_getinternalwithext(msg, l)->extdict = NULL; - } - + msg = UPB_PTR_AT(mem, upb_msg_internalsize(l), upb_msg); + _upb_msg_clear(msg, l); return msg; } -void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, - upb_arena *arena) { +bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena) { upb_msg_internal *in = upb_msg_getinternal(msg); if (len > in->unknown_size - in->unknown_len) { upb_alloc *alloc = upb_arena_alloc(arena); size_t need = in->unknown_size + len; size_t newsize = UPB_MAX(in->unknown_size * 2, need); - in->unknown = upb_realloc(alloc, in->unknown, in->unknown_size, newsize); + void *mem = upb_realloc(alloc, in->unknown, in->unknown_size, newsize); + if (!mem) return false; + in->unknown = mem; in->unknown_size = newsize; } memcpy(in->unknown + in->unknown_len, data, len); in->unknown_len += len; + return true; +} + +void _upb_msg_discardunknown_shallow(upb_msg *msg) { + upb_msg_internal *in = upb_msg_getinternal(msg); + in->unknown_len = 0; } const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) { @@ -148,19 +139,10 @@ static upb_array *getorcreate_array(upb_array **arr_ptr, upb_fieldtype_t type, return arr; } -static bool resize_array(upb_array *arr, size_t size, upb_arena *arena) { - if (size > arr->size && !_upb_array_realloc(arr, size, arena)) { - return false; - } - - arr->len = size; - return true; -} - void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, upb_fieldtype_t type, upb_arena *arena) { upb_array *arr = getorcreate_array(arr_ptr, type, arena); - return arr && resize_array(arr, size, arena) ? _upb_array_ptr(arr) : NULL; + return arr && _upb_array_resize(arr, size, arena) ? _upb_array_ptr(arr) : NULL; } bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, @@ -170,7 +152,7 @@ bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, int lg2 = _upb_fieldtype_to_sizelg2[type]; char *data; - if (!arr || !resize_array(arr, elem + 1, arena)) return false; + if (!arr || !_upb_array_resize(arr, elem + 1, arena)) return false; data = _upb_array_ptr(arr); memcpy(data + (elem << lg2), value, 1 << lg2); @@ -192,5 +174,3 @@ upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) { return map; } - -#undef VOIDPTR_AT diff --git a/upb/msg.h b/upb/msg.h index 2b6423a5bd0..dad54c2b7f1 100644 --- a/upb/msg.h +++ b/upb/msg.h @@ -30,16 +30,17 @@ typedef void upb_msg; * members are public so generated code can initialize them, but users MUST NOT * read or write any of its members. */ -/* This isn't a real label according to descriptor.proto, but in the table we - * use this for map fields instead of UPB_LABEL_REPEATED. */ +/* These aren't real labels according to descriptor.proto, but in the table we + * use these for map/packed fields instead of UPB_LABEL_REPEATED. */ enum { - UPB_LABEL_MAP = 4 + _UPB_LABEL_MAP = 4, + _UPB_LABEL_PACKED = 7 /* Low 3 bits are common with UPB_LABEL_REPEATED. */ }; typedef struct { uint32_t number; uint16_t offset; - int16_t presence; /* If >0, hasbit_index+1. If <0, oneof_index+1. */ + int16_t presence; /* If >0, hasbit_index. If <0, -oneof_index. */ uint16_t submsg_index; /* undefined if descriptortype != MESSAGE or GROUP. */ uint8_t descriptortype; uint8_t label; @@ -80,10 +81,16 @@ extern char _upb_fieldtype_to_size[12]; /* Creates a new messages with the given layout on the given arena. */ upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a); +/* Clears the given message. */ +void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l); + +/* Discards the unknown fields for this message only. */ +void _upb_msg_discardunknown_shallow(upb_msg *msg); + /* Adds unknown data (serialized protobuf data) to the given message. The data * is copied into the message instance. */ -void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, - upb_arena *arena); +bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena); /* Returns a reference to the message's unknown data. */ const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); @@ -104,6 +111,14 @@ UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t n return *PTR_AT(msg, case_ofs, int32_t) == num; } +UPB_INLINE bool _upb_has_submsg_nohasbit(const void *msg, size_t ofs) { + return *PTR_AT(msg, ofs, const void*) != NULL; +} + +UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) { + return (field->label & 3) == UPB_LABEL_REPEATED; +} + /** upb_array *****************************************************************/ /* Our internal representation for repeated fields. */ @@ -133,6 +148,19 @@ void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, upb_fieldtype_t type, upb_arena *arena); +UPB_INLINE bool _upb_array_reserve(upb_array *arr, size_t size, + upb_arena *arena) { + if (arr->size < size) return _upb_array_realloc(arr, size, arena); + return true; +} + +UPB_INLINE bool _upb_array_resize(upb_array *arr, size_t size, + upb_arena *arena) { + if (!_upb_array_reserve(arr, size, arena)) return false; + arr->len = size; + return true; +} + UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs, size_t *size) { const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*); @@ -276,7 +304,7 @@ UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key, upb_value tabval; upb_strview k = _upb_map_tokey(key, key_size); bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); - if (ret) { + if (ret && val) { _upb_map_fromvalue(tabval, val, val_size); } return ret; @@ -287,8 +315,8 @@ UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) { it.t = &map->table; it.index = *iter; upb_strtable_next(&it); - if (upb_strtable_done(&it)) return NULL; *iter = it.index; + if (upb_strtable_done(&it)) return NULL; return (void*)str_tabent(&it); } @@ -315,21 +343,21 @@ UPB_INLINE void _upb_map_clear(upb_map *map) { /* Message map operations, these get the map from the message first. */ UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) { - upb_map *map = UPB_FIELD_AT(msg, upb_map *, ofs); + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); return map ? _upb_map_size(map) : 0; } UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs, const void *key, size_t key_size, void *val, size_t val_size) { - upb_map *map = UPB_FIELD_AT(msg, upb_map *, ofs); + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); if (!map) return false; return _upb_map_get(map, key, key_size, val, val_size); } UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs, size_t *iter) { - upb_map *map = UPB_FIELD_AT(msg, upb_map *, ofs); + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); if (!map) return NULL; return _upb_map_next(map, iter); } @@ -346,13 +374,13 @@ UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key, UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key, size_t key_size) { - upb_map *map = UPB_FIELD_AT(msg, upb_map *, ofs); + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); if (!map) return false; return _upb_map_delete(map, key, key_size); } UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) { - upb_map *map = UPB_FIELD_AT(msg, upb_map *, ofs); + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); if (!map) return; _upb_map_clear(map); } diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c index 8cdb234526a..4f40eed4bed 100644 --- a/upb/pb/decoder.c +++ b/upb/pb/decoder.c @@ -969,9 +969,6 @@ void upb_pbdecoder_reset(upb_pbdecoder *d) { upb_pbdecoder *upb_pbdecoder_create(upb_arena *a, const upb_pbdecodermethod *m, upb_sink sink, upb_status *status) { const size_t default_max_nesting = 64; -#ifndef NDEBUG - size_t size_before = upb_arena_bytesallocated(a); -#endif upb_pbdecoder *d = upb_arena_malloc(a, sizeof(upb_pbdecoder)); if (!d) return NULL; @@ -997,9 +994,6 @@ upb_pbdecoder *upb_pbdecoder_create(upb_arena *a, const upb_pbdecodermethod *m, } d->top->sink = sink; - /* If this fails, increase the value in decoder.h. */ - UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <= - UPB_PB_DECODER_SIZE); return d; } diff --git a/upb/pb/encoder.c b/upb/pb/encoder.c index 257e1474ca3..ea4859ec117 100644 --- a/upb/pb/encoder.c +++ b/upb/pb/encoder.c @@ -534,9 +534,6 @@ upb_pb_encoder *upb_pb_encoder_create(upb_arena *arena, const upb_handlers *h, const size_t initial_segbufsize = 16; /* TODO(haberman): make this configurable. */ const size_t stack_size = 64; -#ifndef NDEBUG - const size_t size_before = upb_arena_bytesallocated(arena); -#endif upb_pb_encoder *e = upb_arena_malloc(arena, sizeof(upb_pb_encoder)); if (!e) return NULL; @@ -561,9 +558,6 @@ upb_pb_encoder *upb_pb_encoder_create(upb_arena *arena, const upb_handlers *h, e->subc = output.closure; e->ptr = e->buf; - /* If this fails, increase the value in encoder.h. */ - UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <= - UPB_PB_ENCODER_SIZE); return e; } diff --git a/upb/port_def.inc b/upb/port_def.inc index 51f8eac96f6..61675d37c05 100644 --- a/upb/port_def.inc +++ b/upb/port_def.inc @@ -21,6 +21,7 @@ * This file is private and must not be included by users! */ #include +#include #if UINTPTR_MAX == 0xffffffff #define UPB_SIZE(size32, size64) size32 @@ -28,20 +29,19 @@ #define UPB_SIZE(size32, size64) size64 #endif -/* These macros aren't really "port", they are helper macros that we don't want - * to leak. +/* If we always read/write as a consistent type to each address, this shouldn't + * violate aliasing. */ -#define UPB_FIELD_AT(msg, fieldtype, offset) \ - *(fieldtype*)((const char*)(msg) + offset) +#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) #define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \ - UPB_FIELD_AT(msg, int, case_offset) == case_val \ - ? UPB_FIELD_AT(msg, fieldtype, offset) \ + *UPB_PTR_AT(msg, case_offset, int) == case_val \ + ? *UPB_PTR_AT(msg, offset, fieldtype) \ : default #define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \ - UPB_FIELD_AT(msg, int, case_offset) = case_val; \ - UPB_FIELD_AT(msg, fieldtype, offset) = value; + *UPB_PTR_AT(msg, case_offset, int) = case_val; \ + *UPB_PTR_AT(msg, offset, fieldtype) = value; #define UPB_MAPTYPE_STRING 0 @@ -54,6 +54,11 @@ #define UPB_INLINE static #endif +#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) +#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) +#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16) +#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member) + /* Hints to the compiler about likely/unlikely branches. */ #if defined (__GNUC__) || defined(__clang__) #define UPB_LIKELY(x) __builtin_expect((x),1) @@ -133,6 +138,8 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #ifdef NDEBUG #ifdef __GNUC__ #define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable() +#elif defined _MSC_VER +#define UPB_ASSUME(expr) if (!(expr)) __assume(0) #else #define UPB_ASSUME(expr) do {} if (false && (expr)) #endif diff --git a/upb/port_undef.inc b/upb/port_undef.inc index e91e9644bb1..c322d471608 100644 --- a/upb/port_undef.inc +++ b/upb/port_undef.inc @@ -2,10 +2,14 @@ #undef UPB_MAPTYPE_STRING #undef UPB_SIZE -#undef UPB_FIELD_AT +#undef UPB_PTR_AT #undef UPB_READ_ONEOF #undef UPB_WRITE_ONEOF #undef UPB_INLINE +#undef UPB_ALIGN_UP +#undef UPB_ALIGN_DOWN +#undef UPB_ALIGN_MALLOC +#undef UPB_ALIGN_OF #undef UPB_FORCEINLINE #undef UPB_NOINLINE #undef UPB_NORETURN diff --git a/upb/reflection.c b/upb/reflection.c index d032eccee40..a23129c2cef 100644 --- a/upb/reflection.c +++ b/upb/reflection.c @@ -47,11 +47,6 @@ static char _upb_fieldtype_to_mapsize[12] = { /** upb_msg *******************************************************************/ -/* If we always read/write as a consistent type to each address, this shouldn't - * violate aliasing. - */ -#define PTR_AT(msg, ofs, type) (type*)((char*)msg + ofs) - upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) { return _upb_msg_new(upb_msgdef_layout(m), a); } @@ -63,12 +58,12 @@ static bool in_oneof(const upb_msglayout_field *field) { static uint32_t *oneofcase(const upb_msg *msg, const upb_msglayout_field *field) { UPB_ASSERT(in_oneof(field)); - return PTR_AT(msg, ~field->presence, uint32_t); + return UPB_PTR_AT(msg, -field->presence, uint32_t); } static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) { const upb_msglayout_field *field = upb_fielddef_layout(f); - const char *mem = PTR_AT(msg, field->offset, char); + const char *mem = UPB_PTR_AT(msg, field->offset, char); upb_msgval val = {0}; int size = upb_fielddef_isseq(f) ? sizeof(void *) : field_size[field->descriptortype]; @@ -82,7 +77,7 @@ bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) { return *oneofcase(msg, field) == field->number; } else if (field->presence > 0) { uint32_t hasbit = field->presence; - return *PTR_AT(msg, hasbit / 8, char) & (1 << (hasbit % 8)); + return *UPB_PTR_AT(msg, hasbit / 8, uint8_t) & (1 << (hasbit % 8)); } else { UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP); @@ -90,16 +85,22 @@ bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) { } } -bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o) { +const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg, + const upb_oneofdef *o) { upb_oneof_iter i; const upb_fielddef *f; const upb_msglayout_field *field; + const upb_msgdef *m = upb_oneofdef_containingtype(o); + uint32_t oneof_case; + /* This is far from optimal. */ upb_oneof_begin(&i, o); if (upb_oneof_done(&i)) return false; f = upb_oneof_iter_field(&i); field = upb_fielddef_layout(f); - return *oneofcase(msg, field) != 0; + oneof_case = *oneofcase(msg, field); + + return oneof_case ? upb_msgdef_itof(m, oneof_case) : NULL; } upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) { @@ -147,7 +148,7 @@ upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a) { const upb_msglayout_field *field = upb_fielddef_layout(f); upb_mutmsgval ret; - char *mem = PTR_AT(msg, field->offset, char); + char *mem = UPB_PTR_AT(msg, field->offset, char); bool wrong_oneof = in_oneof(field) && *oneofcase(msg, field) != field->number; memcpy(&ret, mem, sizeof(void*)); @@ -169,6 +170,9 @@ upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, if (wrong_oneof) { *oneofcase(msg, field) = field->number; + } else if (field->presence > 0) { + uint32_t hasbit = field->presence; + *UPB_PTR_AT(msg, hasbit / 8, uint8_t) |= (1 << (hasbit % 8)); } } return ret; @@ -177,15 +181,40 @@ upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val, upb_arena *a) { const upb_msglayout_field *field = upb_fielddef_layout(f); - char *mem = PTR_AT(msg, field->offset, char); + char *mem = UPB_PTR_AT(msg, field->offset, char); int size = upb_fielddef_isseq(f) ? sizeof(void *) : field_size[field->descriptortype]; memcpy(mem, &val, size); - if (in_oneof(field)) { + if (field->presence > 0) { + uint32_t hasbit = field->presence; + *UPB_PTR_AT(msg, hasbit / 8, uint8_t) |= (1 << (hasbit % 8)); + } else if (in_oneof(field)) { *oneofcase(msg, field) = field->number; } } +void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + char *mem = UPB_PTR_AT(msg, field->offset, char); + int size = upb_fielddef_isseq(f) ? sizeof(void *) + : field_size[field->descriptortype]; + + if (field->presence > 0) { + uint32_t hasbit = field->presence; + *UPB_PTR_AT(msg, hasbit / 8, uint8_t) &= ~(1 << (hasbit % 8)); + } else if (in_oneof(field)) { + uint32_t *oneof_case = oneofcase(msg, field); + if (*oneof_case != field->number) return; + *oneof_case = 0; + } + + memset(mem, 0, size); +} + +void upb_msg_clear(upb_msg *msg, const upb_msgdef *m) { + _upb_msg_clear(msg, upb_msgdef_layout(m)); +} + bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m, const upb_symtab *ext_pool, const upb_fielddef **out_f, upb_msgval *out_val, size_t *iter) { @@ -224,6 +253,56 @@ bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m, return false; } +bool _upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int depth) { + size_t iter = UPB_MSG_BEGIN; + const upb_fielddef *f; + upb_msgval val; + bool ret = true; + + if (--depth == 0) return false; + + _upb_msg_discardunknown_shallow(msg); + + while (upb_msg_next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) { + const upb_msgdef *subm = upb_fielddef_msgsubdef(f); + if (!subm) continue; + if (upb_fielddef_ismap(f)) { + const upb_fielddef *val_f = upb_msgdef_itof(subm, 2); + const upb_msgdef *val_m = upb_fielddef_msgsubdef(val_f); + upb_map *map = (upb_map*)val.map_val; + size_t iter = UPB_MAP_BEGIN; + + if (!val_m) continue; + + while (upb_mapiter_next(map, &iter)) { + upb_msgval map_val = upb_mapiter_value(map, iter); + if (!_upb_msg_discardunknown((upb_msg*)map_val.msg_val, val_m, depth)) { + ret = false; + } + } + } else if (upb_fielddef_isseq(f)) { + const upb_array *arr = val.array_val; + size_t i, n = upb_array_size(arr); + for (i = 0; i < n; i++) { + upb_msgval elem = upb_array_get(arr, i); + if (!_upb_msg_discardunknown((upb_msg*)elem.msg_val, subm, depth)) { + ret = false; + } + } + } else { + if (!_upb_msg_discardunknown((upb_msg*)val.msg_val, subm, depth)) { + ret = false; + } + } + } + + return ret; +} + +bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth) { + return _upb_msg_discardunknown(msg, m, maxdepth); +} + /** upb_array *****************************************************************/ upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) { @@ -259,10 +338,8 @@ bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) { return true; } -/* Resizes the array to the given size, reallocating if necessary, and returns a - * pointer to the new array elements. */ bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) { - return _upb_array_realloc(arr, size, arena); + return _upb_array_resize(arr, size, arena); } /** upb_map *******************************************************************/ @@ -294,6 +371,14 @@ bool upb_mapiter_next(const upb_map *map, size_t *iter) { return _upb_map_next(map, iter); } +bool upb_mapiter_done(const upb_map *map, size_t iter) { + upb_strtable_iter i; + UPB_ASSERT(iter != UPB_MAP_BEGIN); + i.t = &map->table; + i.index = iter; + return upb_strtable_done(&i); +} + /* Returns the key and value for this entry of the map. */ upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) { upb_strtable_iter i; diff --git a/upb/reflection.h b/upb/reflection.h index c55fe4a2e61..0133630c58d 100644 --- a/upb/reflection.h +++ b/upb/reflection.h @@ -44,8 +44,9 @@ upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a) /* May only be called for fields where upb_fielddef_haspresence(f) == true. */ bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f); -/* Returns whether any field is set in the oneof. */ -bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o); +/* Returns the field that is set in the oneof, or NULL if none are set. */ +const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg, + const upb_oneofdef *o); /* Sets the given field to the given value. For a msg/array/map/string, the * value must be in the same arena. */ @@ -55,6 +56,9 @@ void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val, /* Clears any field presence and sets the value back to its default. */ void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f); +/* Clear all data and unknown fields. */ +void upb_msg_clear(upb_msg *msg, const upb_msgdef *m); + /* Iterate over present fields. * * size_t iter = UPB_MSG_BEGIN; @@ -79,6 +83,9 @@ bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m, void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, upb_arena *arena); +/* Clears all unknown field data from this message and all submessages. */ +bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth); + /* Returns a reference to the message's unknown data. */ const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); @@ -143,6 +150,11 @@ bool upb_map_delete(upb_map *map, upb_msgval key); /* Advances to the next entry. Returns false if no more entries are present. */ bool upb_mapiter_next(const upb_map *map, size_t *iter); +/* Returns true if the iterator still points to a valid entry, or false if the + * iterator is past the last element. It is an error to call this function with + * UPB_MAP_BEGIN (you must call next() at least once first). */ +bool upb_mapiter_done(const upb_map *map, size_t iter); + /* Returns the key and value for this entry of the map. */ upb_msgval upb_mapiter_key(const upb_map *map, size_t iter); upb_msgval upb_mapiter_value(const upb_map *map, size_t iter); diff --git a/upb/table.c b/upb/table.c index 21f8fcf6f87..c5ca3ac49bd 100644 --- a/upb/table.c +++ b/upb/table.c @@ -243,7 +243,7 @@ static bool rm(upb_table *t, lookupkey_t key, upb_value *val, static size_t next(const upb_table *t, size_t i) { do { if (++i >= upb_table_size(t)) - return SIZE_MAX; + return SIZE_MAX - 1; /* Distinct from -1. */ } while(upb_tabent_isempty(&t->entries[i])); return i; diff --git a/upb/upb.c b/upb/upb.c index 266ea7d7f98..cccf4489402 100644 --- a/upb/upb.c +++ b/upb/upb.c @@ -11,17 +11,6 @@ #include "upb/port_def.inc" -/* Guarantee null-termination and provide ellipsis truncation. - * It may be tempting to "optimize" this by initializing these final - * four bytes up-front and then being careful never to overwrite them, - * this is safer and simpler. */ -static void nullz(upb_status *status) { - const char *ellipsis = "..."; - size_t len = strlen(ellipsis); - UPB_ASSERT(sizeof(status->msg) > len); - memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len); -} - /* upb_status *****************************************************************/ void upb_status_clear(upb_status *status) { @@ -37,8 +26,8 @@ const char *upb_status_errmsg(const upb_status *status) { return status->msg; } void upb_status_seterrmsg(upb_status *status, const char *msg) { if (!status) return; status->ok = false; - strncpy(status->msg, msg, sizeof(status->msg)); - nullz(status); + strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; } void upb_status_seterrf(upb_status *status, const char *fmt, ...) { @@ -52,7 +41,7 @@ void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) { if (!status) return; status->ok = false; _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args); - nullz(status); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; } /* upb_alloc ******************************************************************/ @@ -74,188 +63,214 @@ upb_alloc upb_alloc_global = {&upb_global_allocfunc}; /* upb_arena ******************************************************************/ /* Be conservative and choose 16 in case anyone is using SSE. */ -static const size_t maxalign = 16; -static size_t align_up_max(size_t size) { - return ((size + maxalign - 1) / maxalign) * maxalign; -} +typedef struct mem_block { + struct mem_block *next; + uint32_t size; + uint32_t cleanups; + /* Data follows. */ +} mem_block; + +typedef struct cleanup_ent { + upb_cleanup_func *cleanup; + void *ud; +} cleanup_ent; struct upb_arena { - /* We implement the allocator interface. - * This must be the first member of upb_arena! */ - upb_alloc alloc; + _upb_arena_head head; + uint32_t *cleanups; /* Allocator to allocate arena blocks. We are responsible for freeing these * when we are destroyed. */ upb_alloc *block_alloc; + uint32_t last_size; - size_t bytes_allocated; - size_t next_block_size; - size_t max_block_size; + /* When multiple arenas are fused together, each arena points to a parent + * arena (root points to itself). The root tracks how many live arenas + * reference it. */ + uint32_t refcount; /* Only used when a->parent == a */ + struct upb_arena *parent; - /* Linked list of blocks. Points to an arena_block, defined in env.c */ - void *block_head; - - /* Cleanup entries. Pointer to a cleanup_ent, defined in env.c */ - void *cleanup_head; + /* Linked list of blocks to free/cleanup. */ + mem_block *freelist, *freelist_tail; }; -typedef struct mem_block { - struct mem_block *next; - size_t size; - size_t used; - bool owned; - /* Data follows. */ -} mem_block; - -typedef struct cleanup_ent { - struct cleanup_ent *next; - upb_cleanup_func *cleanup; - void *ud; -} cleanup_ent; +static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16); -static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size, - bool owned) { +static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size) { mem_block *block = ptr; - block->next = a->block_head; + block->next = a->freelist; block->size = size; - block->used = align_up_max(sizeof(mem_block)); - block->owned = owned; + block->cleanups = 0; + a->freelist = block; + a->last_size = size; + if (!a->freelist_tail) a->freelist_tail = block; - a->block_head = block; + a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char); + a->head.end = UPB_PTR_AT(block, size, char); + a->cleanups = &block->cleanups; /* TODO(haberman): ASAN poison. */ } -static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) { - size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block); +static bool upb_arena_allocblock(upb_arena *a, size_t size) { + size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve; mem_block *block = upb_malloc(a->block_alloc, block_size); - if (!block) { - return NULL; - } + if (!block) return false; + upb_arena_addblock(a, block, block_size); + return true; +} - upb_arena_addblock(a, block, block_size, true); - a->next_block_size = UPB_MIN(block_size * 2, a->max_block_size); +static bool arena_has(upb_arena *a, size_t size) { + _upb_arena_head *h = (_upb_arena_head*)a; + return (size_t)(h->end - h->ptr) >= size; +} - return block; +void *_upb_arena_slowmalloc(upb_arena *a, size_t size) { + if (!upb_arena_allocblock(a, size)) return NULL; /* Out of memory. */ + UPB_ASSERT(arena_has(a, size)); + return upb_arena_malloc(a, size); } static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, size_t size) { upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */ - mem_block *block = a->block_head; - void *ret; + return upb_arena_realloc(a, ptr, oldsize, size); +} - if (size == 0) { - return NULL; /* We are an arena, don't need individual frees. */ +static upb_arena *arena_findroot(upb_arena *a) { + /* Path splitting keeps time complexity down, see: + * https://en.wikipedia.org/wiki/Disjoint-set_data_structure */ + while (a->parent != a) { + upb_arena *next = a->parent; + a->parent = next->parent; + a = next; } + return a; +} - size = align_up_max(size); - - /* TODO(haberman): special-case if this is a realloc of the last alloc? */ +/* Public Arena API ***********************************************************/ - if (!block || block->size - block->used < size) { - /* Slow path: have to allocate a new block. */ - block = upb_arena_allocblock(a, size); +upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) { + const size_t first_block_overhead = sizeof(upb_arena) + memblock_reserve; + upb_arena *a; - if (!block) { - return NULL; /* Out of memory. */ - } + /* We need to malloc the initial block. */ + n = first_block_overhead + 256; + if (!alloc || !(mem = upb_malloc(alloc, n))) { + return NULL; } - ret = (char*)block + block->used; - block->used += size; + a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); + n -= sizeof(*a); - if (oldsize > 0) { - memcpy(ret, ptr, oldsize); /* Preserve existing data. */ - } + a->head.alloc.func = &upb_arena_doalloc; + a->block_alloc = alloc; + a->parent = a; + a->refcount = 1; + a->freelist = NULL; + a->freelist_tail = NULL; - /* TODO(haberman): ASAN unpoison. */ + upb_arena_addblock(a, mem, n); - a->bytes_allocated += size; - return ret; + return a; } -/* Public Arena API ***********************************************************/ - -#define upb_alignof(type) offsetof (struct { char c; type member; }, member) - upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) { - const size_t first_block_overhead = sizeof(upb_arena) + sizeof(mem_block); upb_arena *a; - bool owned = false; /* Round block size down to alignof(*a) since we will allocate the arena * itself at the end. */ - n &= ~(upb_alignof(upb_arena) - 1); - - if (n < first_block_overhead) { - /* We need to malloc the initial block. */ - n = first_block_overhead + 256; - owned = true; - if (!alloc || !(mem = upb_malloc(alloc, n))) { - return NULL; - } + n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_arena)); + + if (UPB_UNLIKELY(n < sizeof(upb_arena))) { + return arena_initslow(mem, n, alloc); } - a = (void*)((char*)mem + n - sizeof(*a)); + a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena); n -= sizeof(*a); - a->alloc.func = &upb_arena_doalloc; - a->block_alloc = &upb_alloc_global; - a->bytes_allocated = 0; - a->next_block_size = 256; - a->max_block_size = 16384; - a->cleanup_head = NULL; - a->block_head = NULL; + a->head.alloc.func = &upb_arena_doalloc; a->block_alloc = alloc; - - upb_arena_addblock(a, mem, n, owned); + a->parent = a; + a->refcount = 1; + a->last_size = 128; + a->head.ptr = mem; + a->head.end = UPB_PTR_AT(mem, n, char); + a->freelist = NULL; + a->cleanups = NULL; return a; } -#undef upb_alignof +static void arena_dofree(upb_arena *a) { + mem_block *block = a->freelist; + UPB_ASSERT(a->parent == a); + UPB_ASSERT(a->refcount == 0); -void upb_arena_free(upb_arena *a) { - cleanup_ent *ent = a->cleanup_head; - mem_block *block = a->block_head; - - while (ent) { - ent->cleanup(ent->ud); - ent = ent->next; - } - - /* Must do this after running cleanup functions, because this will delete - * the memory we store our cleanup entries in! */ while (block) { /* Load first since we are deleting block. */ mem_block *next = block->next; - if (block->owned) { - upb_free(a->block_alloc, block); + if (block->cleanups > 0) { + cleanup_ent *end = UPB_PTR_AT(block, block->size, void); + cleanup_ent *ptr = end - block->cleanups; + + for (; ptr < end; ptr++) { + ptr->cleanup(ptr->ud); + } } + upb_free(a->block_alloc, block); block = next; } } +void upb_arena_free(upb_arena *a) { + a = arena_findroot(a); + if (--a->refcount == 0) arena_dofree(a); +} + bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) { - cleanup_ent *ent = upb_malloc(&a->alloc, sizeof(cleanup_ent)); - if (!ent) { - return false; /* Out of memory. */ + cleanup_ent *ent; + + if (!a->cleanups || !arena_has(a, sizeof(cleanup_ent))) { + if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */ + UPB_ASSERT(arena_has(a, sizeof(cleanup_ent))); } + a->head.end -= sizeof(cleanup_ent); + ent = (cleanup_ent*)a->head.end; + (*a->cleanups)++; + ent->cleanup = func; ent->ud = ud; - ent->next = a->cleanup_head; - a->cleanup_head = ent; return true; } -size_t upb_arena_bytesallocated(const upb_arena *a) { - return a->bytes_allocated; +void upb_arena_fuse(upb_arena *a1, upb_arena *a2) { + upb_arena *r1 = arena_findroot(a1); + upb_arena *r2 = arena_findroot(a2); + + if (r1 == r2) return; /* Already fused. */ + + /* We want to join the smaller tree to the larger tree. + * So swap first if they are backwards. */ + if (r1->refcount < r2->refcount) { + upb_arena *tmp = r1; + r1 = r2; + r2 = tmp; + } + + /* r1 takes over r2's freelist and refcount. */ + r1->refcount += r2->refcount; + if (r2->freelist_tail) { + UPB_ASSERT(r2->freelist_tail->next == NULL); + r2->freelist_tail->next = r1->freelist; + r1->freelist = r2->freelist; + } + r2->parent = r1; } diff --git a/upb/upb.h b/upb/upb.h index 011103d949a..7ad3b1fdc1d 100644 --- a/upb/upb.h +++ b/upb/upb.h @@ -1,8 +1,5 @@ /* ** This file contains shared definitions that are widely used across upb. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. */ #ifndef UPB_H_ @@ -15,24 +12,14 @@ #include #include +#include "upb/port_def.inc" + #ifdef __cplusplus -#include -namespace upb { -class Arena; -class Status; -template class InlinedArena; -} +extern "C" { #endif -#include "upb/port_def.inc" - /* upb_status *****************************************************************/ -/* upb_status represents a success or failure status and error message. - * It owns no resources and allocates no memory, so it should work - * even in OOM situations. */ - -/* The maximum length of an error message before it will get truncated. */ #define UPB_STATUS_MAX_MESSAGE 127 typedef struct { @@ -40,59 +27,15 @@ typedef struct { char msg[UPB_STATUS_MAX_MESSAGE]; /* Error message; NULL-terminated. */ } upb_status; -#ifdef __cplusplus -extern "C" { -#endif - const char *upb_status_errmsg(const upb_status *status); bool upb_ok(const upb_status *status); -/* Any of the functions that write to a status object allow status to be NULL, - * to support use cases where the function's caller does not care about the - * status message. */ +/* These are no-op if |status| is NULL. */ void upb_status_clear(upb_status *status); void upb_status_seterrmsg(upb_status *status, const char *msg); void upb_status_seterrf(upb_status *status, const char *fmt, ...); void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args); -UPB_INLINE void upb_status_setoom(upb_status *status) { - upb_status_seterrmsg(status, "out of memory"); -} - -#ifdef __cplusplus -} /* extern "C" */ - -class upb::Status { - public: - Status() { upb_status_clear(&status_); } - - upb_status* ptr() { return &status_; } - - /* Returns true if there is no error. */ - bool ok() const { return upb_ok(&status_); } - - /* Guaranteed to be NULL-terminated. */ - const char *error_message() const { return upb_status_errmsg(&status_); } - - /* The error message will be truncated if it is longer than - * UPB_STATUS_MAX_MESSAGE-4. */ - void SetErrorMessage(const char *msg) { upb_status_seterrmsg(&status_, msg); } - void SetFormattedErrorMessage(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - upb_status_vseterrf(&status_, fmt, args); - va_end(args); - } - - /* Resets the status to a successful state with no message. */ - void Clear() { upb_status_clear(&status_); } - - private: - upb_status status_; -}; - -#endif /* __cplusplus */ - /** upb_strview ************************************************************/ typedef struct { @@ -159,16 +102,8 @@ UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) { /* The global allocator used by upb. Uses the standard malloc()/free(). */ -#ifdef __cplusplus -extern "C" { -#endif - extern upb_alloc upb_alloc_global; -#ifdef __cplusplus -} /* extern "C" */ -#endif - /* Functions that hard-code the global malloc. * * We still get benefit because we can put custom logic into our global @@ -205,9 +140,14 @@ typedef void upb_cleanup_func(void *ud); struct upb_arena; typedef struct upb_arena upb_arena; -#ifdef __cplusplus -extern "C" { -#endif +typedef struct { + /* We implement the allocator interface. + * This must be the first member of upb_arena! + * TODO(haberman): remove once handlers are gone. */ + upb_alloc alloc; + + char *ptr, *end; +} _upb_arena_head; /* Creates an arena from the given initial block (if any -- n may be 0). * Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this @@ -215,83 +155,40 @@ extern "C" { upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc); void upb_arena_free(upb_arena *a); bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func); -size_t upb_arena_bytesallocated(const upb_arena *a); +void upb_arena_fuse(upb_arena *a, upb_arena *b); +void *_upb_arena_slowmalloc(upb_arena *a, size_t size); UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; } -/* Convenience wrappers around upb_alloc functions. */ - UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) { - return upb_malloc(upb_arena_alloc(a), size); + _upb_arena_head *h = (_upb_arena_head*)a; + void* ret; + size = UPB_ALIGN_MALLOC(size); + + if (UPB_UNLIKELY((size_t)(h->end - h->ptr) < size)) { + return _upb_arena_slowmalloc(a, size); + } + + ret = h->ptr; + h->ptr += size; + return ret; } UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize, size_t size) { - return upb_realloc(upb_arena_alloc(a), ptr, oldsize, size); + void *ret = upb_arena_malloc(a, size); + + if (ret && oldsize > 0) { + memcpy(ret, ptr, oldsize); + } + + return ret; } UPB_INLINE upb_arena *upb_arena_new(void) { return upb_arena_init(NULL, 0, &upb_alloc_global); } -#ifdef __cplusplus -} /* extern "C" */ - -class upb::Arena { - public: - /* A simple arena with no initial memory block and the default allocator. */ - Arena() : ptr_(upb_arena_new(), upb_arena_free) {} - - upb_arena* ptr() { return ptr_.get(); } - - /* Allows this arena to be used as a generic allocator. - * - * The arena does not need free() calls so when using Arena as an allocator - * it is safe to skip them. However they are no-ops so there is no harm in - * calling free() either. */ - upb_alloc *allocator() { return upb_arena_alloc(ptr_.get()); } - - /* Add a cleanup function to run when the arena is destroyed. - * Returns false on out-of-memory. */ - bool AddCleanup(void *ud, upb_cleanup_func* func) { - return upb_arena_addcleanup(ptr_.get(), ud, func); - } - - /* Total number of bytes that have been allocated. It is undefined what - * Realloc() does to &arena_ counter. */ - size_t BytesAllocated() const { return upb_arena_bytesallocated(ptr_.get()); } - - private: - std::unique_ptr ptr_; -}; - -#endif - -/* upb::InlinedArena **********************************************************/ - -/* upb::InlinedArena seeds the arenas with a predefined amount of memory. No - * heap memory will be allocated until the initial block is exceeded. - * - * These types only exist in C++ */ - -#ifdef __cplusplus - -template class upb::InlinedArena : public upb::Arena { - public: - InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {} - - upb_arena* ptr() { return ptr_.get(); } - - private: - InlinedArena(const InlinedArena*) = delete; - InlinedArena& operator=(const InlinedArena*) = delete; - - std::unique_ptr ptr_; - char initial_block_[N]; -}; - -#endif /* __cplusplus */ - /* Constants ******************************************************************/ /* Generic function type. */ @@ -311,20 +208,15 @@ typedef enum { * types defined in descriptor.proto, which gives INT32 and SINT32 separate * types (we distinguish the two with the "integer encoding" enum below). */ typedef enum { - /* Types stored in 1 byte. */ UPB_TYPE_BOOL = 1, - /* Types stored in 4 bytes. */ UPB_TYPE_FLOAT = 2, UPB_TYPE_INT32 = 3, UPB_TYPE_UINT32 = 4, UPB_TYPE_ENUM = 5, /* Enum values are int32. */ - /* Types stored as void* (probably 4 or 8 bytes). */ UPB_TYPE_MESSAGE = 6, - /* Types stored as 8 bytes. */ UPB_TYPE_DOUBLE = 7, UPB_TYPE_INT64 = 8, UPB_TYPE_UINT64 = 9, - /* Types stored as upb_strview (2 * void*) (probably 8 or 16 bytes). */ UPB_TYPE_STRING = 10, UPB_TYPE_BYTES = 11 } upb_fieldtype_t; @@ -338,6 +230,7 @@ typedef enum { /* Descriptor types, as defined in descriptor.proto. */ typedef enum { + /* Old (long) names. TODO(haberman): remove */ UPB_DESCRIPTOR_TYPE_DOUBLE = 1, UPB_DESCRIPTOR_TYPE_FLOAT = 2, UPB_DESCRIPTOR_TYPE_INT64 = 3, @@ -355,11 +248,34 @@ typedef enum { UPB_DESCRIPTOR_TYPE_SFIXED32 = 15, UPB_DESCRIPTOR_TYPE_SFIXED64 = 16, UPB_DESCRIPTOR_TYPE_SINT32 = 17, - UPB_DESCRIPTOR_TYPE_SINT64 = 18 + UPB_DESCRIPTOR_TYPE_SINT64 = 18, + + UPB_DTYPE_DOUBLE = 1, + UPB_DTYPE_FLOAT = 2, + UPB_DTYPE_INT64 = 3, + UPB_DTYPE_UINT64 = 4, + UPB_DTYPE_INT32 = 5, + UPB_DTYPE_FIXED64 = 6, + UPB_DTYPE_FIXED32 = 7, + UPB_DTYPE_BOOL = 8, + UPB_DTYPE_STRING = 9, + UPB_DTYPE_GROUP = 10, + UPB_DTYPE_MESSAGE = 11, + UPB_DTYPE_BYTES = 12, + UPB_DTYPE_UINT32 = 13, + UPB_DTYPE_ENUM = 14, + UPB_DTYPE_SFIXED32 = 15, + UPB_DTYPE_SFIXED64 = 16, + UPB_DTYPE_SINT32 = 17, + UPB_DTYPE_SINT64 = 18 } upb_descriptortype_t; #define UPB_MAP_BEGIN -1 #include "upb/port_undef.inc" +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* UPB_H_ */ diff --git a/upb/upb.hpp b/upb/upb.hpp new file mode 100644 index 00000000000..60ef29b2966 --- /dev/null +++ b/upb/upb.hpp @@ -0,0 +1,86 @@ + +#ifndef UPB_HPP_ +#define UPB_HPP_ + +#include + +#include "upb/upb.h" + +namespace upb { + +class Status { + public: + Status() { upb_status_clear(&status_); } + + upb_status* ptr() { return &status_; } + + // Returns true if there is no error. + bool ok() const { return upb_ok(&status_); } + + // Guaranteed to be NULL-terminated. + const char *error_message() const { return upb_status_errmsg(&status_); } + + // The error message will be truncated if it is longer than + // UPB_STATUS_MAX_MESSAGE-4. + void SetErrorMessage(const char *msg) { upb_status_seterrmsg(&status_, msg); } + void SetFormattedErrorMessage(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + upb_status_vseterrf(&status_, fmt, args); + va_end(args); + } + + // Resets the status to a successful state with no message. + void Clear() { upb_status_clear(&status_); } + + private: + upb_status status_; +}; + +class Arena { + public: + // A simple arena with no initial memory block and the default allocator. + Arena() : ptr_(upb_arena_new(), upb_arena_free) {} + + upb_arena* ptr() { return ptr_.get(); } + + // Allows this arena to be used as a generic allocator. + // + // The arena does not need free() calls so when using Arena as an allocator + // it is safe to skip them. However they are no-ops so there is no harm in + // calling free() either. + upb_alloc *allocator() { return upb_arena_alloc(ptr_.get()); } + + // Add a cleanup function to run when the arena is destroyed. + // Returns false on out-of-memory. + template + bool Own(T *obj) { + return upb_arena_addcleanup(ptr_.get(), obj, [](void* obj) { + delete static_cast(obj); + }); + } + + private: + std::unique_ptr ptr_; +}; + +// InlinedArena seeds the arenas with a predefined amount of memory. No +// heap memory will be allocated until the initial block is exceeded. +template +class InlinedArena : public Arena { + public: + InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {} + + upb_arena* ptr() { return ptr_.get(); } + + private: + InlinedArena(const InlinedArena*) = delete; + InlinedArena& operator=(const InlinedArena*) = delete; + + std::unique_ptr ptr_; + char initial_block_[N]; +}; + +} // namespace upb + +#endif // UPB_HPP_ diff --git a/upbc/generator.cc b/upbc/generator.cc index 47cc07ad10b..3ae64232624 100644 --- a/upbc/generator.cc +++ b/upbc/generator.cc @@ -87,7 +87,9 @@ class Generator : public protoc::CodeGenerator { bool Generate(const protobuf::FileDescriptor* file, const std::string& parameter, protoc::GeneratorContext* context, std::string* error) const override; - + uint64_t GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } }; void AddMessages(const protobuf::Descriptor* message, @@ -350,7 +352,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output MessageName(message), MessageInit(message)); } - for (int i = 0; i < message->oneof_decl_count(); i++) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { const protobuf::OneofDescriptor* oneof = message->oneof_decl(i); std::string fullname = ToCIdent(oneof->full_name()); output("typedef enum {\n"); @@ -364,7 +366,7 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output fullname); output( "UPB_INLINE $0_oneofcases $1_$2_case(const $1* msg) { " - "return ($0_oneofcases)UPB_FIELD_AT(msg, int32_t, $3); }\n" + "return ($0_oneofcases)*UPB_PTR_AT(msg, $3, int32_t); }\n" "\n", fullname, msgname, oneof->name(), GetSizeInit(layout.GetOneofCaseOffset(oneof))); @@ -379,13 +381,19 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output "UPB_INLINE bool $0_has_$1(const $0 *msg) { " "return _upb_has_field(msg, $2); }\n", msgname, field->name(), layout.GetHasbitIndex(field)); - } else if (field->containing_oneof()) { + } else if (field->real_containing_oneof()) { output( "UPB_INLINE bool $0_has_$1(const $0 *msg) { " "return _upb_has_oneof_field(msg, $2, $3); }\n", msgname, field->name(), - GetSizeInit(layout.GetOneofCaseOffset(field->containing_oneof())), + GetSizeInit( + layout.GetOneofCaseOffset(field->real_containing_oneof())), field->number()); + } else if (field->message_type()) { + output( + "UPB_INLINE bool $0_has_$1(const $0 *msg) { " + "return _upb_has_submsg_nohasbit(msg, $2); }\n", + msgname, field->name(), GetSizeInit(layout.GetFieldOffset(field))); } // Generate getter. @@ -430,18 +438,18 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output "return ($0 const*)_upb_array_accessor(msg, $3, len); }\n", CTypeConst(field), msgname, field->name(), GetSizeInit(layout.GetFieldOffset(field))); - } else if (field->containing_oneof()) { + } else if (field->real_containing_oneof()) { output( "UPB_INLINE $0 $1_$2(const $1 *msg) { " "return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6); }\n", CTypeConst(field), msgname, field->name(), GetSizeInit(layout.GetFieldOffset(field)), - GetSizeInit(layout.GetOneofCaseOffset(field->containing_oneof())), + GetSizeInit(layout.GetOneofCaseOffset(field->real_containing_oneof())), field->number(), FieldDefault(field)); } else { output( "UPB_INLINE $0 $1_$2(const $1 *msg) { " - "return UPB_FIELD_AT(msg, $0, $3); }\n", + "return *UPB_PTR_AT(msg, $3, $0); }\n", CTypeConst(field), msgname, field->name(), GetSizeInit(layout.GetFieldOffset(field))); } @@ -544,19 +552,20 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING ? "0" : "sizeof(" + CType(field) + ")"); - } else if (field->containing_oneof()) { + } else if (field->real_containing_oneof()) { output( " UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n" "}\n", CType(field), GetSizeInit(layout.GetFieldOffset(field)), - GetSizeInit(layout.GetOneofCaseOffset(field->containing_oneof())), + GetSizeInit( + layout.GetOneofCaseOffset(field->real_containing_oneof())), field->number()); } else { if (MessageLayout::HasHasbit(field)) { output(" _upb_sethas(msg, $0);\n", layout.GetHasbitIndex(field)); } output( - " UPB_FIELD_AT(msg, $0, $1) = value;\n" + " *UPB_PTR_AT(msg, $1, $0) = value;\n" "}\n", CType(field), GetSizeInit(layout.GetFieldOffset(field))); } @@ -699,7 +708,6 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output) { std::string msgname = ToCIdent(message->full_name()); std::string fields_array_ref = "NULL"; std::string submsgs_array_ref = "NULL"; - std::string oneofs_array_ref = "NULL"; absl::flat_hash_map submsg_indexes; MessageLayout layout(message); std::vector sorted_submsgs = @@ -742,18 +750,29 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output) { } if (MessageLayout::HasHasbit(field)) { - presence = absl::StrCat(layout.GetHasbitIndex(field)); - } else if (field->containing_oneof()) { + int index = layout.GetHasbitIndex(field); + assert(index != 0); + presence = absl::StrCat(index); + } else if (field->real_containing_oneof()) { MessageLayout::Size case_offset = - layout.GetOneofCaseOffset(field->containing_oneof()); + layout.GetOneofCaseOffset(field->real_containing_oneof()); - // Our encoding that distinguishes oneofs from presence-having fields. - case_offset.size32 = -case_offset.size32 - 1; - case_offset.size64 = -case_offset.size64 - 1; + // We encode as negative to distinguish from hasbits. + case_offset.size32 = -case_offset.size32; + case_offset.size64 = -case_offset.size64; + assert(case_offset.size32 != 0); + assert(case_offset.size64 != 0); presence = GetSizeInit(case_offset); } - // Sync '4' with UPB_LABEL_MAP in upb/msg.h. - int label = field->is_map() ? 4 : field->label(); + + std::string label; + if (field->is_map()) { + label = "_UPB_LABEL_MAP"; + } else if (field->is_packed()) { + label = "_UPB_LABEL_PACKED"; + } else { + label = absl::StrCat(field->label()); + } output(" {$0, $1, $2, $3, $4, $5},\n", field->number(), @@ -839,6 +858,7 @@ void WriteDefSource(const protobuf::FileDescriptor* file, Output& output) { EmitFileWarning(file, output); output("#include \"upb/def.h\"\n"); + output("#include \"$0\"\n", DefHeaderFilename(file->name())); output("\n"); for (int i = 0; i < file->dependency_count(); i++) { @@ -867,35 +887,19 @@ void WriteDefSource(const protobuf::FileDescriptor* file, Output& output) { std::string file_data; file_proto.SerializeToString(&file_data); - output("static const char descriptor[$0] =", file_data.size()); - - { - if (file_data.size() > 65535) { - // Workaround for MSVC: "Error C1091: compiler limit: string exceeds - // 65535 bytes in length". Declare a static array of chars rather than - // use a string literal. Only write 25 bytes per line. - static const size_t kBytesPerLine = 25; - output("{ "); - for (size_t i = 0; i < file_data.size();) { - for (size_t j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { - output("'$0', ", absl::CEscape(file_data.substr(i, 1))); - } - output("\n"); - } - output("'\\0' }"); // null-terminate - } else { - // Only write 40 bytes per line. - static const size_t kBytesPerLine = 40; - for (size_t i = 0; i < file_data.size(); i += kBytesPerLine) { - output("\n"); - output( - " \"$0\"", - EscapeTrigraphs(absl::CEscape(file_data.substr(i, kBytesPerLine)))); - } + output("static const char descriptor[$0] = {", file_data.size()); + + // C90 only guarantees that strings can be up to 509 characters, and some + // implementations have limits here (for example, MSVC only allows 64k: + // https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/fatal-error-c1091. + // So we always emit an array instead of a string. + for (size_t i = 0; i < file_data.size();) { + for (size_t j = 0; j < 25 && i < file_data.size(); ++i, ++j) { + output("'$0', ", absl::CEscape(file_data.substr(i, 1))); } - output(";\n"); + output("\n"); } - output("\n"); + output("};\n\n"); output("static upb_def_init *deps[$0] = {\n", file->dependency_count() + 1); for (int i = 0; i < file->dependency_count(); i++) {