diff --git a/BUILD b/BUILD index 0166b14c98..f502744ff9 100644 --- a/BUILD +++ b/BUILD @@ -2,10 +2,6 @@ load( "//bazel:build_defs.bzl", "generated_file_staleness_test", "licenses", # copybara:strip_for_google3 - "lua_binary", - "lua_cclibrary", - "lua_library", - "lua_test", "make_shell_script", "upb_amalgamation", ) @@ -14,6 +10,10 @@ load( "upb_proto_library", "upb_proto_reflection_library", ) +load( + "//:upb/bindings/lua/lua_proto_library.bzl", + "lua_proto_library", +) licenses(["notice"]) # BSD (Google-authored w/ possible external contributions) @@ -32,6 +32,7 @@ CPPOPTS = [ COPTS = CPPOPTS + [ # copybara:strip_for_google3_begin "-pedantic", + "-Werror=pedantic", "-Wstrict-prototypes", # copybara:strip_end ] @@ -70,7 +71,6 @@ cc_library( srcs = [ "upb/decode.c", "upb/encode.c", - "upb/generated_util.h", "upb/msg.c", "upb/msg.h", "upb/table.c", @@ -99,7 +99,6 @@ cc_library( cc_library( name = "generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", hdrs = [ - "upb/generated_util.h", "upb/msg.h", "upb/port_def.inc", "upb/port_undef.inc", @@ -124,11 +123,11 @@ cc_library( name = "reflection", srcs = [ "upb/def.c", - "upb/msgfactory.c", + "upb/reflection.c", ], hdrs = [ "upb/def.h", - "upb/msgfactory.h", + "upb/reflection.h", ], copts = select({ ":windows": [], @@ -156,24 +155,6 @@ cc_library( # Legacy C/C++ Libraries (not recommended for new code) ######################## -cc_library( - name = "legacy_msg_reflection", - srcs = [ - "upb/msg.h", - "upb/legacy_msg_reflection.c", - ], - hdrs = ["upb/legacy_msg_reflection.h"], - copts = select({ - ":windows": [], - "//conditions:default": COPTS - }), - deps = [ - ":port", - ":table", - ":upb", - ], -) - cc_library( name = "handlers", srcs = [ @@ -359,6 +340,15 @@ cc_test( ], ) +cc_test( + name = "test_generated_code", + srcs = ["tests/test_generated_code.c"], + deps = [ + ":test_messages_proto3_proto_upb", + ":upb_test", + ], +) + proto_library( name = "test_decoder_proto", srcs = [ @@ -563,6 +553,7 @@ sh_test( ":conformance_upb", "@com_google_protobuf//:conformance_test_runner", ], + deps = ["@bazel_tools//tools/bash/runfiles"], ) # copybara:strip_for_google3_begin @@ -602,10 +593,10 @@ cc_library( }), ) -# Lua libraries. ############################################################### +# Lua ########################################################################## -lua_cclibrary( - name = "lua/upb_c", +cc_library( + name = "lupb", srcs = [ "upb/bindings/lua/def.c", "upb/bindings/lua/msg.c", @@ -615,48 +606,56 @@ lua_cclibrary( "upb/bindings/lua/upb.h", ], deps = [ - "legacy_msg_reflection", - "upb", - "upb_pb", + ":reflection", + ":upb", + "@lua//:liblua", ], ) -lua_library( - name = "lua/upb", - srcs = ["upb/bindings/lua/upb.lua"], - luadeps = ["lua/upb_c"], - strip_prefix = "upb/bindings/lua", -) - -lua_cclibrary( - name = "lua/upb/pb_c", - srcs = ["upb/bindings/lua/upb/pb.c"], - luadeps = ["lua/upb_c"], - deps = ["upb_pb"], +cc_test( + name = "test_lua", + linkstatic = 1, + srcs = ["tests/bindings/lua/main.c"], + data = [ + "@com_google_protobuf//:conformance_proto", + "@com_google_protobuf//:descriptor_proto", + ":descriptor_proto_lua", + ":test_messages_proto3_proto_lua", + "tests/bindings/lua/test_upb.lua", + "third_party/lunit/console.lua", + "third_party/lunit/lunit.lua", + "upb/bindings/lua/upb.lua", + ], + deps = [ + ":lupb", + "@lua//:liblua", + ] ) -lua_library( - name = "lua/upb/pb", - srcs = ["upb/bindings/lua/upb/pb.lua"], - luadeps = [ - "lua/upb", - "lua/upb/pb_c", +cc_binary( + name = "protoc-gen-lua", + srcs = ["upb/bindings/lua/upbc.cc"], + copts = select({ + ":windows": [], + "//conditions:default": CPPOPTS + }), + visibility = ["//visibility:public"], + deps = [ + "@com_google_absl//absl/strings", + "@com_google_protobuf//:protoc_lib" ], - strip_prefix = "upb/bindings/lua", ) -# Lua tests. ################################################################### - -lua_test( - name = "lua/test_upb", - luadeps = ["lua/upb"], - luamain = "tests/bindings/lua/test_upb.lua", +lua_proto_library( + name = "descriptor_proto_lua", + visibility = ["//visibility:public"], + deps = ["@com_google_protobuf//:descriptor_proto"], ) -lua_test( - name = "lua/test_upb_pb", - luadeps = ["lua/upb/pb"], - luamain = "tests/bindings/lua/test_upb.pb.lua", +lua_proto_library( + name = "test_messages_proto3_proto_lua", + testonly = 1, + deps = ["@com_google_protobuf//:test_messages_proto3_proto"], ) # Test the CMake build ######################################################### @@ -683,6 +682,7 @@ sh_test( name = "cmake_build", srcs = ["run_cmake_build.sh"], data = [":cmake_files"], + deps = ["@bazel_tools//tools/bash/runfiles"], ) # Generated files ############################################################## diff --git a/CMakeLists.txt b/CMakeLists.txt index 96b265dd3a..cb8297ac77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,6 @@ add_library(port add_library(upb upb/decode.c upb/encode.c - upb/generated_util.h upb/msg.c upb/msg.h upb/table.c @@ -81,9 +80,9 @@ target_link_libraries(generated_code_support__only_for_generated_code_do_not_use upb) add_library(reflection upb/def.c - upb/msgfactory.c + upb/reflection.c upb/def.h - upb/msgfactory.h) + upb/reflection.h) target_link_libraries(reflection descriptor_upbproto port @@ -93,14 +92,6 @@ add_library(table INTERFACE) target_link_libraries(table INTERFACE port upb) -add_library(legacy_msg_reflection - upb/msg.h - upb/legacy_msg_reflection.c - upb/legacy_msg_reflection.h) -target_link_libraries(legacy_msg_reflection - port - table - upb) add_library(handlers upb/handlers.c upb/handlers-inl.h diff --git a/bazel/build_defs.bzl b/bazel/build_defs.bzl index 08bb44ee3f..7544e12517 100644 --- a/bazel/build_defs.bzl +++ b/bazel/build_defs.bzl @@ -5,6 +5,19 @@ load(":upb_proto_library.bzl", "GeneratedSrcsInfo") def _librule(name): return name + "_lib" +runfiles_init = """\ +# --- begin runfiles.bash initialization v2 --- +# Copy-pasted from the Bazel Bash runfiles library v2. +set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash +source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ + source "$0.runfiles/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e +# --- end runfiles.bash initialization v2 --- +""" + def _get_real_short_path(file): # For some reason, files from other archives have short paths that look like: # ../com_google_protobuf/google/protobuf/descriptor.proto @@ -26,42 +39,6 @@ def _get_real_roots(files): roots[real_root] = True return roots.keys() -def lua_cclibrary(name, srcs, hdrs = [], deps = [], luadeps = []): - lib_rule = name + "_lib" - so_rule = "lib" + name + ".so" - so_file = _remove_prefix(name, "lua/") + ".so" - - native.cc_library( - name = _librule(name), - hdrs = hdrs, - srcs = srcs, - deps = deps + [_librule(dep) for dep in luadeps] + ["@lua//:liblua_headers"], - ) - - native.cc_binary( - name = so_rule, - linkshared = True, - deps = [_librule(name)], - linkopts = select({ - ":darwin": [ - "-undefined dynamic_lookup", - ], - "//conditions:default": [], - }), - ) - - native.genrule( - name = name + "_copy", - srcs = [":" + so_rule], - outs = [so_file], - cmd = "cp $< $@", - ) - - native.filegroup( - name = name, - data = [so_file], - ) - def _remove_prefix(str, prefix): if not str.startswith(prefix): fail("%s doesn't start with %s" % (str, prefix)) @@ -72,54 +49,14 @@ def _remove_suffix(str, suffix): fail("%s doesn't end with %s" % (str, suffix)) return str[:-len(suffix)] -def lua_library(name, srcs, strip_prefix, luadeps = []): - outs = [_remove_prefix(src, strip_prefix + "/") for src in srcs] - native.genrule( - name = name + "_copy", - srcs = srcs, - outs = outs, - cmd = "cp $(SRCS) $(@D)", - ) - - native.filegroup( - name = name, - data = outs + luadeps, - ) - def make_shell_script(name, contents, out): - contents = contents.replace("$", "$$") + contents = (runfiles_init + contents).replace("$", "$$") native.genrule( name = "gen_" + name, outs = [out], cmd = "(cat <<'HEREDOC'\n%s\nHEREDOC\n) > $@" % contents, ) -def _lua_binary_or_test(name, luamain, luadeps, rule): - script = name + ".sh" - - make_shell_script( - name = "gen_" + name, - out = script, - contents = """ -BASE=$(dirname $(rlocation upb/upb_c.so)) -export LUA_CPATH="$BASE/?.so" -export LUA_PATH="$BASE/?.lua" -$(rlocation lua/lua) $(rlocation upb/tools/upbc.lua) "$@" -""", - ) - - rule( - name = name, - srcs = [script], - data = ["@lua//:lua", luamain] + luadeps, - ) - -def lua_binary(name, luamain, luadeps = []): - _lua_binary_or_test(name, luamain, luadeps, native.sh_binary) - -def lua_test(name, luamain, luadeps = []): - _lua_binary_or_test(name, luamain, luadeps, native.sh_test) - def generated_file_staleness_test(name, outs, generated_pattern): """Tests that checked-in file(s) match the contents of generated file(s). diff --git a/bazel/upb_proto_library.bzl b/bazel/upb_proto_library.bzl index bea611776c..9ad578f96f 100644 --- a/bazel/upb_proto_library.bzl +++ b/bazel/upb_proto_library.bzl @@ -146,8 +146,10 @@ GeneratedSrcsInfo = provider( }, ) -_WrappedCcInfo = provider(fields = ["cc_info"]) +_UpbWrappedCcInfo = provider(fields = ["cc_info"]) +_UpbDefsWrappedCcInfo = provider(fields = ["cc_info"]) _WrappedGeneratedSrcsInfo = provider(fields = ["srcs"]) +_WrappedDefsGeneratedSrcsInfo = provider(fields = ["srcs"]) def _compile_upb_protos(ctx, proto_info, proto_sources, ext): srcs = [_generate_output_file(ctx, name, ext + ".c") for name in proto_sources] @@ -175,11 +177,23 @@ def _upb_proto_rule_impl(ctx): if len(ctx.attr.deps) != 1: fail("only one deps dependency allowed.") dep = ctx.attr.deps[0] - if _WrappedCcInfo not in dep or _WrappedGeneratedSrcsInfo not in dep: - fail("proto_library rule must generate _WrappedCcInfo and " + - "_WrappedGeneratedSrcsInfo (aspect should have handled this).") - cc_info = dep[_WrappedCcInfo].cc_info - srcs = dep[_WrappedGeneratedSrcsInfo].srcs + + if _WrappedDefsGeneratedSrcsInfo in dep: + srcs = dep[_WrappedDefsGeneratedSrcsInfo].srcs + elif _WrappedGeneratedSrcsInfo in dep: + srcs = dep[_WrappedGeneratedSrcsInfo].srcs + else: + fail("proto_library rule must generate _WrappedGeneratedSrcsInfo or " + + "_WrappedDefsGeneratedSrcsInfo (aspect should have handled this).") + + if _UpbDefsWrappedCcInfo in dep: + cc_info = dep[_UpbDefsWrappedCcInfo].cc_info + elif _UpbWrappedCcInfo in dep: + cc_info = dep[_UpbWrappedCcInfo].cc_info + else: + fail("proto_library rule must generate _UpbWrappedCcInfo or " + + "_UpbDefsWrappedCcInfo (aspect should have handled this).") + if type(cc_info.linking_context.libraries_to_link) == "list": lib = cc_info.linking_context.libraries_to_link[0] else: @@ -195,12 +209,19 @@ def _upb_proto_rule_impl(ctx): cc_info, ] -def _upb_proto_aspect_impl(target, ctx): +def _upb_proto_aspect_impl(target, ctx, cc_provider, file_provider): proto_info = target[ProtoInfo] files = _compile_upb_protos(ctx, proto_info, proto_info.direct_sources, ctx.attr._ext) deps = ctx.rule.attr.deps + ctx.attr._upb + if cc_provider == _UpbDefsWrappedCcInfo: + deps += ctx.attr._upb_reflection dep_ccinfos = [dep[CcInfo] for dep in deps if CcInfo in dep] - dep_ccinfos += [dep[_WrappedCcInfo].cc_info for dep in deps if _WrappedCcInfo in dep] + dep_ccinfos += [dep[_UpbWrappedCcInfo].cc_info for dep in deps if _UpbWrappedCcInfo in dep] + dep_ccinfos += [dep[_UpbDefsWrappedCcInfo].cc_info for dep in deps if _UpbDefsWrappedCcInfo in dep] + if cc_provider == _UpbDefsWrappedCcInfo: + if _UpbWrappedCcInfo not in target: + fail("Target should have _UpbDefsWrappedCcInfo provider") + dep_ccinfos += [target[_UpbWrappedCcInfo].cc_info] cc_info = _cc_library_func( ctx = ctx, name = ctx.rule.attr.name + ctx.attr._ext, @@ -208,7 +229,13 @@ def _upb_proto_aspect_impl(target, ctx): srcs = files.srcs, dep_ccinfos = dep_ccinfos, ) - return [_WrappedCcInfo(cc_info = cc_info), _WrappedGeneratedSrcsInfo(srcs = files)] + return [cc_provider(cc_info = cc_info), file_provider(srcs = files)] + +def _upb_proto_library_aspect_impl(target, ctx): + return _upb_proto_aspect_impl(target, ctx, _UpbWrappedCcInfo, _WrappedGeneratedSrcsInfo) + +def _upb_proto_reflection_library_aspect_impl(target, ctx): + return _upb_proto_aspect_impl(target, ctx, _UpbDefsWrappedCcInfo, _WrappedDefsGeneratedSrcsInfo) def _maybe_add(d): if not _is_bazel: @@ -242,7 +269,11 @@ _upb_proto_library_aspect = aspect( ]), "_ext": attr.string(default = ".upb"), }), - implementation = _upb_proto_aspect_impl, + implementation = _upb_proto_library_aspect_impl, + provides = [ + _UpbWrappedCcInfo, + _WrappedGeneratedSrcsInfo, + ], attr_aspects = ["deps"], fragments = ["cpp"], toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], @@ -277,6 +308,7 @@ _upb_proto_reflection_library_aspect = aspect( "_cc_toolchain": attr.label( default = "@bazel_tools//tools/cpp:current_cc_toolchain", ), + # For unknown reasons, this gets overwritten. "_upb": attr.label_list( default = [ "//:generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", @@ -284,9 +316,23 @@ _upb_proto_reflection_library_aspect = aspect( "//:reflection", ], ), + "_upb_reflection": attr.label_list( + default = [ + "//:upb", + "//:reflection", + ], + ), "_ext": attr.string(default = ".upbdefs"), }), - implementation = _upb_proto_aspect_impl, + implementation = _upb_proto_reflection_library_aspect_impl, + provides = [ + _UpbDefsWrappedCcInfo, + _WrappedDefsGeneratedSrcsInfo, + ], + required_aspect_providers = [ + _UpbWrappedCcInfo, + _WrappedGeneratedSrcsInfo, + ], attr_aspects = ["deps"], fragments = ["cpp"], toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], @@ -297,7 +343,10 @@ upb_proto_reflection_library = rule( implementation = _upb_proto_rule_impl, attrs = { "deps": attr.label_list( - aspects = [_upb_proto_reflection_library_aspect], + aspects = [ + _upb_proto_library_aspect, + _upb_proto_reflection_library_aspect, + ], allow_rules = ["proto_library"], providers = [ProtoInfo], ), diff --git a/generated_for_cmake/google/protobuf/descriptor.upb.h b/generated_for_cmake/google/protobuf/descriptor.upb.h index 681614910e..5baad08810 100644 --- a/generated_for_cmake/google/protobuf/descriptor.upb.h +++ b/generated_for_cmake/google/protobuf/descriptor.upb.h @@ -9,7 +9,6 @@ #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ #define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ -#include "upb/generated_util.h" #include "upb/msg.h" #include "upb/decode.h" #include "upb/encode.h" @@ -157,7 +156,7 @@ typedef enum { /* google.protobuf.FileDescriptorSet */ UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) { - return (google_protobuf_FileDescriptorSet *)upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena); + return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena); } UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size, upb_arena *arena) { @@ -174,10 +173,10 @@ UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorS return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) { - return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) { - struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); + struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -187,7 +186,7 @@ UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescr /* google.protobuf.FileDescriptorProto */ UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_FileDescriptorProto *)upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); + return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -228,20 +227,20 @@ UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(g return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len); } UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_STRING, arena); } UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(36, 72), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(36, 72), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, + arena); } UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) { return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len); } UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -251,10 +250,10 @@ UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorP return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len); } UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(44, 88), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -264,10 +263,10 @@ UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescript return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len); } UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 96), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 96), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); + struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(48, 96), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -277,10 +276,10 @@ UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptor return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len); } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 104), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 104), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(52, 104), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -293,7 +292,7 @@ UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_ 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); if (sub == NULL) { - sub = (struct google_protobuf_FileOptions*)upb_msg_new(&google_protobuf_FileOptions_msginit, arena); + sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena); if (!sub) return NULL; google_protobuf_FileDescriptorProto_set_options(msg, sub); } @@ -306,7 +305,7 @@ UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_ 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); if (sub == NULL) { - sub = (struct google_protobuf_SourceCodeInfo*)upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); + sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); if (!sub) return NULL; google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub); } @@ -316,21 +315,21 @@ UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependenc return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len); } UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(56, 112), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(56, 112), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(56, 112), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(56, 112), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len); } UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(60, 120), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(60, 120), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(60, 120), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(60, 120), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 3); @@ -340,7 +339,7 @@ UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_F /* google.protobuf.DescriptorProto */ UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) { - return (google_protobuf_DescriptorProto *)upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -372,10 +371,10 @@ UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProt return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -385,10 +384,10 @@ UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mut return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -398,10 +397,10 @@ UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(24, 48), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -411,10 +410,10 @@ UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_Desc return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); } UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); + struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(28, 56), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -424,10 +423,10 @@ UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProt return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len); } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 64), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 64), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(32, 64), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -440,7 +439,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_Desc 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); if (sub == NULL) { - sub = (struct google_protobuf_MessageOptions*)upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); + sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); if (!sub) return NULL; google_protobuf_DescriptorProto_set_options(msg, sub); } @@ -450,10 +449,10 @@ UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProt return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len); } UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); + struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(36, 72), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -463,10 +462,10 @@ UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_Descr return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len); } UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); + struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -476,17 +475,17 @@ UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(go return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len); } UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_STRING, arena); } UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(44, 88), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(44, 88), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, + arena); } /* google.protobuf.DescriptorProto.ExtensionRange */ UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) { - return (google_protobuf_DescriptorProto_ExtensionRange *)upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); + return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); } UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size, upb_arena *arena) { @@ -519,7 +518,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(googl 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); if (sub == NULL) { - sub = (struct google_protobuf_ExtensionRangeOptions*)upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); + sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); if (!sub) return NULL; google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub); } @@ -529,7 +528,7 @@ UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_Descrip /* google.protobuf.DescriptorProto.ReservedRange */ UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) { - return (google_protobuf_DescriptorProto_ReservedRange *)upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); + return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); } UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size, upb_arena *arena) { @@ -557,7 +556,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_pro /* google.protobuf.ExtensionRangeOptions */ UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) { - return (google_protobuf_ExtensionRangeOptions *)upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); + return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); } UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -574,10 +573,10 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeO return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -587,7 +586,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_Extension /* google.protobuf.FieldDescriptorProto */ UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_FieldDescriptorProto *)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -654,7 +653,7 @@ UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf 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); if (sub == NULL) { - sub = (struct google_protobuf_FieldOptions*)upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); + sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); if (!sub) return NULL; google_protobuf_FieldDescriptorProto_set_options(msg, sub); } @@ -672,7 +671,7 @@ UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protob /* google.protobuf.OneofDescriptorProto */ UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_OneofDescriptorProto *)upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); + return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -699,7 +698,7 @@ UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf 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); if (sub == NULL) { - sub = (struct google_protobuf_OneofOptions*)upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); + sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); if (!sub) return NULL; google_protobuf_OneofDescriptorProto_set_options(msg, sub); } @@ -709,7 +708,7 @@ UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorP /* google.protobuf.EnumDescriptorProto */ UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto *)upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -736,10 +735,10 @@ UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescri return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); + struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -752,7 +751,7 @@ UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_ 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); if (sub == NULL) { - sub = (struct google_protobuf_EnumOptions*)upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); + sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); if (!sub) return NULL; google_protobuf_EnumDescriptorProto_set_options(msg, sub); } @@ -762,10 +761,10 @@ UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protob return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); + struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -775,17 +774,17 @@ UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_nam return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { - return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_STRING, arena); } UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(24, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, + arena); } /* google.protobuf.EnumDescriptorProto.EnumReservedRange */ UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); + return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); } UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size, upb_arena *arena) { @@ -813,7 +812,7 @@ UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(go /* google.protobuf.EnumValueDescriptorProto */ UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_EnumValueDescriptorProto *)upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); + return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -846,7 +845,7 @@ UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_prot 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); if (sub == NULL) { - sub = (struct google_protobuf_EnumValueOptions*)upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); + sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); if (!sub) return NULL; google_protobuf_EnumValueDescriptorProto_set_options(msg, sub); } @@ -856,7 +855,7 @@ UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDes /* google.protobuf.ServiceDescriptorProto */ UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_ServiceDescriptorProto *)upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); + return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -881,10 +880,10 @@ UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescri return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); + struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -897,7 +896,7 @@ UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protob 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); if (sub == NULL) { - sub = (struct google_protobuf_ServiceOptions*)upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); + sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); if (!sub) return NULL; google_protobuf_ServiceDescriptorProto_set_options(msg, sub); } @@ -907,7 +906,7 @@ UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescrip /* google.protobuf.MethodDescriptorProto */ UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_MethodDescriptorProto *)upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); + return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -950,7 +949,7 @@ UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobu 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); if (sub == NULL) { - sub = (struct google_protobuf_MethodOptions*)upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); + sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); if (!sub) return NULL; google_protobuf_MethodDescriptorProto_set_options(msg, sub); } @@ -968,7 +967,7 @@ UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(googl /* google.protobuf.FileOptions */ UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) { - return (google_protobuf_FileOptions *)upb_msg_new(&google_protobuf_FileOptions_msginit, arena); + return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena); } UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1105,10 +1104,10 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mut return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 192), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(108, 192), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(108, 192), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(108, 192), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1118,7 +1117,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptio /* google.protobuf.MessageOptions */ UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) { - return (google_protobuf_MessageOptions *)upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); + return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); } UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1159,10 +1158,10 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_ return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(8, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(8, 8), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(8, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1172,7 +1171,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOp /* google.protobuf.FieldOptions */ UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) { - return (google_protobuf_FieldOptions *)upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); + return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); } UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1225,10 +1224,10 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mu return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 32), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(28, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1238,7 +1237,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOpti /* google.protobuf.OneofOptions */ UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) { - return (google_protobuf_OneofOptions *)upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); + return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); } UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1255,10 +1254,10 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mu return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1268,7 +1267,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOpti /* google.protobuf.EnumOptions */ UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) { - return (google_protobuf_EnumOptions *)upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); + return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); } UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1297,10 +1296,10 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mut return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1310,7 +1309,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptio /* google.protobuf.EnumValueOptions */ UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) { - return (google_protobuf_EnumValueOptions *)upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); + return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); } UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1333,10 +1332,10 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOption return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1346,7 +1345,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValue /* google.protobuf.ServiceOptions */ UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) { - return (google_protobuf_ServiceOptions *)upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); + return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); } UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1369,10 +1368,10 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_ return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1382,7 +1381,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOp /* google.protobuf.MethodOptions */ UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) { - return (google_protobuf_MethodOptions *)upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); + return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); } UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1411,10 +1410,10 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_m return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 24), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(20, 24), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1424,7 +1423,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOpt /* google.protobuf.UninterpretedOption */ UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) { - return (google_protobuf_UninterpretedOption *)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); } UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1453,10 +1452,10 @@ UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_Uninte return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len); } UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 80), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); + struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(56, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1490,7 +1489,7 @@ UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_p /* google.protobuf.UninterpretedOption.NamePart */ UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) { - return (google_protobuf_UninterpretedOption_NamePart *)upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); + return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); } UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1518,7 +1517,7 @@ UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(go /* google.protobuf.SourceCodeInfo */ UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) { - return (google_protobuf_SourceCodeInfo *)upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); + return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); } UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1535,10 +1534,10 @@ UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeI return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) { - return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) { - struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); + struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1548,7 +1547,7 @@ UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_Sourc /* google.protobuf.SourceCodeInfo.Location */ UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) { - return (google_protobuf_SourceCodeInfo_Location *)upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); + return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); } UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1571,21 +1570,21 @@ UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_ return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(20, 40), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(20, 40), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(24, 48), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) { _upb_sethas(msg, 1); @@ -1599,17 +1598,17 @@ UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_ return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); } UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { - return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_STRING, arena); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(28, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(28, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, + arena); } /* google.protobuf.GeneratedCodeInfo */ UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) { - return (google_protobuf_GeneratedCodeInfo *)upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena); + return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena); } UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1626,10 +1625,10 @@ UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_Genera return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) { - return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) { - struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); + struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1639,7 +1638,7 @@ UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_ /* google.protobuf.GeneratedCodeInfo.Annotation */ UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) { - return (google_protobuf_GeneratedCodeInfo_Annotation *)upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); + return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); } UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1662,11 +1661,11 @@ UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(go return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len); } UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(20, 32), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(20, 32), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) { _upb_sethas(msg, 3); diff --git a/tests/bindings/googlepb/test_vs_proto2.cc b/tests/bindings/googlepb/test_vs_proto2.cc deleted file mode 100644 index ac447e1b0c..0000000000 --- a/tests/bindings/googlepb/test_vs_proto2.cc +++ /dev/null @@ -1,165 +0,0 @@ -/* - * - * A test that verifies that our results are identical to proto2 for a - * given proto type and input protobuf. - */ - -#define __STDC_LIMIT_MACROS // So we get UINT32_MAX -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tests/google_messages.pb.h" -#include "tests/upb_test.h" -#include "upb/bindings/googlepb/bridge.h" -#include "upb/def.h" -#include "upb/handlers.h" -#include "upb/pb/decoder.h" -#include "upb/pb/glue.h" -#include "upb/pb/varint.int.h" - -// Pull in string data from tests/google_message{1,2}.dat -// (the .h files are generated with xxd). -const unsigned char message1_data[] = { -#include "tests/google_message1.h" -}; - -const unsigned char message2_data[] = { -#include "tests/google_message2.h" -}; - -void compare_metadata(const google::protobuf::Descriptor* d, - const upb::MessageDef *upb_md) { - ASSERT(d->field_count() == upb_md->field_count()); - for (upb::MessageDef::const_field_iterator i = upb_md->field_begin(); - i != upb_md->field_end(); ++i) { - const upb::FieldDef* upb_f = *i; - const google::protobuf::FieldDescriptor *proto2_f = - d->FindFieldByNumber(upb_f->number()); - ASSERT(upb_f); - ASSERT(proto2_f); - ASSERT(upb_f->number() == (uint32_t)proto2_f->number()); - ASSERT(std::string(upb_f->name()) == proto2_f->name()); - ASSERT(upb_f->descriptor_type() == - static_cast(proto2_f->type())); - ASSERT(upb_f->IsSequence() == proto2_f->is_repeated()); - } -} - -void print_diff(const google::protobuf::Message& msg1, - const google::protobuf::Message& msg2) { - std::string text_str1; - std::string text_str2; - google::protobuf::TextFormat::PrintToString(msg1, &text_str1); - google::protobuf::TextFormat::PrintToString(msg2, &text_str2); - fprintf(stderr, "str1: %s, str2: %s\n", text_str1.c_str(), text_str2.c_str()); -} - -void parse_and_compare(google::protobuf::Message *msg1, - google::protobuf::Message *msg2, - const upb::Handlers *protomsg_handlers, - const char *str, size_t len, bool allow_jit) { - // Parse to both proto2 and upb. - ASSERT(msg1->ParseFromArray(str, len)); - - upb::pb::CodeCache cache; - ASSERT(cache.set_allow_jit(allow_jit)); - upb::reffed_ptr decoder_method( - cache.GetDecoderMethod(upb::pb::DecoderMethodOptions(protomsg_handlers))); - - upb::Status status; - upb::Environment env; - env.ReportErrorsTo(&status); - upb::Sink protomsg_sink(protomsg_handlers, msg2); - upb::pb::Decoder* decoder = - upb::pb::Decoder::Create(&env, decoder_method.get(), &protomsg_sink); - - msg2->Clear(); - bool ok = upb::BufferSource::PutBuffer(str, len, decoder->input()); - if (!ok) { - fprintf(stderr, "error parsing: %s\n", status.error_message()); - print_diff(*msg1, *msg2); - } - ASSERT(ok); - ASSERT(status.ok()); - - // Would like to just compare the message objects themselves, but - // unfortunately MessageDifferencer is not part of the open-source release of - // proto2, so we compare their serialized strings, which we expect will be - // equivalent. - std::string str1; - std::string str2; - msg1->SerializeToString(&str1); - msg2->SerializeToString(&str2); - if (str1 != str2) { - print_diff(*msg1, *msg2); - } - ASSERT(str1 == str2); - ASSERT(std::string(str, len) == str2); -} - -void test_zig_zag() { - for (uint64_t num = 5; num * 1.5 < UINT64_MAX; num *= 1.5) { - ASSERT(upb_zzenc_64(num) == - google::protobuf::internal::WireFormatLite::ZigZagEncode64(num)); - if (num < UINT32_MAX) { - ASSERT(upb_zzenc_32(num) == - google::protobuf::internal::WireFormatLite::ZigZagEncode32(num)); - } - } - -} - -extern "C" { - -int run_tests(int argc, char *argv[]) { - UPB_UNUSED(argc); - UPB_UNUSED(argv); - UPB_UNUSED(message1_data); - UPB_UNUSED(message2_data); - size_t len = sizeof(MESSAGE_DATA_IDENT); - const char *str = (const char*)MESSAGE_DATA_IDENT; - - MESSAGE_CIDENT msg1; - MESSAGE_CIDENT msg2; - - upb::reffed_ptr h( - upb::googlepb::WriteHandlers::New(msg1)); - - compare_metadata(msg1.GetDescriptor(), h->message_def()); - - // Run twice to test proper object reuse. - parse_and_compare(&msg1, &msg2, h.get(), str, len, false); - parse_and_compare(&msg1, &msg2, h.get(), str, len, true); - parse_and_compare(&msg1, &msg2, h.get(), str, len, false); - parse_and_compare(&msg1, &msg2, h.get(), str, len, true); - - // Test with DynamicMessage. - google::protobuf::DynamicMessageFactory* factory = - new google::protobuf::DynamicMessageFactory; - const google::protobuf::Message* prototype = - factory->GetPrototype(msg1.descriptor()); - google::protobuf::Message* dyn_msg1 = prototype->New(); - google::protobuf::Message* dyn_msg2 = prototype->New(); - h = upb::googlepb::WriteHandlers::New(*dyn_msg1); - parse_and_compare(dyn_msg1, dyn_msg2, h.get(), str, len, false); - parse_and_compare(dyn_msg1, dyn_msg2, h.get(), str, len, true); - delete dyn_msg1; - delete dyn_msg2; - delete factory; - - test_zig_zag(); - - printf("All tests passed, %d assertions.\n", num_assertions); - - google::protobuf::ShutdownProtobufLibrary(); - return 0; -} - -} diff --git a/tests/bindings/lua/main.c b/tests/bindings/lua/main.c new file mode 100644 index 0000000000..5b501738c1 --- /dev/null +++ b/tests/bindings/lua/main.c @@ -0,0 +1,56 @@ + +#include +#include +#include +#include + +#include "upb/bindings/lua/upb.h" + +lua_State *L; + +static void interrupt(lua_State *L, lua_Debug *ar) { + (void)ar; + lua_sethook(L, NULL, 0, 0); + luaL_error(L, "SIGINT"); +} + +static void sighandler(int i) { + fprintf(stderr, "Signal!\n"); + signal(i, SIG_DFL); + lua_sethook(L, interrupt, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + +const char *init = + "package.preload['lupb'] = ... " + "package.path = '" + "./?.lua;" + "./third_party/lunit/?.lua;" + "external/com_google_protobuf/?.lua;" + "external/com_google_protobuf/src/?.lua;" + "bazel-bin/external/com_google_protobuf/src/?.lua;" + "bazel-bin/external/com_google_protobuf/?.lua;" + "upb/bindings/lua/?.lua" + "'"; + +int main() { + int ret = 0; + L = luaL_newstate(); + luaL_openlibs(L); + lua_pushcfunction(L, luaopen_lupb); + ret = luaL_loadstring(L, init); + lua_pushcfunction(L, luaopen_lupb); + + signal(SIGINT, sighandler); + ret = ret || + lua_pcall(L, 1, LUA_MULTRET, 0) || + luaL_dofile(L, "tests/bindings/lua/test_upb.lua"); + signal(SIGINT, SIG_DFL); + + if (ret) { + fprintf(stderr, "error testing Lua: %s\n", lua_tostring(L, -1)); + ret = 1; + } + + lua_close(L); + return ret; +} diff --git a/tests/bindings/lua/test_upb.lua b/tests/bindings/lua/test_upb.lua index e4edda4003..25ec0c1721 100644 --- a/tests/bindings/lua/test_upb.lua +++ b/tests/bindings/lua/test_upb.lua @@ -1,6 +1,8 @@ -local upb = require "upb" +local upb = require "lupb" local lunit = require "lunit" +local test_messages_proto3 = require "google.protobuf.test_messages_proto3_pb" +local descriptor = require "google.protobuf.descriptor_pb" if _VERSION >= 'Lua 5.2' then _ENV = lunit.module("testupb", "seeall") @@ -16,460 +18,259 @@ function iter_to_array(iter) return arr end -function test_msgdef() - local f2 = upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32} - local o = upb.OneofDef{name = "field1", fields = {f2}} - local f = upb.FieldDef{name = "field3", number = 2, type = upb.TYPE_INT32} - - local m = upb.MessageDef{fields = {o, f}} - - assert_equal(f, m:lookup_name("field3")) - assert_equal(o, m:lookup_name("field1")) - assert_equal(f2, m:lookup_name("field2")) -end - -function test_fielddef() - local f = upb.FieldDef() - assert_false(f:is_frozen()) - assert_nil(f:number()) - assert_nil(f:name()) - assert_nil(f:type()) +function test_def_readers() + local m = test_messages_proto3.TestAllTypesProto3 + assert_equal("TestAllTypesProto3", m:name()) + assert_equal("protobuf_test_messages.proto3.TestAllTypesProto3", m:full_name()) + + -- field + local f = m:field("optional_int32") + local f2 = m:field(1) + assert_equal(f, f2) + assert_equal(1, f:number()) + assert_equal("optional_int32", f:name()) assert_equal(upb.LABEL_OPTIONAL, f:label()) + assert_equal(upb.DESCRIPTOR_TYPE_INT32, f:descriptor_type()) + assert_equal(upb.TYPE_INT32, f:type()) + assert_nil(f:containing_oneof()) + assert_equal(m, f:containing_type()) + assert_equal(0, f:default()) + + -- enum + local e = test_messages_proto3['TestAllTypesProto3.NestedEnum'] + assert_true(#e > 3 and #e < 10) + assert_equal(2, e:value("BAZ")) +end - f:set_name("foo_field") - f:set_number(3) - f:set_label(upb.LABEL_REPEATED) - f:set_type(upb.TYPE_FLOAT) - - assert_equal("foo_field", f:name()) - assert_equal(3, f:number()) - assert_equal(upb.LABEL_REPEATED, f:label()) - assert_equal(upb.TYPE_FLOAT, f:type()) - - local f2 = upb.FieldDef{ - name = "foo", number = 5, type = upb.TYPE_DOUBLE, label = upb.LABEL_REQUIRED - } - - assert_equal("foo", f2:name()) - assert_equal(5, f2:number()) - assert_equal(upb.TYPE_DOUBLE, f2:type()) - assert_equal(upb.LABEL_REQUIRED, f2:label()) +function test_msg_map() + msg = test_messages_proto3.TestAllTypesProto3() + msg.map_int32_int32[5] = 10 + msg.map_int32_int32[6] = 12 + assert_equal(10, msg.map_int32_int32[5]) + assert_equal(12, msg.map_int32_int32[6]) + + -- Test overwrite. + msg.map_int32_int32[5] = 20 + assert_equal(20, msg.map_int32_int32[5]) + assert_equal(12, msg.map_int32_int32[6]) + msg.map_int32_int32[5] = 10 + + -- Test delete. + msg.map_int32_int32[5] = nil + assert_nil(msg.map_int32_int32[5]) + assert_equal(12, msg.map_int32_int32[6]) + msg.map_int32_int32[5] = 10 + + local serialized = upb.encode(msg) + assert_true(#serialized > 0) + local msg2 = upb.decode(test_messages_proto3.TestAllTypesProto3, serialized) + assert_equal(10, msg2.map_int32_int32[5]) + assert_equal(12, msg2.map_int32_int32[6]) end -function test_enumdef() - local e = upb.EnumDef() - assert_equal(0, #e) - assert_nil(e:value(5)) - assert_nil(e:value("NONEXISTENT_NAME")) +function test_msg_string_map() + msg = test_messages_proto3.TestAllTypesProto3() + msg.map_string_string["foo"] = "bar" + msg.map_string_string["baz"] = "quux" + assert_nil(msg.map_string_string["abc"]) + assert_equal("bar", msg.map_string_string["foo"]) + assert_equal("quux", msg.map_string_string["baz"]) + + -- Test overwrite. + msg.map_string_string["foo"] = "123" + assert_equal("123", msg.map_string_string["foo"]) + assert_equal("quux", msg.map_string_string["baz"]) + msg.map_string_string["foo"] = "bar" + + -- Test delete + msg.map_string_string["foo"] = nil + assert_nil(msg.map_string_string["foo"]) + assert_equal("quux", msg.map_string_string["baz"]) + msg.map_string_string["foo"] = "bar" + + local serialized = upb.encode(msg) + assert_true(#serialized > 0) + local msg2 = upb.decode(test_messages_proto3.TestAllTypesProto3, serialized) + assert_equal("bar", msg2.map_string_string["foo"]) + assert_equal("quux", msg2.map_string_string["baz"]) +end - for name, value in e:values() do - fail() - end +function test_msg_array() + msg = test_messages_proto3.TestAllTypesProto3() - e:add("VAL1", 1) - e:add("VAL2", 2) + assert_not_nil(msg.repeated_int32) + assert_equal(msg.repeated_int32, msg.repeated_int32) + assert_equal(0, #msg.repeated_int32) - local values = {} - for name, value in e:values() do - values[name] = value - end + msg.repeated_int32[1] = 2 + assert_equal(1, #msg.repeated_int32); + assert_equal(2, msg.repeated_int32[1]); - assert_equal(1, values["VAL1"]) - assert_equal(2, values["VAL2"]) + -- Can't assign a scalar; array is expected. + assert_error_match("lupb.array expected", function() msg.repeated_int32 = 5 end) - local e2 = upb.EnumDef{ - values = { - {"FOO", 1}, - {"BAR", 77}, - } - } + -- Can't assign array of the wrong type. + local function assign_int64() + msg.repeated_int32 = upb.Array(upb.TYPE_INT64) + end + assert_error_match("array type mismatch", assign_int64) - assert_equal(1, e2:value("FOO")) - assert_equal(77, e2:value("BAR")) - assert_equal("FOO", e2:value(1)) - assert_equal("BAR", e2:value(77)) - - e2:freeze() - - local f = upb.FieldDef{type = upb.TYPE_ENUM} - - -- No default set and no EnumDef to get a default from. - assert_equal(f:default(), nil) - - f:set_subdef(upb.EnumDef()) - -- No default to pull in from the EnumDef. - assert_equal(f:default(), nil) - - f:set_subdef(e2) - -- First member added to e2. - assert_equal(f:default(), "FOO") - - f:set_subdef(nil) - assert_equal(f:default(), nil) - - f:set_default(1) - assert_equal(f:default(), 1) - - f:set_default("YOYOYO") - assert_equal(f:default(), "YOYOYO") - - f:set_subdef(e2) - f:set_default(1) - -- It prefers to return a string, and could resolve the explicit "1" we set - -- it to to the string value. - assert_equal(f:default(), "FOO") - - -- FieldDef can specify default value by name or number, but the value must - -- exist at freeze time. - local m1 = upb.build_defs{ - upb.MessageDef{ - full_name = "A", - fields = { - upb.FieldDef{ - name = "f1", - number = 1, - type = upb.TYPE_ENUM, - subdef = e2, - default = "BAR" - }, - upb.FieldDef{ - name = "f2", - number = 2, - type = upb.TYPE_ENUM, - subdef = e2, - default = 77 - } - } - } - } + local arr = upb.Array(upb.TYPE_INT32) + arr[1] = 6 + assert_equal(1, #arr) + msg.repeated_int32 = arr + assert_equal(msg.repeated_int32, msg.repeated_int32) + assert_equal(arr, msg.repeated_int32) + assert_equal(1, #msg.repeated_int32) + assert_equal(6, msg.repeated_int32[1]) - assert_equal(m1:field("f1"):default(), "BAR") - assert_equal(m1:field("f1"):default(), "BAR") - - assert_error_match( - "enum default for field A.f1 .DOESNT_EXIST. is not in the enum", - function() - local m1 = upb.build_defs{ - upb.MessageDef{ - full_name = "A", - fields = { - upb.FieldDef{ - name = "f1", - number = 1, - type = upb.TYPE_ENUM, - subdef = e2, - default = "DOESNT_EXIST" - } - } - } - } - end - ) - - assert_error_match( - "enum default for field A.f1 .142. is not in the enum", - function() - local m1 = upb.build_defs{ - upb.MessageDef{ - full_name = "A", - fields = { - upb.FieldDef{ - name = "f1", - number = 1, - type = upb.TYPE_ENUM, - subdef = e2, - default = 142 - } - } - } - } - end - ) + -- Can't assign other Lua types. + assert_error_match("array expected", function() msg.repeated_int32 = "abc" end) + assert_error_match("array expected", function() msg.repeated_int32 = true end) + assert_error_match("array expected", function() msg.repeated_int32 = false end) + assert_error_match("array expected", function() msg.repeated_int32 = nil end) + assert_error_match("array expected", function() msg.repeated_int32 = {} end) + assert_error_match("array expected", function() msg.repeated_int32 = print end) end -function test_empty_msgdef() - local md = upb.MessageDef() - assert_nil(md:full_name()) -- Def without name is anonymous. - assert_false(md:is_frozen()) - assert_equal(0, #md) - assert_nil(md:field("nonexistent_field")) - assert_nil(md:field(3)) - for field in md:fields() do - fail() - end +function test_msg_submsg() + --msg = test_messages_proto3.TestAllTypesProto3() + msg = test_messages_proto3['TestAllTypesProto3']() - upb.freeze(md) - assert_true(md:is_frozen()) - assert_equal(0, #md) - assert_nil(md:field("nonexistent_field")) - assert_nil(md:field(3)) - for field in md:fields() do - fail() - end -end + assert_nil(msg.optional_nested_message) -function test_msgdef_constructor() - local f1 = upb.FieldDef{name = "field1", number = 7, type = upb.TYPE_INT32} - local f2 = upb.FieldDef{name = "field2", number = 8, type = upb.TYPE_INT32} - local md = upb.MessageDef{ - full_name = "TestMessage", - fields = {f1, f2} - } - assert_equal("TestMessage", md:full_name()) - assert_false(md:is_frozen()) - assert_equal(2, #md) - assert_equal(f1, md:field("field1")) - assert_equal(f2, md:field("field2")) - assert_equal(f1, md:field(7)) - assert_equal(f2, md:field(8)) - local count = 0 - local found = {} - for field in md:fields() do - count = count + 1 - found[field] = true + -- Can't assign message of the wrong type. + local function assign_int64() + msg.optional_nested_message = test_messages_proto3.TestAllTypesProto3() end - assert_equal(2, count) - assert_true(found[f1]) - assert_true(found[f2]) + assert_error_match("message type mismatch", assign_int64) - upb.freeze(md) -end + local nested = test_messages_proto3['TestAllTypesProto3.NestedMessage']() + msg.optional_nested_message = nested + assert_equal(nested, msg.optional_nested_message) -function test_iteration() - -- Test that we cannot crash the process even if we modify the set of fields - -- during iteration. - local md = upb.MessageDef{full_name = "TestMessage"} - - for i=1,10 do - md:add(upb.FieldDef{ - name = "field" .. tostring(i), - number = 1000 - i, - type = upb.TYPE_INT32 - }) - end + -- Can't assign other Lua types. + assert_error_match("msg expected", function() msg.optional_nested_message = "abc" end) + assert_error_match("msg expected", function() msg.optional_nested_message = true end) + assert_error_match("msg expected", function() msg.optional_nested_message = false end) + assert_error_match("msg expected", function() msg.optional_nested_message = nil end) + assert_error_match("msg expected", function() msg.optional_nested_message = {} end) + assert_error_match("msg expected", function() msg.optional_nested_message = print end) +end - local add = #md - for f in md:fields() do - if add > 0 then - add = add - 1 - for i=10000,11000 do - local field_name = "field" .. tostring(i) - -- We want to add fields to the table to trigger a table resize, - -- but we must skip it if the field name or number already exists - -- otherwise it will raise an error. - if md:field(field_name) == nil and - md:field(i) == nil then - md:add(upb.FieldDef{ - name = field_name, - number = i, - type = upb.TYPE_INT32 - }) - end - end - end +-- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer +-- can be defined in Lua. +if _VERSION >= 'Lua 5.2' then + function defer(fn) + setmetatable({}, { __gc = fn }) end - - -- Test that iterators don't crash the process even if the MessageDef goes - -- out of scope. - -- - -- Note: have previously verified that this can indeed crash the process if - -- we do not explicitly add a reference from the iterator to the underlying - -- MessageDef. - local iter = md:fields() - md = nil - collectgarbage() - while iter() do +else + function defer(fn) + getmetatable(newproxy(true)).__gc = fn end +end - local ed = upb.EnumDef{ - values = { - {"FOO", 1}, - {"BAR", 77}, +function test_finalizer() + -- Tests that we correctly handle a call into an already-finalized object. + -- Collectible objects are finalized in the opposite order of creation. + do + local t = {} + defer(function() + assert_error_match("called into dead object", function() + -- Generic def call. + t[1]:lookup_msg("abc") + end) + end) + t = { + upb.SymbolTable(), } - } - iter = ed:values() - ed = nil - collectgarbage() - while iter() do end + collectgarbage() end -function test_msgdef_setters() - local md = upb.MessageDef() - md:set_full_name("Message1") - assert_equal("Message1", md:full_name()) - local f = upb.FieldDef{name = "field1", number = 3, type = upb.TYPE_DOUBLE} - md:add(f) - assert_equal(1, #md) - assert_equal(f, md:field("field1")) -end - -function test_msgdef_errors() - assert_error(function() upb.MessageDef{bad_initializer_key = 5} end) - local md = upb.MessageDef() - assert_error(function() - -- Duplicate field number. - upb.MessageDef{ - fields = { - upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32} - } - } - end) - assert_error(function() - -- Duplicate field name. - upb.MessageDef{ - fields = { - upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "field1", number = 2, type = upb.TYPE_INT32} - } - } - end) - - assert_error(function() - -- Duplicate field name. - upb.MessageDef{ - fields = { - upb.OneofDef{name = "field1", fields = { - upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32}, - }}, - upb.FieldDef{name = "field2", number = 2, type = upb.TYPE_INT32} - } - } - end) - - -- attempt to set a name with embedded NULLs. - assert_error_match("names cannot have embedded NULLs", function() - md:set_full_name("abc\0def") - end) - - upb.freeze(md) - -- Attempt to mutate frozen MessageDef. - assert_error_match("frozen", function() - md:add(upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}) - end) - assert_error_match("frozen", function() - md:set_full_name("abc") - end) - - -- Attempt to freeze a msgdef without freezing its subdef. - assert_error_match("is not frozen or being frozen", function() - m1 = upb.MessageDef() - upb.freeze( - upb.MessageDef{ - fields = { - upb.FieldDef{name = "f1", number = 1, type = upb.TYPE_MESSAGE, - subdef = m1} - } - } - ) - end) -end +-- in-range of 64-bit types but not exactly representable as double +local bad64 = 2^68 - 1 + +local numeric_types = { + [upb.TYPE_UINT32] = { + valid_val = 2^32 - 1, + too_big = 2^32, + too_small = -1, + other_bad = 5.1 + }, + [upb.TYPE_UINT64] = { + valid_val = 2^63, + too_big = 2^64, + too_small = -1, + other_bad = bad64 + }, + [upb.TYPE_INT32] = { + valid_val = 2^31 - 1, + too_big = 2^31, + too_small = -2^31 - 1, + other_bad = 5.1 + }, + -- Enums don't exist at a language level in Lua, so we just represent enum + -- values as int32s. + [upb.TYPE_ENUM] = { + valid_val = 2^31 - 1, + too_big = 2^31, + too_small = -2^31 - 1, + other_bad = 5.1 + }, + [upb.TYPE_INT64] = { + valid_val = 2^62, + too_big = 2^63, + too_small = -2^64, + other_bad = bad64 + }, + [upb.TYPE_FLOAT] = { + valid_val = 340282306073709652508363335590014353408 + }, + [upb.TYPE_DOUBLE] = { + valid_val = 10^101 + }, +} -function test_symtab() - local empty = upb.SymbolTable() - assert_equal(0, #iter_to_array(empty:defs(upb.DEF_ANY))) - assert_equal(0, #iter_to_array(empty:defs(upb.DEF_MSG))) - assert_equal(0, #iter_to_array(empty:defs(upb.DEF_ENUM))) - - local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "TestMessage"}, - upb.MessageDef{full_name = "ContainingMessage", fields = { - upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "field2", number = 2, type = upb.TYPE_MESSAGE, - subdef_name = ".TestMessage"} - } - } +function test_msg_primitives() + local msg = test_messages_proto3.TestAllTypesProto3{ + optional_int32 = 10, + optional_uint32 = 20, + optional_int64 = 30, + optional_uint64 = 40, + optional_double = 50, + optional_float = 60, + optional_sint32 = 70, + optional_sint64 = 80, + optional_fixed32 = 90, + optional_fixed64 = 100, + optional_sfixed32 = 110, + optional_sfixed64 = 120, + optional_bool = true, + optional_string = "abc", + optional_nested_message = test_messages_proto3['TestAllTypesProto3.NestedMessage']{a = 123}, } - local msgdef1 = symtab:lookup("TestMessage") - local msgdef2 = symtab:lookup("ContainingMessage") - assert_not_nil(msgdef1) - assert_not_nil(msgdef2) - assert_equal(msgdef1, msgdef2:field("field2"):subdef()) - assert_true(msgdef1:is_frozen()) - assert_true(msgdef2:is_frozen()) - - symtab:add{ - upb.MessageDef{full_name = "ContainingMessage2", fields = { - upb.FieldDef{name = "field5", number = 5, type = upb.TYPE_MESSAGE, - subdef = msgdef2} - } - } - } + -- Attempts to access non-existent fields fail. + assert_error_match("no such field", function() msg.no_such = 1 end) - local msgdef3 = symtab:lookup("ContainingMessage2") - assert_not_nil(msgdef3) - assert_equal(msgdef3:field("field5"):subdef(), msgdef2) + assert_equal(10, msg.optional_int32) + assert_equal(20, msg.optional_uint32) + assert_equal(30, msg.optional_int64) + assert_equal(40, msg.optional_uint64) + assert_equal(50, msg.optional_double) + assert_equal(60, msg.optional_float) + assert_equal(70, msg.optional_sint32) + assert_equal(80, msg.optional_sint64) + assert_equal(90, msg.optional_fixed32) + assert_equal(100, msg.optional_fixed64) + assert_equal(110, msg.optional_sfixed32) + assert_equal(120, msg.optional_sfixed64) + assert_equal(true, msg.optional_bool) + assert_equal("abc", msg.optional_string) + assert_equal(123, msg.optional_nested_message.a) end -function test_numeric_array() - local function test_for_numeric_type(upb_type, val, too_big, too_small, bad3) - local array = upb.Array(upb_type) - assert_equal(0, #array) - - -- 0 is never a valid index in Lua. - assert_error_match("array index", function() return array[0] end) - -- Past the end of the array. - assert_error_match("array index", function() return array[1] end) - - array[1] = val - assert_equal(val, array[1]) - assert_equal(1, #array) - assert_equal(val, array[1]) - -- Past the end of the array. - assert_error_match("array index", function() return array[2] end) - - array[2] = 10 - assert_equal(val, array[1]) - assert_equal(10, array[2]) - assert_equal(2, #array) - -- Past the end of the array. - assert_error_match("array index", function() return array[3] end) - - local n = 1 - for i, val in upb.ipairs(array) do - assert_equal(n, i) - n = n + 1 - assert_equal(array[i], val) - end - - -- Values that are out of range. - local errmsg = "not an integer or out of range" - if too_small then - assert_error_match(errmsg, function() array[3] = too_small end) - end - if too_big then - assert_error_match(errmsg, function() array[3] = too_big end) - end - if bad3 then - assert_error_match(errmsg, function() array[3] = bad3 end) - end - - -- Can't assign other Lua types. - errmsg = "bad argument #3" - assert_error_match(errmsg, function() array[3] = "abc" end) - assert_error_match(errmsg, function() array[3] = true end) - assert_error_match(errmsg, function() array[3] = false end) - assert_error_match(errmsg, function() array[3] = nil end) - assert_error_match(errmsg, function() array[3] = {} end) - assert_error_match(errmsg, function() array[3] = print end) - assert_error_match(errmsg, function() array[3] = array end) - end - - -- in-range of 64-bit types but not exactly representable as double - local bad64 = 2^68 - 1 - - test_for_numeric_type(upb.TYPE_UINT32, 2^32 - 1, 2^32, -1, 5.1) - test_for_numeric_type(upb.TYPE_UINT64, 2^63, 2^64, -1, bad64) - test_for_numeric_type(upb.TYPE_INT32, 2^31 - 1, 2^31, -2^31 - 1, 5.1) - -- Enums don't exist at a language level in Lua, so we just represent enum - -- values as int32s. - test_for_numeric_type(upb.TYPE_ENUM, 2^31 - 1, 2^31, -2^31 - 1, 5.1) - test_for_numeric_type(upb.TYPE_INT64, 2^62, 2^63, -2^64, bad64) - test_for_numeric_type(upb.TYPE_FLOAT, 340282306073709652508363335590014353408) - test_for_numeric_type(upb.TYPE_DOUBLE, 10^101) -end function test_string_array() local function test_for_string_type(upb_type) @@ -497,14 +298,6 @@ function test_string_array() -- Past the end of the array. assert_error_match("array index", function() return array[3] end) - local n = 1 - for i, val in upb.ipairs(array) do - assert_equal(n, i) - n = n + 1 - assert_equal(array[i], val) - end - assert_equal(3, n) - -- Can't assign other Lua types. assert_error_match("Expected string", function() array[3] = 123 end) assert_error_match("Expected string", function() array[3] = true end) @@ -519,228 +312,127 @@ function test_string_array() test_for_string_type(upb.TYPE_BYTES) end -function test_msg_primitives() - local function test_for_numeric_type(upb_type, val, too_big, too_small, bad3) - local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "TestMessage", fields = { - upb.FieldDef{name = "f", number = 1, type = upb_type}, - } - } - } - - factory = upb.MessageFactory(symtab) - TestMessage = factory:get_message_class("TestMessage") - msg = TestMessage() +function test_numeric_array() + local function test_for_numeric_type(upb_type) + local array = upb.Array(upb_type) + local vals = numeric_types[upb_type] + assert_equal(0, #array) - -- Defaults to zero - assert_equal(0, msg.f) + -- 0 is never a valid index in Lua. + assert_error_match("array index", function() return array[0] end) + -- Past the end of the array. + assert_error_match("array index", function() return array[1] end) - msg.f = 0 - assert_equal(0, msg.f) + array[1] = vals.valid_val + assert_equal(vals.valid_val, array[1]) + assert_equal(1, #array) + assert_equal(vals.valid_val, array[1]) + -- Past the end of the array. + assert_error_match("array index", function() return array[2] end) - msg.f = val - assert_equal(val, msg.f) + array[2] = 10 + assert_equal(vals.valid_val, array[1]) + assert_equal(10, array[2]) + assert_equal(2, #array) + -- Past the end of the array. + assert_error_match("array index", function() return array[3] end) + -- Values that are out of range. local errmsg = "not an integer or out of range" - if too_small then - assert_error_match(errmsg, function() msg.f = too_small end) + if vals.too_small then + assert_error_match(errmsg, function() array[3] = vals.too_small end) end - if too_big then - assert_error_match(errmsg, function() msg.f = too_big end) + if vals.too_big then + assert_error_match(errmsg, function() array[3] = vals.too_big end) end - if bad3 then - assert_error_match(errmsg, function() msg.f = bad3 end) + if vals.other_bad then + assert_error_match(errmsg, function() array[3] = vals.other_bad end) end -- Can't assign other Lua types. errmsg = "bad argument #3" - assert_error_match(errmsg, function() msg.f = "abc" end) - assert_error_match(errmsg, function() msg.f = true end) - assert_error_match(errmsg, function() msg.f = false end) - assert_error_match(errmsg, function() msg.f = nil end) - assert_error_match(errmsg, function() msg.f = {} end) - assert_error_match(errmsg, function() msg.f = print end) - assert_error_match(errmsg, function() msg.f = array end) + assert_error_match(errmsg, function() array[3] = "abc" end) + assert_error_match(errmsg, function() array[3] = true end) + assert_error_match(errmsg, function() array[3] = false end) + assert_error_match(errmsg, function() array[3] = nil end) + assert_error_match(errmsg, function() array[3] = {} end) + assert_error_match(errmsg, function() array[3] = print end) + assert_error_match(errmsg, function() array[3] = array end) end - local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "TestMessage", fields = { - upb.FieldDef{ - name = "i32", number = 1, type = upb.TYPE_INT32, default = 1}, - upb.FieldDef{ - name = "u32", number = 2, type = upb.TYPE_UINT32, default = 2}, - upb.FieldDef{ - name = "i64", number = 3, type = upb.TYPE_INT64, default = 3}, - upb.FieldDef{ - name = "u64", number = 4, type = upb.TYPE_UINT64, default = 4}, - upb.FieldDef{ - name = "dbl", number = 5, type = upb.TYPE_DOUBLE, default = 5}, - upb.FieldDef{ - name = "flt", number = 6, type = upb.TYPE_FLOAT, default = 6}, - upb.FieldDef{ - name = "bool", number = 7, type = upb.TYPE_BOOL, default = true}, - } - } - } - - factory = upb.MessageFactory(symtab) - TestMessage = factory:get_message_class("TestMessage") - msg = TestMessage() - - -- Unset member returns default value. - -- TODO(haberman): re-enable these when we have descriptor-based reflection. - -- assert_equal(1, msg.i32) - -- assert_equal(2, msg.u32) - -- assert_equal(3, msg.i64) - -- assert_equal(4, msg.u64) - -- assert_equal(5, msg.dbl) - -- assert_equal(6, msg.flt) - -- assert_equal(true, msg.bool) - - -- Attempts to access non-existent fields fail. - assert_error_match("no such field", function() msg.no_such = 1 end) - - msg.i32 = 10 - msg.u32 = 20 - msg.i64 = 30 - msg.u64 = 40 - msg.dbl = 50 - msg.flt = 60 - msg.bool = true - - assert_equal(10, msg.i32) - assert_equal(20, msg.u32) - assert_equal(30, msg.i64) - assert_equal(40, msg.u64) - assert_equal(50, msg.dbl) - assert_equal(60, msg.flt) - assert_equal(true, msg.bool) - - test_for_numeric_type(upb.TYPE_UINT32, 2^32 - 1, 2^32, -1, 5.1) - test_for_numeric_type(upb.TYPE_UINT64, 2^62, 2^64, -1, bad64) - test_for_numeric_type(upb.TYPE_INT32, 2^31 - 1, 2^31, -2^31 - 1, 5.1) - test_for_numeric_type(upb.TYPE_INT64, 2^61, 2^63, -2^64, bad64) - test_for_numeric_type(upb.TYPE_FLOAT, 2^20) - test_for_numeric_type(upb.TYPE_DOUBLE, 10^101) -end - -function test_msg_array() - local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "TestMessage", fields = { - upb.FieldDef{name = "i32_array", number = 1, type = upb.TYPE_INT32, - label = upb.LABEL_REPEATED}, - } - } - } - - factory = upb.MessageFactory(symtab) - TestMessage = factory:get_message_class("TestMessage") - msg = TestMessage() - - assert_nil(msg.i32_array) - - -- Can't assign a scalar; array is expected. - assert_error_match("lupb.array expected", function() msg.i32_array = 5 end) - - -- Can't assign array of the wrong type. - local function assign_int64() - msg.i32_array = upb.Array(upb.TYPE_INT64) + for k in pairs(numeric_types) do + test_for_numeric_type(k) end - assert_error_match("Array had incorrect type", assign_int64) - - local arr = upb.Array(upb.TYPE_INT32) - msg.i32_array = arr - assert_equal(arr, msg.i32_array) - - -- Can't assign other Lua types. - assert_error_match("array expected", function() msg.i32_array = "abc" end) - assert_error_match("array expected", function() msg.i32_array = true end) - assert_error_match("array expected", function() msg.i32_array = false end) - assert_error_match("array expected", function() msg.i32_array = nil end) - assert_error_match("array expected", function() msg.i32_array = {} end) - assert_error_match("array expected", function() msg.i32_array = print end) end -function test_msg_submsg() - local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "TestMessage", fields = { - upb.FieldDef{name = "submsg", number = 1, type = upb.TYPE_MESSAGE, - subdef_name = ".SubMessage"}, - } - }, - upb.MessageDef{full_name = "SubMessage"} - } +function test_numeric_map() + local function test_for_numeric_types(key_type, val_type) + local map = upb.Map(key_type, val_type) + local key_vals = numeric_types[key_type] + local val_vals = numeric_types[val_type] - factory = upb.MessageFactory(symtab) - TestMessage = factory:get_message_class("TestMessage") - SubMessage = factory:get_message_class("SubMessage") - msg = TestMessage() + assert_equal(0, #map) - assert_nil(msg.submsg) + -- Unset keys return nil + assert_nil(map[key_vals.valid_val]) - -- Can't assign message of the wrong type. - local function assign_int64() - msg.submsg = TestMessage() - end - assert_error_match("Message had incorrect type", assign_int64) + map[key_vals.valid_val] = val_vals.valid_val + assert_equal(1, #map) + assert_equal(val_vals.valid_val, map[key_vals.valid_val]) - local sub = SubMessage() - msg.submsg = sub - assert_equal(sub, msg.submsg) + i = 0 + for k, v in pairs(map) do + assert_equal(key_vals.valid_val, k) + assert_equal(val_vals.valid_val, v) + end - -- Can't assign other Lua types. - assert_error_match("msg expected", function() msg.submsg = "abc" end) - assert_error_match("msg expected", function() msg.submsg = true end) - assert_error_match("msg expected", function() msg.submsg = false end) - assert_error_match("msg expected", function() msg.submsg = nil end) - assert_error_match("msg expected", function() msg.submsg = {} end) - assert_error_match("msg expected", function() msg.submsg = print end) -end + -- Out of range key/val + local errmsg = "not an integer or out of range" + if key_vals.too_small then + assert_error_match(errmsg, function() map[key_vals.too_small] = 1 end) + end + if key_vals.too_big then + assert_error_match(errmsg, function() map[key_vals.too_big] = 1 end) + end + if key_vals.other_bad then + assert_error_match(errmsg, function() map[key_vals.other_bad] = 1 end) + end --- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer --- can be defined in Lua. -if _VERSION >= 'Lua 5.2' then - function defer(fn) - setmetatable({}, { __gc = fn }) + if val_vals.too_small then + assert_error_match(errmsg, function() map[1] = val_vals.too_small end) + end + if val_vals.too_big then + assert_error_match(errmsg, function() map[1] = val_vals.too_big end) + end + if val_vals.other_bad then + assert_error_match(errmsg, function() map[1] = val_vals.other_bad end) + end end -else - function defer(fn) - getmetatable(newproxy(true)).__gc = fn + + for k in pairs(numeric_types) do + for v in pairs(numeric_types) do + test_for_numeric_types(k, v) + end end end -function test_finalizer() - -- Tests that we correctly handle a call into an already-finalized object. - -- Collectible objects are finalized in the opposite order of creation. - do - local t = {} - defer(function() - assert_error_match("called into dead object", function() - -- Generic def call. - t[1]:full_name() - end) - assert_error_match("called into dead object", function() - -- Specific msgdef call. - t[1]:add() - end) - assert_error_match("called into dead object", function() - t[2]:values() - end) - assert_error_match("called into dead object", function() - t[3]:number() - end) - assert_error_match("called into dead object", function() - t[4]:lookup() - end) - end) - t = { - upb.MessageDef(), - upb.EnumDef(), - upb.FieldDef(), - upb.SymbolTable(), - } - end - collectgarbage() +function test_foo() + local symtab = upb.SymbolTable() + local filename = "external/com_google_protobuf/descriptor_proto-descriptor-set.proto.bin" + local file = io.open(filename, "rb") or io.open("bazel-bin/" .. filename, "rb") + assert_not_nil(file) + local descriptor = file:read("*a") + assert_true(#descriptor > 0) + symtab:add_set(descriptor) + local FileDescriptorSet = symtab:lookup_msg("google.protobuf.FileDescriptorSet") + assert_not_nil(FileDescriptorSet) + set = FileDescriptorSet() + assert_equal(#set.file, 0) + assert_error_match("lupb.array expected", function () set.file = 1 end) + + set = upb.decode(FileDescriptorSet, descriptor) + assert_equal(#set.file, 1) + assert_equal(set.file[1].name, "google/protobuf/descriptor.proto") end local stats = lunit.main() diff --git a/tests/bindings/lua/test_upb.pb.lua b/tests/bindings/lua/test_upb.pb.lua deleted file mode 100644 index ea6de09989..0000000000 --- a/tests/bindings/lua/test_upb.pb.lua +++ /dev/null @@ -1,80 +0,0 @@ - --- Require "pb" first to ensure that the transitive require of "upb" is --- handled properly by the "pb" module. -local pb = require "upb.pb" -local upb = require "upb" -local lunit = require "lunit" - -if _VERSION >= 'Lua 5.2' then - _ENV = lunit.module("testupb_pb", "seeall") -else - module("testupb_pb", lunit.testcase, package.seeall) -end - -local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "TestMessage", fields = { - upb.FieldDef{name = "i32", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "u32", number = 2, type = upb.TYPE_UINT32}, - upb.FieldDef{name = "i64", number = 3, type = upb.TYPE_INT64}, - upb.FieldDef{name = "u64", number = 4, type = upb.TYPE_UINT64}, - upb.FieldDef{name = "dbl", number = 5, type = upb.TYPE_DOUBLE}, - upb.FieldDef{name = "flt", number = 6, type = upb.TYPE_FLOAT}, - upb.FieldDef{name = "bool", number = 7, type = upb.TYPE_BOOL}, - } - } -} - -local factory = upb.MessageFactory(symtab); -local TestMessage = factory:get_message_class("TestMessage") - -function test_parse_primitive() - local binary_pb = - "\008\128\128\128\128\002\016\128\128\128\128\004\024\128\128" - .. "\128\128\128\128\128\002\032\128\128\128\128\128\128\128\001\041\000" - .. "\000\000\000\000\000\248\063\053\000\000\096\064\056\001" - local msg = TestMessage() - pb.decode(msg, binary_pb) - assert_equal(536870912, msg.i32) - assert_equal(1073741824, msg.u32) - assert_equal(1125899906842624, msg.i64) - assert_equal(562949953421312, msg.u64) - assert_equal(1.5, msg.dbl) - assert_equal(3.5, msg.flt) - assert_equal(true, msg.bool) - - local encoded = pb.encode(msg) - local msg2 = TestMessage() - pb.decode(msg2, encoded) - assert_equal(536870912, msg.i32) - assert_equal(1073741824, msg.u32) - assert_equal(1125899906842624, msg.i64) - assert_equal(562949953421312, msg.u64) - assert_equal(1.5, msg.dbl) - assert_equal(3.5, msg.flt) - assert_equal(true, msg.bool) -end - -function test_parse_string() - local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "TestMessage", fields = { - upb.FieldDef{name = "str", number = 1, type = upb.TYPE_STRING}, - } - } - } - - local factory = upb.MessageFactory(symtab); - local TestMessage = factory:get_message_class("TestMessage") - - local binary_pb = "\010\005Hello" - msg = TestMessage() - pb.decode(msg, binary_pb) - -- TODO(haberman): re-enable when this stuff works better. - -- assert_equal("Hello", msg.str) -end - - -local stats = lunit.main() - -if stats.failed > 0 or stats.errors > 0 then - error("One or more errors in test suite") -end diff --git a/tests/bindings/ruby/upb.rb b/tests/bindings/ruby/upb.rb deleted file mode 100644 index 3e06c1798c..0000000000 --- a/tests/bindings/ruby/upb.rb +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/ruby -# -# Tests for Ruby upb extension. - -require 'test/unit' -require 'set' -require 'upb' - -def get_descriptor - File.open("upb/descriptor/descriptor.pb").read -end - -def load_descriptor - symtab = Upb::SymbolTable.new - symtab.load_descriptor(get_descriptor()) - return symtab -end - -def get_message_class(name) - return Upb.get_message_class(load_descriptor().lookup(name)) -end - -class TestRubyExtension < Test::Unit::TestCase - def test_parsedescriptor - msgdef = load_descriptor.lookup("google.protobuf.FileDescriptorSet") - assert_instance_of(Upb::MessageDef, msgdef) - - file_descriptor_set = Upb.get_message_class(msgdef) - msg = file_descriptor_set.parse(get_descriptor()) - - # A couple message types we know should exist. - names = Set.new(["DescriptorProto", "FieldDescriptorProto"]) - - msg.file.each { |file| - file.message_type.each { |message_type| - names.delete(message_type.name) - } - } - - assert_equal(0, names.size) - end - - def test_parseserialize - field_descriptor_proto = get_message_class("google.protobuf.FieldDescriptorProto") - field_options = get_message_class("google.protobuf.FieldOptions") - - field = field_descriptor_proto.new - - field.name = "MyName" - field.number = 5 - field.options = field_options.new - field.options.packed = true - - serialized = Upb::Message.serialize(field) - - field2 = field_descriptor_proto.parse(serialized) - - assert_equal("MyName", field2.name) - assert_equal(5, field2.number) - assert_equal(true, field2.options.packed) - end -end diff --git a/tests/google_message1.dat b/tests/google_message1.dat deleted file mode 100644 index bc0f064cc2..0000000000 Binary files a/tests/google_message1.dat and /dev/null differ diff --git a/tests/google_message2.dat b/tests/google_message2.dat deleted file mode 100644 index 06c09441b9..0000000000 Binary files a/tests/google_message2.dat and /dev/null differ diff --git a/tests/google_messages.proto b/tests/google_messages.proto deleted file mode 100644 index 489c470732..0000000000 --- a/tests/google_messages.proto +++ /dev/null @@ -1,149 +0,0 @@ - -package benchmarks; - -option optimize_for = SPEED; - -enum Foo { - FOO_VALUE = 1; - FOO_VALUE2 = 2; -} - -message Simple { - message M2 { - optional int32 f1 = 1234567; - } - optional M2 m2 = 1; -} - -message SpeedMessage1 { - required string field1 = 1; - optional string field9 = 9; - optional string field18 = 18; - optional bool field80 = 80 [default=false]; - optional bool field81 = 81 [default=true]; - required int32 field2 = 2; - required int32 field3 = 3; - optional int32 field280 = 280; - optional int32 field6 = 6 [default=0]; - optional int64 field22 = 22; - optional string field4 = 4; - repeated fixed64 field5 = 5; - optional bool field59 = 59 [default=false]; - optional string field7 = 7; - optional int32 field16 = 16; - optional int32 field130 = 130 [default=0]; - optional bool field12 = 12 [default=true]; - optional bool field17 = 17 [default=true]; - optional bool field13 = 13 [default=true]; - optional bool field14 = 14 [default=true]; - optional int32 field104 = 104 [default=0]; - optional int32 field100 = 100 [default=0]; - optional int32 field101 = 101 [default=0]; - optional string field102 = 102; - optional string field103 = 103; - optional int32 field29 = 29 [default=0]; - optional bool field30 = 30 [default=false]; - optional int32 field60 = 60 [default=-1]; - optional int32 field271 = 271 [default=-1]; - optional int32 field272 = 272 [default=-1]; - optional int32 field150 = 150; - optional int32 field23 = 23 [default=0]; - optional bool field24 = 24 [default=false]; - optional int32 field25 = 25 [default=0]; - optional SpeedMessage1SubMessage field15 = 15; - optional bool field78 = 78; - optional int32 field67 = 67 [default=0]; - optional int32 field68 = 68; - optional int32 field128 = 128 [default=0]; - optional string field129 = 129 [default="xxxxxxxxxxxxxxxxxxxxx"]; - optional int32 field131 = 131 [default=0]; - optional Foo field132 = 132 [default=FOO_VALUE]; -} - -message SpeedMessage1SubMessage { - optional int32 field1 = 1 [default=0]; - optional int32 field2 = 2 [default=0]; - optional int32 field3 = 3 [default=0]; - optional string field15 = 15 [default="FOOBAR!"]; - optional bool field12 = 12 [default=true]; - optional int64 field13 = 13; - optional int64 field14 = 14; - optional int32 field16 = 16; - optional int32 field19 = 19 [default=2]; - optional bool field20 = 20 [default=true]; - optional bool field28 = 28 [default=true]; - optional fixed64 field21 = 21; - optional int32 field22 = 22; - optional bool field23 = 23 [ default=false ]; - optional bool field206 = 206 [default=false]; - optional fixed32 field203 = 203; - optional int32 field204 = 204; - optional string field205 = 205; - optional uint64 field207 = 207; - optional uint64 field300 = 300; -} - -message SpeedMessage2 { - optional string field1 = 1; - optional int64 field3 = 3; - optional int64 field4 = 4; - optional int64 field30 = 30; - optional bool field75 = 75 [default=false]; - optional string field6 = 6; - optional bytes field2 = 2; - optional int32 field21 = 21 [default=0]; - optional int32 field71 = 71; - optional float field25 = 25; - optional int32 field109 = 109 [default=0]; - optional int32 field210 = 210 [default=0]; - optional int32 field211 = 211 [default=0]; - optional int32 field212 = 212 [default=0]; - optional int32 field213 = 213 [default=0]; - optional int32 field216 = 216 [default=0]; - optional int32 field217 = 217 [default=0]; - optional int32 field218 = 218 [default=0]; - optional int32 field220 = 220 [default=0]; - optional int32 field221 = 221 [default=0]; - optional float field222 = 222 [default=0.0]; - optional int32 field63 = 63; - - repeated group Group1 = 10 { - required float field11 = 11; - optional float field26 = 26; - optional string field12 = 12; - optional string field13 = 13; - repeated string field14 = 14; - required uint64 field15 = 15; - optional int32 field5 = 5; - optional string field27 = 27; - optional int32 field28 = 28; - optional string field29 = 29; - optional string field16 = 16; - repeated string field22 = 22; - repeated int32 field73 = 73; - optional int32 field20 = 20 [default=0]; - optional string field24 = 24; - optional SpeedMessage2GroupedMessage field31 = 31; - } - repeated string field128 = 128; - optional int64 field131 = 131; - repeated string field127 = 127; - optional int32 field129 = 129; - repeated int64 field130 = 130; - optional bool field205 = 205 [default=false]; - optional bool field206 = 206 [default=false]; -} - -message SpeedMessage2GroupedMessage { - optional float field1 = 1; - optional float field2 = 2; - optional float field3 = 3 [default=0.0]; - optional bool field4 = 4; - optional bool field5 = 5; - optional bool field6 = 6 [default=true]; - optional bool field7 = 7 [default=false]; - optional float field8 = 8; - optional bool field9 = 9; - optional float field10 = 10; - optional int64 field11 = 11; -} diff --git a/tests/pb/test_varint.c b/tests/pb/test_varint.c index 95a04ab9b8..cdae9dba47 100644 --- a/tests/pb/test_varint.c +++ b/tests/pb/test_varint.c @@ -53,6 +53,13 @@ static void test_varint_for_num(upb_decoderet (*decoder)(const char*), ASSERT(upb_zzenc_64(upb_zzdec_64(num)) == num); } +/* Making up for the lack of 64-bit constants in C89. */ +static uint64_t make_u64(uint32_t high, uint32_t low) { + uint64_t ret = high; + ret = (ret << 32) | low; + return ret; +} + static void test_varint_decoder(upb_decoderet (*decoder)(const char*)) { #define TEST(bytes, expected_val) {\ size_t n = sizeof(bytes) - 1; /* for NULL */ \ @@ -74,18 +81,20 @@ static void test_varint_decoder(upb_decoderet (*decoder)(const char*)) { upb_decoderet r = decoder(twelvebyte_buf); ASSERT(r.p == NULL); - TEST("\x00", 0ULL); - TEST("\x01", 1ULL); - TEST("\x81\x14", 0xa01ULL); - TEST("\x81\x03", 0x181ULL); - TEST("\x81\x83\x07", 0x1c181ULL); - TEST("\x81\x83\x87\x0f", 0x1e1c181ULL); - TEST("\x81\x83\x87\x8f\x1f", 0x1f1e1c181ULL); - TEST("\x81\x83\x87\x8f\x9f\x3f", 0x1f9f1e1c181ULL); - TEST("\x81\x83\x87\x8f\x9f\xbf\x7f", 0x1fdf9f1e1c181ULL); - TEST("\x81\x83\x87\x8f\x9f\xbf\xff\x01", 0x3fdf9f1e1c181ULL); - TEST("\x81\x83\x87\x8f\x9f\xbf\xff\x81\x03", 0x303fdf9f1e1c181ULL); - TEST("\x81\x83\x87\x8f\x9f\xbf\xff\x81\x83\x07", 0x8303fdf9f1e1c181ULL); + TEST("\x00", 0UL); + TEST("\x01", 1UL); + TEST("\x81\x14", 0xa01UL); + TEST("\x81\x03", 0x181UL); + TEST("\x81\x83\x07", 0x1c181UL); + TEST("\x81\x83\x87\x0f", 0x1e1c181UL); + TEST("\x81\x83\x87\x8f\x1f", make_u64(0x1, 0xf1e1c181UL)); + TEST("\x81\x83\x87\x8f\x9f\x3f", make_u64(0x1f9, 0xf1e1c181UL)); + TEST("\x81\x83\x87\x8f\x9f\xbf\x7f", make_u64(0x1fdf9, 0xf1e1c181UL)); + TEST("\x81\x83\x87\x8f\x9f\xbf\xff\x01", make_u64(0x3fdf9, 0xf1e1c181UL)); + TEST("\x81\x83\x87\x8f\x9f\xbf\xff\x81\x03", + make_u64(0x303fdf9, 0xf1e1c181UL)); + TEST("\x81\x83\x87\x8f\x9f\xbf\xff\x81\x83\x07", + make_u64(0x8303fdf9, 0xf1e1c181UL)); #undef TEST for (num = 5; num * 1.5 < UINT64_MAX; num *= 1.5) { diff --git a/tests/test.proto.pb b/tests/test.proto.pb deleted file mode 100644 index a587fb1825..0000000000 Binary files a/tests/test.proto.pb and /dev/null differ diff --git a/tests/test_generated_code.c b/tests/test_generated_code.c new file mode 100644 index 0000000000..3d1f518b4c --- /dev/null +++ b/tests/test_generated_code.c @@ -0,0 +1,329 @@ +/* Test of generated code, with a special focus on features that are not used in + * descriptor.proto or conformance.proto (since these get some testing from + * upb/def.c and tests/conformance_upb.c, respectively). + */ + +#include "src/google/protobuf/test_messages_proto3.upb.h" +#include "tests/upb_test.h" + +const char test_str[] = "abcdefg"; +const char test_str2[] = "12345678910"; +const char test_str3[] = "rstlnezxcvbnm"; +const char test_str4[] = "just another test string"; + +const upb_strview test_str_view = {test_str, sizeof(test_str) - 1}; +const upb_strview test_str_view2 = {test_str2, sizeof(test_str2) - 1}; +const upb_strview test_str_view3 = {test_str3, sizeof(test_str3) - 1}; +const upb_strview test_str_view4 = {test_str4, sizeof(test_str4) - 1}; + +const int32_t test_int32 = 10; +const int32_t test_int32_2 = -20; +const int32_t test_int32_3 = 30; +const int32_t test_int32_4 = -40; + +static void test_scalars() { + upb_arena *arena = upb_arena_new(); + protobuf_test_messages_proto3_TestAllTypesProto3 *msg = + protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); + protobuf_test_messages_proto3_TestAllTypesProto3 *msg2; + upb_strview serialized; + + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_int32(msg, 10); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_int64(msg, 20); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_uint32(msg, 30); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_uint64(msg, 40); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_float(msg, 50.5); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_double(msg, 60.6); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_bool(msg, 1); + protobuf_test_messages_proto3_TestAllTypesProto3_set_optional_string( + msg, test_str_view); + + serialized.data = protobuf_test_messages_proto3_TestAllTypesProto3_serialize( + msg, arena, &serialized.size); + + msg2 = protobuf_test_messages_proto3_TestAllTypesProto3_parse( + serialized.data, serialized.size, arena); + + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_int32( + msg2) == 10); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_int64( + msg2) == 20); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint32( + msg2) == 30); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_uint64( + msg2) == 40); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_float( + msg2) == 50.5); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_double( + msg2) == 60.6); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_optional_bool( + msg2) == 1); + ASSERT(upb_strview_eql( + protobuf_test_messages_proto3_TestAllTypesProto3_optional_string(msg2), + test_str_view)); + + upb_arena_free(arena); +} + +static void check_string_map_empty( + protobuf_test_messages_proto3_TestAllTypesProto3 *msg) { + size_t iter; + + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_size( + msg) == 0); + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( + msg, &iter)); +} + +static void check_string_map_one_entry( + protobuf_test_messages_proto3_TestAllTypesProto3 *msg) { + const protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry + *const_ent; + size_t iter; + upb_strview str; + + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_size( + msg) == 1); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_get( + msg, test_str_view, &str)); + ASSERT(upb_strview_eql(str, test_str_view2)); + + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_get( + msg, test_str_view3, &str)); + + /* Test that iteration reveals a single k/v pair in the map. */ + iter = UPB_MAP_BEGIN; + const_ent = protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( + msg, &iter); + ASSERT(const_ent); + ASSERT(upb_strview_eql( + test_str_view, + protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_key( + const_ent))); + ASSERT(upb_strview_eql( + test_str_view2, + protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_value( + const_ent))); + + const_ent = protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( + msg, &iter); + ASSERT(!const_ent); +} + +static void test_string_map() { + upb_arena *arena = upb_arena_new(); + protobuf_test_messages_proto3_TestAllTypesProto3 *msg = + protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); + const protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry + *const_ent; + size_t iter, count; + + check_string_map_empty(msg); + + /* Set map[test_str_view] = test_str_view2 */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_set( + msg, test_str_view, test_str_view2, arena); + check_string_map_one_entry(msg); + + /* Deleting a non-existent key does nothing. */ + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_delete( + msg, test_str_view3)); + check_string_map_one_entry(msg); + + /* Deleting the key sets the map back to empty. */ + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_delete( + msg, test_str_view)); + check_string_map_empty(msg); + + /* Set two keys this time: + * map[test_str_view] = test_str_view2 + * map[test_str_view3] = test_str_view4 + */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_set( + msg, test_str_view, test_str_view2, arena); + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_set( + msg, test_str_view3, test_str_view4, arena); + + /* Test iteration */ + iter = UPB_MAP_BEGIN; + count = 0; + + while ( + (const_ent = + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_next( + msg, &iter)) != NULL) { + upb_strview key = + protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_key( + const_ent); + upb_strview val = + protobuf_test_messages_proto3_TestAllTypesProto3_MapStringStringEntry_value( + const_ent); + + count++; + if (upb_strview_eql(key, test_str_view)) { + ASSERT(upb_strview_eql(val, test_str_view2)); + } else { + ASSERT(upb_strview_eql(key, test_str_view3)); + ASSERT(upb_strview_eql(val, test_str_view4)); + } + } + + ASSERT(count == 2); + + /* Clearing the map goes back to empty. */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_string_string_clear(msg); + check_string_map_empty(msg); + + upb_arena_free(arena); +} + +static void check_int32_map_empty( + protobuf_test_messages_proto3_TestAllTypesProto3 *msg) { + size_t iter; + + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_size( + msg) == 0); + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( + msg, &iter)); +} + +static void check_int32_map_one_entry( + protobuf_test_messages_proto3_TestAllTypesProto3 *msg) { + const protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry + *const_ent; + size_t iter; + int32_t val; + + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_size( + msg) == 1); + ASSERT(protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_get( + msg, test_int32, &val)); + ASSERT(val == test_int32_2); + + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_get( + msg, test_int32_3, &val)); + + /* Test that iteration reveals a single k/v pair in the map. */ + iter = UPB_MAP_BEGIN; + const_ent = protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( + msg, &iter); + ASSERT(const_ent); + ASSERT( + test_int32 == + protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry_key( + const_ent)); + ASSERT( + test_int32_2 == + protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry_value( + const_ent)); + + const_ent = protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( + msg, &iter); + ASSERT(!const_ent); +} + +static void test_int32_map() { + upb_arena *arena = upb_arena_new(); + protobuf_test_messages_proto3_TestAllTypesProto3 *msg = + protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); + const protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry + *const_ent; + size_t iter, count; + + check_int32_map_empty(msg); + + /* Set map[test_int32] = test_int32_2 */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( + msg, test_int32, test_int32_2, arena); + check_int32_map_one_entry(msg); + + /* Deleting a non-existent key does nothing. */ + ASSERT( + !protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_delete( + msg, test_int32_3)); + check_int32_map_one_entry(msg); + + /* Deleting the key sets the map back to empty. */ + ASSERT( + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_delete( + msg, test_int32)); + check_int32_map_empty(msg); + + /* Set two keys this time: + * map[test_int32] = test_int32_2 + * map[test_int32_3] = test_int32_4 + */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( + msg, test_int32, test_int32_2, arena); + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( + msg, test_int32_3, test_int32_4, arena); + + /* Test iteration */ + iter = UPB_MAP_BEGIN; + count = 0; + + while ( + (const_ent = + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_next( + msg, &iter)) != NULL) { + int32_t key = + protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry_key( + const_ent); + int32_t val = + protobuf_test_messages_proto3_TestAllTypesProto3_MapInt32Int32Entry_value( + const_ent); + + count++; + if (key == test_int32) { + ASSERT(val == test_int32_2); + } else { + ASSERT(key == test_int32_3); + ASSERT(val == test_int32_4); + } + } + + ASSERT(count == 2); + + /* Clearing the map goes back to empty. */ + protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_clear(msg); + check_int32_map_empty(msg); + + upb_arena_free(arena); +} + +void test_repeated() { + upb_arena *arena = upb_arena_new(); + protobuf_test_messages_proto3_TestAllTypesProto3 *msg = + protobuf_test_messages_proto3_TestAllTypesProto3_new(arena); + size_t size; + const int *elems; + + protobuf_test_messages_proto3_TestAllTypesProto3_add_repeated_int32( + msg, 5, arena); + + elems = protobuf_test_messages_proto3_TestAllTypesProto3_repeated_int32( + msg, &size); + + ASSERT(size == 1); + ASSERT(elems[0] == 5); + + upb_arena_free(arena); +} + +int run_tests(int argc, char *argv[]) { + test_scalars(); + test_string_map(); + test_int32_map(); + test_repeated(); + return 0; +} diff --git a/tests/test_table.cc b/tests/test_table.cc index 063eb68cee..e19a74a50d 100644 --- a/tests/test_table.cc +++ b/tests/test_table.cc @@ -166,7 +166,8 @@ class StrTable { std::pair operator*() const { std::pair ret; - ret.first.assign(upb_strtable_iter_key(&iter_)); + upb_strview view = upb_strtable_iter_key(&iter_); + ret.first.assign(view.data, view.size); ret.second = upb_strtable_iter_value(&iter_); return ret; } diff --git a/tools/make_cmakelists.py b/tools/make_cmakelists.py index a4923c8da0..76e3ee1598 100755 --- a/tools/make_cmakelists.py +++ b/tools/make_cmakelists.py @@ -38,6 +38,8 @@ class BuildFileFunctions(object): def cc_library(self, **kwargs): if kwargs["name"] == "amalgamation" or kwargs["name"] == "upbc_generator": return + if kwargs["name"] == "lupb": + return files = kwargs.get("srcs", []) + kwargs.get("hdrs", []) found_files = [] for file in files: @@ -98,16 +100,7 @@ class BuildFileFunctions(object): def py_binary(self, **kwargs): pass - def lua_cclibrary(self, **kwargs): - pass - - def lua_library(self, **kwargs): - pass - - def lua_binary(self, **kwargs): - pass - - def lua_test(self, **kwargs): + def lua_proto_library(self, **kwargs): pass def sh_test(self, **kwargs): diff --git a/upb/bindings/lua/def.c b/upb/bindings/lua/def.c index a9ab9a89db..6dc6b1a575 100644 --- a/upb/bindings/lua/def.c +++ b/upb/bindings/lua/def.c @@ -15,97 +15,71 @@ #define LUPB_SYMTAB "lupb.symtab" #define LUPB_OBJCACHE "lupb.objcache" -#define CHK(pred) \ - do { \ - upb_status status; \ - upb_status_clear(&status); \ - pred; \ - lupb_checkstatus(L, &status); \ - } while (0) +static void lupb_symtab_pushwrapper(lua_State *L, int narg, const void *def, + const char *type); /* lupb_wrapper ***************************************************************/ -/* Wrappers around upb objects. */ +/* Wrappers around upb def objects. The userval contains a reference to the + * symtab. */ -/* Checks type; if it matches, pulls the pointer out of the wrapper. */ -void *lupb_checkwrapper(lua_State *L, int narg, const char *type) { - void *ud = lua_touserdata(L, narg); - void *ret; +#define LUPB_SYMTAB_INDEX 1 - if (!ud) { - luaL_typerror(L, narg, "upb wrapper"); - } - - memcpy(&ret, ud, sizeof(ret)); - if (!ret) { - luaL_error(L, "called into dead object"); - } +typedef struct { + const void* def; /* upb_msgdef, upb_enumdef, upb_oneofdef, etc. */ +} lupb_wrapper; - luaL_checkudata(L, narg, type); - return ret; +static const void *lupb_wrapper_check(lua_State *L, int narg, + const char *type) { + lupb_wrapper *w = luaL_checkudata(L, narg, type); + return w->def; } -void lupb_pushwrapper(lua_State *L, const void *obj, const char *type) { - void *ud; - - if (obj == NULL) { - lua_pushnil(L); - return; - } - - /* Lookup our cache in the registry (we don't put our objects in the registry - * directly because we need our cache to be a weak table). */ - lua_getfield(L, LUA_REGISTRYINDEX, LUPB_OBJCACHE); - UPB_ASSERT(!lua_isnil(L, -1)); /* Should have been created by luaopen_upb. */ - lua_pushlightuserdata(L, (void*)obj); - lua_rawget(L, -2); - /* Stack is now: objcache, cached value. */ - - if (lua_isnil(L, -1)) { - /* Remove bad cached value and push new value. */ - lua_pop(L, 1); - ud = lua_newuserdata(L, sizeof(*ud)); - memcpy(ud, &obj, sizeof(*ud)); - - luaL_getmetatable(L, type); - /* Should have been created by luaopen_upb. */ - lupb_assert(L, !lua_isnil(L, -1)); - lua_setmetatable(L, -2); - - /* Set it in the cache. */ - lua_pushlightuserdata(L, (void*)obj); - lua_pushvalue(L, -2); - lua_rawset(L, -4); - } - - lua_insert(L, -2); - lua_pop(L, 1); +static void lupb_wrapper_pushsymtab(lua_State *L, int narg) { + lua_getiuservalue(L, narg, LUPB_SYMTAB_INDEX); } -void lupb_msgdef_pushwrapper(lua_State *L, const upb_msgdef *m); -void lupb_oneofdef_pushwrapper(lua_State *L, const upb_oneofdef *o); -static void lupb_enumdef_pushwrapper(lua_State *L, const upb_enumdef *e); +/* lupb_wrapper_pushwrapper() + * + * For a given def wrapper at index |narg|, pushes a wrapper for the given |def| + * and the given |type|. The new wrapper will be part of the same symtab. */ +static void lupb_wrapper_pushwrapper(lua_State *L, int narg, const void *def, + const char *type) { + lupb_wrapper_pushsymtab(L, narg); + lupb_symtab_pushwrapper(L, -1, def, type); + lua_replace(L, -2); /* Remove symtab from stack. */ +} +/* lupb_msgdef_pushsubmsgdef() + * + * Pops the msgdef wrapper at the top of the stack and replaces it with a msgdef + * wrapper for field |f| of this msgdef. + */ +void lupb_msgdef_pushsubmsgdef(lua_State *L, const upb_fielddef *f) { + assert(luaL_testudata(L, -1, LUPB_MSGDEF)); + const upb_msgdef *m = upb_fielddef_msgsubdef(f); + assert(upb_fielddef_containingtype(f) == lupb_msgdef_check(L, -1)); + lupb_wrapper_pushwrapper(L, -1, m, LUPB_MSGDEF); + lua_replace(L, -2); /* Replace msgdef with submsgdef. */ +} /* lupb_fielddef **************************************************************/ -void lupb_fielddef_pushwrapper(lua_State *L, const upb_fielddef *f) { - lupb_pushwrapper(L, f, LUPB_FIELDDEF); -} - const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg) { - return lupb_checkwrapper(L, narg, LUPB_FIELDDEF); + return lupb_wrapper_check(L, narg, LUPB_FIELDDEF); } static int lupb_fielddef_containingoneof(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lupb_oneofdef_pushwrapper(L, upb_fielddef_containingoneof(f)); + const upb_oneofdef *o = upb_fielddef_containingoneof(f); + lupb_wrapper_pushwrapper(L, 1, o, LUPB_ONEOFDEF); return 1; } static int lupb_fielddef_containingtype(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lupb_msgdef_pushwrapper(L, upb_fielddef_containingtype(f)); + const upb_msgdef *m = upb_fielddef_containingtype(f); + lupb_wrapper_pushwrapper(L, 1, m, LUPB_MSGDEF); return 1; } @@ -146,17 +120,6 @@ static int lupb_fielddef_descriptortype(lua_State *L) { return 1; } -static int lupb_fielddef_getsel(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - upb_selector_t sel; - if (upb_handlers_getselector(f, luaL_checknumber(L, 2), &sel)) { - lua_pushinteger(L, sel); - return 1; - } else { - return 0; - } -} - static int lupb_fielddef_hassubdef(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); lua_pushboolean(L, upb_fielddef_hassubdef(f)); @@ -211,22 +174,21 @@ static int lupb_fielddef_packed(lua_State *L) { static int lupb_fielddef_msgsubdef(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lupb_msgdef_pushwrapper(L, upb_fielddef_msgsubdef(f)); + const upb_msgdef *m = upb_fielddef_msgsubdef(f); + lupb_wrapper_pushwrapper(L, 1, m, LUPB_MSGDEF); return 1; } static int lupb_fielddef_enumsubdef(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lupb_enumdef_pushwrapper(L, upb_fielddef_enumsubdef(f)); + const upb_enumdef *e = upb_fielddef_enumsubdef(f); + lupb_wrapper_pushwrapper(L, 1, e, LUPB_ENUMDEF); return 1; } static int lupb_fielddef_type(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - if (upb_fielddef_typeisset(f)) - lua_pushinteger(L, upb_fielddef_type(f)); - else - lua_pushnil(L); + lua_pushinteger(L, upb_fielddef_type(f)); return 1; } @@ -235,7 +197,6 @@ static const struct luaL_Reg lupb_fielddef_m[] = { {"containing_type", lupb_fielddef_containingtype}, {"default", lupb_fielddef_default}, {"descriptor_type", lupb_fielddef_descriptortype}, - {"getsel", lupb_fielddef_getsel}, {"has_subdef", lupb_fielddef_hassubdef}, {"index", lupb_fielddef_index}, {"is_extension", lupb_fielddef_isextension}, @@ -250,55 +211,64 @@ static const struct luaL_Reg lupb_fielddef_m[] = { {NULL, NULL} }; - /* lupb_oneofdef **************************************************************/ -void lupb_oneofdef_pushwrapper(lua_State *L, const upb_oneofdef *o) { - lupb_pushwrapper(L, o, LUPB_ONEOFDEF); -} - const upb_oneofdef *lupb_oneofdef_check(lua_State *L, int narg) { - return lupb_checkwrapper(L, narg, LUPB_ONEOFDEF); + return lupb_wrapper_check(L, narg, LUPB_ONEOFDEF); } static int lupb_oneofdef_containingtype(lua_State *L) { const upb_oneofdef *o = lupb_oneofdef_check(L, 1); - lupb_msgdef_pushwrapper(L, upb_oneofdef_containingtype(o)); + const upb_msgdef *m = upb_oneofdef_containingtype(o); + lupb_wrapper_pushwrapper(L, 1, m, LUPB_MSGDEF); return 1; } +/* lupb_oneofdef_field() + * + * Handles: + * oneof.field(field_number) + * oneof.field(field_name) + */ static int lupb_oneofdef_field(lua_State *L) { const upb_oneofdef *o = lupb_oneofdef_check(L, 1); - int type = lua_type(L, 2); const upb_fielddef *f; - if (type == LUA_TNUMBER) { - f = upb_oneofdef_itof(o, lua_tointeger(L, 2)); - } else if (type == LUA_TSTRING) { - f = upb_oneofdef_ntofz(o, lua_tostring(L, 2)); - } else { - const char *msg = lua_pushfstring(L, "number or string expected, got %s", - luaL_typename(L, 2)); - return luaL_argerror(L, 2, msg); + + switch (lua_type(L, 2)) { + case LUA_TNUMBER: + f = upb_oneofdef_itof(o, lua_tointeger(L, 2)); + break; + case LUA_TSTRING: + f = upb_oneofdef_ntofz(o, lua_tostring(L, 2)); + break; + default: { + const char *msg = lua_pushfstring(L, "number or string expected, got %s", + luaL_typename(L, 2)); + return luaL_argerror(L, 2, msg); + } } - lupb_fielddef_pushwrapper(L, f); + lupb_wrapper_pushwrapper(L, 1, f, LUPB_FIELDDEF); return 1; } static int lupb_oneofiter_next(lua_State *L) { upb_oneof_iter *i = lua_touserdata(L, lua_upvalueindex(1)); + const upb_fielddef *f; if (upb_oneof_done(i)) return 0; - lupb_fielddef_pushwrapper(L, upb_oneof_iter_field(i)); + f = upb_oneof_iter_field(i); upb_oneof_next(i); + lupb_symtab_pushwrapper(L, lua_upvalueindex(2), f, LUPB_FIELDDEF); return 1; } static int lupb_oneofdef_fields(lua_State *L) { const upb_oneofdef *o = lupb_oneofdef_check(L, 1); upb_oneof_iter *i = lua_newuserdata(L, sizeof(upb_oneof_iter)); + lupb_wrapper_pushsymtab(L, 1); upb_oneof_begin(i, o); - /* Need to guarantee that the msgdef outlives the iter. */ - lua_pushvalue(L, 1); + + /* Closure upvalues are: iter, symtab. */ lua_pushcclosure(L, &lupb_oneofiter_next, 2); return 1; } @@ -335,12 +305,8 @@ typedef struct { const upb_msgdef *md; } lupb_msgdef; -void lupb_msgdef_pushwrapper(lua_State *L, const upb_msgdef *m) { - lupb_pushwrapper(L, m, LUPB_MSGDEF); -} - const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg) { - return lupb_checkwrapper(L, narg, LUPB_MSGDEF); + return lupb_wrapper_check(L, narg, LUPB_MSGDEF); } static int lupb_msgdef_len(lua_State *L) { @@ -349,42 +315,73 @@ static int lupb_msgdef_len(lua_State *L) { return 1; } +/* lupb_msgdef_field() + * + * Handles: + * msg.field(field_number) -> fielddef + * msg.field(field_name) -> fielddef + */ static int lupb_msgdef_field(lua_State *L) { const upb_msgdef *m = lupb_msgdef_check(L, 1); - int type = lua_type(L, 2); const upb_fielddef *f; - if (type == LUA_TNUMBER) { - f = upb_msgdef_itof(m, lua_tointeger(L, 2)); - } else if (type == LUA_TSTRING) { - f = upb_msgdef_ntofz(m, lua_tostring(L, 2)); - } else { - const char *msg = lua_pushfstring(L, "number or string expected, got %s", - luaL_typename(L, 2)); - return luaL_argerror(L, 2, msg); + + switch (lua_type(L, 2)) { + case LUA_TNUMBER: + f = upb_msgdef_itof(m, lua_tointeger(L, 2)); + break; + case LUA_TSTRING: + f = upb_msgdef_ntofz(m, lua_tostring(L, 2)); + break; + default: { + const char *msg = lua_pushfstring(L, "number or string expected, got %s", + luaL_typename(L, 2)); + return luaL_argerror(L, 2, msg); + } } - lupb_fielddef_pushwrapper(L, f); + lupb_wrapper_pushwrapper(L, 1, f, LUPB_FIELDDEF); return 1; } +/* lupb_msgdef_lookupname() + * + * Handles: + * msg.lookup_name(name) -> fielddef or oneofdef + */ static int lupb_msgdef_lookupname(lua_State *L) { const upb_msgdef *m = lupb_msgdef_check(L, 1); const upb_fielddef *f; const upb_oneofdef *o; + if (!upb_msgdef_lookupnamez(m, lua_tostring(L, 2), &f, &o)) { lua_pushnil(L); } else if (o) { - lupb_oneofdef_pushwrapper(L, o); + lupb_wrapper_pushwrapper(L, 1, o, LUPB_ONEOFDEF); } else { - lupb_fielddef_pushwrapper(L, f); + lupb_wrapper_pushwrapper(L, 1, f, LUPB_FIELDDEF); } + + return 1; +} + +/* lupb_msgdef_name() + * + * Handles: + * msg.name() -> string + */ +static int lupb_msgdef_name(lua_State *L) { + const upb_msgdef *m = lupb_msgdef_check(L, 1); + lua_pushstring(L, upb_msgdef_name(m)); return 1; } static int lupb_msgfielditer_next(lua_State *L) { upb_msg_field_iter *i = lua_touserdata(L, lua_upvalueindex(1)); + const upb_fielddef *f; + if (upb_msg_field_done(i)) return 0; - lupb_fielddef_pushwrapper(L, upb_msg_iter_field(i)); + f = upb_msg_iter_field(i); + lupb_symtab_pushwrapper(L, lua_upvalueindex(2), f, LUPB_FIELDDEF); upb_msg_field_next(i); return 1; } @@ -392,27 +389,44 @@ static int lupb_msgfielditer_next(lua_State *L) { static int lupb_msgdef_fields(lua_State *L) { const upb_msgdef *m = lupb_msgdef_check(L, 1); upb_msg_field_iter *i = lua_newuserdata(L, sizeof(upb_msg_field_iter)); + lupb_wrapper_pushsymtab(L, 1); upb_msg_field_begin(i, m); - /* Need to guarantee that the msgdef outlives the iter. */ - lua_pushvalue(L, 1); + + /* Closure upvalues are: iter, symtab. */ lua_pushcclosure(L, &lupb_msgfielditer_next, 2); return 1; } +static int lupb_msgdef_file(lua_State *L) { + const upb_msgdef *m = lupb_msgdef_check(L, 1); + const upb_filedef *file = upb_msgdef_file(m); + lupb_wrapper_pushwrapper(L, 1, file, LUPB_FILEDEF); + return 1; +} + +static int lupb_msgdef_fullname(lua_State *L) { + const upb_msgdef *m = lupb_msgdef_check(L, 1); + lua_pushstring(L, upb_msgdef_fullname(m)); + return 1; +} + static int lupb_msgoneofiter_next(lua_State *L) { upb_msg_oneof_iter *i = lua_touserdata(L, lua_upvalueindex(1)); + const upb_oneofdef *o; if (upb_msg_oneof_done(i)) return 0; - lupb_oneofdef_pushwrapper(L, upb_msg_iter_oneof(i)); + o = upb_msg_iter_oneof(i); upb_msg_oneof_next(i); + lupb_symtab_pushwrapper(L, lua_upvalueindex(2), o, LUPB_ONEOFDEF); return 1; } static int lupb_msgdef_oneofs(lua_State *L) { const upb_msgdef *m = lupb_msgdef_check(L, 1); upb_msg_oneof_iter *i = lua_newuserdata(L, sizeof(upb_msg_oneof_iter)); + lupb_wrapper_pushsymtab(L, 1); upb_msg_oneof_begin(i, m); - /* Need to guarantee that the msgdef outlives the iter. */ - lua_pushvalue(L, 1); + + /* Closure upvalues are: iter, symtab. */ lua_pushcclosure(L, &lupb_msgoneofiter_next, 2); return 1; } @@ -429,15 +443,27 @@ static int lupb_msgdef_syntax(lua_State *L) { return 1; } +static int lupb_msgdef_tostring(lua_State *L) { + const upb_msgdef *m = lupb_msgdef_check(L, 1); + lua_pushfstring(L, "", + upb_msgdef_fullname(m), (int)upb_msgdef_numfields(m)); + return 1; +} + static const struct luaL_Reg lupb_msgdef_mm[] = { + {"__call", lupb_msg_pushnew}, {"__len", lupb_msgdef_len}, + {"__tostring", lupb_msgdef_tostring}, {NULL, NULL} }; static const struct luaL_Reg lupb_msgdef_m[] = { {"field", lupb_msgdef_field}, {"fields", lupb_msgdef_fields}, + {"file", lupb_msgdef_file}, + {"full_name", lupb_msgdef_fullname}, {"lookup_name", lupb_msgdef_lookupname}, + {"name", lupb_msgdef_name}, {"oneofs", lupb_msgdef_oneofs}, {"syntax", lupb_msgdef_syntax}, {"_map_entry", lupb_msgdef_mapentry}, @@ -448,11 +474,7 @@ static const struct luaL_Reg lupb_msgdef_m[] = { /* lupb_enumdef ***************************************************************/ const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg) { - return lupb_checkwrapper(L, narg, LUPB_ENUMDEF); -} - -static void lupb_enumdef_pushwrapper(lua_State *L, const upb_enumdef *e) { - lupb_pushwrapper(L, e, LUPB_ENUMDEF); + return lupb_wrapper_check(L, narg, LUPB_ENUMDEF); } static int lupb_enumdef_len(lua_State *L) { @@ -461,26 +483,46 @@ static int lupb_enumdef_len(lua_State *L) { return 1; } +static int lupb_enumdef_file(lua_State *L) { + const upb_enumdef *e = lupb_enumdef_check(L, 1); + const upb_filedef *file = upb_enumdef_file(e); + lupb_wrapper_pushwrapper(L, 1, file, LUPB_FILEDEF); + return 1; +} + +/* lupb_enumdef_value() + * + * Handles: + * enum.value(number) -> name + * enum.value(name) -> number + */ static int lupb_enumdef_value(lua_State *L) { const upb_enumdef *e = lupb_enumdef_check(L, 1); - int type = lua_type(L, 2); - if (type == LUA_TNUMBER) { - /* Pushes "nil" for a NULL pointer. */ - int32_t key = lupb_checkint32(L, 2); - lua_pushstring(L, upb_enumdef_iton(e, key)); - } else if (type == LUA_TSTRING) { - const char *key = lua_tostring(L, 2); - int32_t num; - if (upb_enumdef_ntoiz(e, key, &num)) { - lua_pushinteger(L, num); - } else { - lua_pushnil(L); + + switch (lua_type(L, 2)) { + case LUA_TNUMBER: { + int32_t key = lupb_checkint32(L, 2); + /* Pushes "nil" for a NULL pointer. */ + lua_pushstring(L, upb_enumdef_iton(e, key)); + break; + } + case LUA_TSTRING: { + const char *key = lua_tostring(L, 2); + int32_t num; + if (upb_enumdef_ntoiz(e, key, &num)) { + lua_pushinteger(L, num); + } else { + lua_pushnil(L); + } + break; + } + default: { + const char *msg = lua_pushfstring(L, "number or string expected, got %s", + luaL_typename(L, 2)); + return luaL_argerror(L, 2, msg); } - } else { - const char *msg = lua_pushfstring(L, "number or string expected, got %s", - luaL_typename(L, 2)); - return luaL_argerror(L, 2, msg); } + return 1; } @@ -496,9 +538,10 @@ static int lupb_enumiter_next(lua_State *L) { static int lupb_enumdef_values(lua_State *L) { const upb_enumdef *e = lupb_enumdef_check(L, 1); upb_enum_iter *i = lua_newuserdata(L, sizeof(upb_enum_iter)); + lupb_wrapper_pushsymtab(L, 1); upb_enum_begin(i, e); - /* Need to guarantee that the enumdef outlives the iter. */ - lua_pushvalue(L, 1); + + /* Closure upvalues are: iter, symtab. */ lua_pushcclosure(L, &lupb_enumiter_next, 2); return 1; } @@ -509,6 +552,7 @@ static const struct luaL_Reg lupb_enumdef_mm[] = { }; static const struct luaL_Reg lupb_enumdef_m[] = { + {"file", lupb_enumdef_file}, {"value", lupb_enumdef_value}, {"values", lupb_enumdef_values}, {NULL, NULL} @@ -517,18 +561,15 @@ static const struct luaL_Reg lupb_enumdef_m[] = { /* lupb_filedef ***************************************************************/ -void lupb_filedef_pushwrapper(lua_State *L, const upb_filedef *f) { - lupb_pushwrapper(L, f, LUPB_FILEDEF); -} - const upb_filedef *lupb_filedef_check(lua_State *L, int narg) { - return lupb_checkwrapper(L, narg, LUPB_FILEDEF); + return lupb_wrapper_check(L, narg, LUPB_FILEDEF); } static int lupb_filedef_dep(lua_State *L) { const upb_filedef *f = lupb_filedef_check(L, 1); int index = luaL_checkint(L, 2); - lupb_filedef_pushwrapper(L, upb_filedef_dep(f, index)); + const upb_filedef *dep = upb_filedef_dep(f, index); + lupb_wrapper_pushwrapper(L, 1, dep, LUPB_FILEDEF); return 1; } @@ -541,7 +582,8 @@ static int lupb_filedef_depcount(lua_State *L) { static int lupb_filedef_enum(lua_State *L) { const upb_filedef *f = lupb_filedef_check(L, 1); int index = luaL_checkint(L, 2); - lupb_enumdef_pushwrapper(L, upb_filedef_enum(f, index)); + const upb_enumdef *e = upb_filedef_enum(f, index); + lupb_wrapper_pushwrapper(L, 1, e, LUPB_ENUMDEF); return 1; } @@ -554,7 +596,8 @@ static int lupb_filedef_enumcount(lua_State *L) { static int lupb_filedef_msg(lua_State *L) { const upb_filedef *f = lupb_filedef_check(L, 1); int index = luaL_checkint(L, 2); - lupb_msgdef_pushwrapper(L, upb_filedef_msg(f, index)); + const upb_msgdef *m = upb_filedef_msg(f, index); + lupb_wrapper_pushwrapper(L, 1, m, LUPB_MSGDEF); return 1; } @@ -598,6 +641,13 @@ static const struct luaL_Reg lupb_filedef_m[] = { /* lupb_symtab ****************************************************************/ +/* The symtab owns all defs. Thus GC-rooting the symtab ensures that all + * underlying defs stay alive. + * + * The symtab's userval is a cache of def* -> object. */ + +#define LUPB_CACHE_INDEX 1 + typedef struct { upb_symtab *symtab; } lupb_symtab; @@ -610,11 +660,61 @@ upb_symtab *lupb_symtab_check(lua_State *L, int narg) { return lsymtab->symtab; } +void lupb_symtab_pushwrapper(lua_State *L, int narg, const void *def, + const char *type) { + narg = lua_absindex(L, narg); + assert(luaL_testudata(L, narg, LUPB_SYMTAB)); + + if (def == NULL) { + lua_pushnil(L); + return; + } + + lua_getiuservalue(L, narg, LUPB_CACHE_INDEX); /* Get cache. */ + + /* Index by "def" pointer. */ + lua_rawgetp(L, -1, def); + + /* Stack is now: cache, cached value. */ + if (lua_isnil(L, -1)) { + /* Create new wrapper. */ + lupb_wrapper *w = lupb_newuserdata(L, sizeof(*w), 1, type); + w->def = def; + lua_replace(L, -2); /* Replace nil */ + + /* Set symtab as userval. */ + lua_pushvalue(L, narg); + lua_setiuservalue(L, -2, LUPB_SYMTAB_INDEX); + + /* Add wrapper to the the cache. */ + lua_pushvalue(L, -1); + lua_rawsetp(L, -3, def); + } + + lua_replace(L, -2); /* Remove cache, leaving only the wrapper. */ +} + +/* upb_symtab_new() + * + * Handles: + * upb.SymbolTable() -> + */ static int lupb_symtab_new(lua_State *L) { - lupb_symtab *lsymtab = lua_newuserdata(L, sizeof(*lsymtab)); + lupb_symtab *lsymtab = lupb_newuserdata(L, sizeof(*lsymtab), 1, LUPB_SYMTAB); lsymtab->symtab = upb_symtab_new(); - luaL_getmetatable(L, LUPB_SYMTAB); + + /* Create our object cache. */ + lua_newtable(L); + + /* Cache metatable: specifies that values are weak. */ + lua_createtable(L, 0, 1); + lua_pushstring(L, "v"); + lua_setfield(L, -2, "__mode"); lua_setmetatable(L, -2); + + /* Set the cache as our userval. */ + lua_setiuservalue(L, -2, LUPB_CACHE_INDEX); + return 1; } @@ -625,20 +725,40 @@ static int lupb_symtab_gc(lua_State *L) { return 0; } -/* TODO(haberman): perhaps this should take a message object instead of a - * serialized string once we have a good story for vending compiled-in - * messages. */ -static int lupb_symtab_add(lua_State *L) { - upb_arena *arena; +static int lupb_symtab_addfile(lua_State *L) { + size_t len; + upb_symtab *s = lupb_symtab_check(L, 1); + const char *str = luaL_checklstring(L, 2, &len); + upb_arena *arena = lupb_arena_pushnew(L);; + const google_protobuf_FileDescriptorProto *file; + const upb_filedef *file_def; + upb_status status; + + upb_status_clear(&status); + file = google_protobuf_FileDescriptorProto_parse(str, len, arena); + + if (!file) { + luaL_argerror(L, 2, "failed to parse descriptor"); + } + + file_def = upb_symtab_addfile(s, file, &status); + lupb_checkstatus(L, &status); + + lupb_symtab_pushwrapper(L, 1, file_def, LUPB_FILEDEF); + + return 1; +} + +static int lupb_symtab_addset(lua_State *L) { size_t i, n, len; const google_protobuf_FileDescriptorProto *const *files; google_protobuf_FileDescriptorSet *set; upb_symtab *s = lupb_symtab_check(L, 1); const char *str = luaL_checklstring(L, 2, &len); + upb_arena *arena = lupb_arena_pushnew(L);; + upb_status status; - lupb_arena_new(L); - arena = lupb_arena_check(L, -1); - + upb_status_clear(&status); set = google_protobuf_FileDescriptorSet_parse(str, len, arena); if (!set) { @@ -647,7 +767,8 @@ static int lupb_symtab_add(lua_State *L) { files = google_protobuf_FileDescriptorSet_file(set, &n); for (i = 0; i < n; i++) { - CHK(upb_symtab_addfile(s, files[i], &status)); + upb_symtab_addfile(s, files[i], &status); + lupb_checkstatus(L, &status); } return 0; @@ -656,19 +777,27 @@ static int lupb_symtab_add(lua_State *L) { static int lupb_symtab_lookupmsg(lua_State *L) { const upb_symtab *s = lupb_symtab_check(L, 1); const upb_msgdef *m = upb_symtab_lookupmsg(s, luaL_checkstring(L, 2)); - lupb_msgdef_pushwrapper(L, m); + lupb_symtab_pushwrapper(L, 1, m, LUPB_MSGDEF); return 1; } static int lupb_symtab_lookupenum(lua_State *L) { const upb_symtab *s = lupb_symtab_check(L, 1); const upb_enumdef *e = upb_symtab_lookupenum(s, luaL_checkstring(L, 2)); - lupb_enumdef_pushwrapper(L, e); + lupb_symtab_pushwrapper(L, 1, e, LUPB_ENUMDEF); + return 1; +} + +static int lupb_symtab_tostring(lua_State *L) { + const upb_symtab *s = lupb_symtab_check(L, 1); + lua_pushfstring(L, "", + (int)upb_symtab_filecount(s)); return 1; } static const struct luaL_Reg lupb_symtab_m[] = { - {"add", lupb_symtab_add}, + {"add_file", lupb_symtab_addfile}, + {"add_set", lupb_symtab_addset}, {"lookup_msg", lupb_symtab_lookupmsg}, {"lookup_enum", lupb_symtab_lookupenum}, {NULL, NULL} @@ -676,6 +805,7 @@ static const struct luaL_Reg lupb_symtab_m[] = { static const struct luaL_Reg lupb_symtab_mm[] = { {"__gc", lupb_symtab_gc}, + {"__tostring", lupb_symtab_tostring}, {NULL, NULL} }; @@ -694,7 +824,7 @@ static const struct luaL_Reg lupbdef_toplevel_m[] = { void lupb_def_registertypes(lua_State *L) { lupb_setfuncs(L, lupbdef_toplevel_m); - /* Refcounted types. */ + /* Register types. */ lupb_register_type(L, LUPB_ENUMDEF, lupb_enumdef_m, lupb_enumdef_mm); lupb_register_type(L, LUPB_FIELDDEF, lupb_fielddef_m, NULL); lupb_register_type(L, LUPB_FILEDEF, lupb_filedef_m, NULL); @@ -702,14 +832,6 @@ void lupb_def_registertypes(lua_State *L) { lupb_register_type(L, LUPB_ONEOFDEF, lupb_oneofdef_m, lupb_oneofdef_mm); lupb_register_type(L, LUPB_SYMTAB, lupb_symtab_m, lupb_symtab_mm); - /* Create our object cache. */ - lua_newtable(L); - lua_createtable(L, 0, 1); /* Cache metatable. */ - lua_pushstring(L, "v"); /* Values are weak. */ - lua_setfield(L, -2, "__mode"); - lua_setmetatable(L, -2); - lua_setfield(L, LUA_REGISTRYINDEX, LUPB_OBJCACHE); - /* Register constants. */ lupb_setfieldi(L, "LABEL_OPTIONAL", UPB_LABEL_OPTIONAL); lupb_setfieldi(L, "LABEL_REQUIRED", UPB_LABEL_REQUIRED); @@ -746,21 +868,6 @@ void lupb_def_registertypes(lua_State *L) { lupb_setfieldi(L, "DESCRIPTOR_TYPE_SINT32", UPB_DESCRIPTOR_TYPE_SINT32); lupb_setfieldi(L, "DESCRIPTOR_TYPE_SINT64", UPB_DESCRIPTOR_TYPE_SINT64); - lupb_setfieldi(L, "HANDLER_INT32", UPB_HANDLER_INT32); - lupb_setfieldi(L, "HANDLER_INT64", UPB_HANDLER_INT64); - lupb_setfieldi(L, "HANDLER_UINT32", UPB_HANDLER_UINT32); - lupb_setfieldi(L, "HANDLER_UINT64", UPB_HANDLER_UINT64); - lupb_setfieldi(L, "HANDLER_FLOAT", UPB_HANDLER_FLOAT); - lupb_setfieldi(L, "HANDLER_DOUBLE", UPB_HANDLER_DOUBLE); - lupb_setfieldi(L, "HANDLER_BOOL", UPB_HANDLER_BOOL); - lupb_setfieldi(L, "HANDLER_STARTSTR", UPB_HANDLER_STARTSTR); - lupb_setfieldi(L, "HANDLER_STRING", UPB_HANDLER_STRING); - lupb_setfieldi(L, "HANDLER_ENDSTR", UPB_HANDLER_ENDSTR); - lupb_setfieldi(L, "HANDLER_STARTSUBMSG", UPB_HANDLER_STARTSUBMSG); - lupb_setfieldi(L, "HANDLER_ENDSUBMSG", UPB_HANDLER_ENDSUBMSG); - lupb_setfieldi(L, "HANDLER_STARTSEQ", UPB_HANDLER_STARTSEQ); - lupb_setfieldi(L, "HANDLER_ENDSEQ", UPB_HANDLER_ENDSEQ); - lupb_setfieldi(L, "SYNTAX_PROTO2", UPB_SYNTAX_PROTO2); lupb_setfieldi(L, "SYNTAX_PROTO3", UPB_SYNTAX_PROTO3); } diff --git a/upb/bindings/lua/lua_proto_library.bzl b/upb/bindings/lua/lua_proto_library.bzl new file mode 100644 index 0000000000..f21655140a --- /dev/null +++ b/upb/bindings/lua/lua_proto_library.bzl @@ -0,0 +1,109 @@ + +load("@bazel_skylib//lib:paths.bzl", "paths") + +# Generic support code ######################################################### + +_is_bazel = not hasattr(native, "genmpm") + +def _get_real_short_path(file): + # For some reason, files from other archives have short paths that look like: + # ../com_google_protobuf/google/protobuf/descriptor.proto + short_path = file.short_path + if short_path.startswith("../"): + second_slash = short_path.index("/", 3) + short_path = short_path[second_slash + 1:] + # Sometimes it has another few prefixes like: + # _virtual_imports/any_proto/google/protobuf/any.proto + # We want just google/protobuf/any.proto. + if short_path.startswith("_virtual_imports"): + short_path = short_path.split("/", 2)[-1] + return short_path + +def _get_real_root(file): + real_short_path = _get_real_short_path(file) + return file.path[:-len(real_short_path) - 1] + +def _generate_output_file(ctx, src, extension): + real_short_path = _get_real_short_path(src) + real_short_path = paths.relativize(real_short_path, ctx.label.package) + output_filename = paths.replace_extension(real_short_path, extension) + ret = ctx.actions.declare_file(output_filename) + return ret + +# upb_proto_library / upb_proto_reflection_library shared code ################# + +_LuaFiles = provider(fields = ["files"]) + +def _compile_upb_protos(ctx, proto_info, proto_sources): + files = [_generate_output_file(ctx, name, "_pb.lua") for name in proto_sources] + transitive_sets = proto_info.transitive_descriptor_sets.to_list() + ctx.actions.run( + inputs = depset( + direct = [proto_info.direct_descriptor_set], + transitive = [proto_info.transitive_descriptor_sets], + ), + tools = [ctx.executable._upbc], + outputs = files, + executable = ctx.executable._protoc, + arguments = [ + "--lua_out=" + _get_real_root(files[0]), + "--plugin=protoc-gen-lua=" + ctx.executable._upbc.path, + "--descriptor_set_in=" + ctx.configuration.host_path_separator.join([f.path for f in transitive_sets]), + ] + + [_get_real_short_path(file) for file in proto_sources], + progress_message = "Generating Lua protos for :" + ctx.label.name, + ) + return files + +def _lua_proto_rule_impl(ctx): + if len(ctx.attr.deps) != 1: + fail("only one deps dependency allowed.") + dep = ctx.attr.deps[0] + if _LuaFiles not in dep: + fail("proto_library rule must generate _LuaFiles (aspect should have handled this).") + files = dep[_LuaFiles].files + return [ + DefaultInfo( + files = files, + data_runfiles = ctx.runfiles(files = files.to_list())), + ] + +def _lua_proto_library_aspect_impl(target, ctx): + proto_info = target[ProtoInfo] + files = _compile_upb_protos(ctx, proto_info, proto_info.direct_sources) + deps = ctx.rule.attr.deps + transitive = [dep[_LuaFiles].files for dep in deps if _LuaFiles in dep] + return [_LuaFiles(files = depset(direct = files, transitive = transitive))] + +# lua_proto_library() ########################################################## + +_lua_proto_library_aspect = aspect( + attrs = { + "_upbc": attr.label( + executable = True, + cfg = "host", + default = "//:protoc-gen-lua", + ), + "_protoc": attr.label( + executable = True, + cfg = "host", + default = "@com_google_protobuf//:protoc", + ), + }, + implementation = _lua_proto_library_aspect_impl, + provides = [_LuaFiles], + attr_aspects = ["deps"], + fragments = ["cpp"], +) + +lua_proto_library = rule( + output_to_genfiles = True, + implementation = _lua_proto_rule_impl, + attrs = { + "deps": attr.label_list( + aspects = [_lua_proto_library_aspect], + allow_rules = ["proto_library"], + providers = [ProtoInfo], + ), + }, +) diff --git a/upb/bindings/lua/msg.c b/upb/bindings/lua/msg.c index 5e769b2f0d..82d65e0fa6 100644 --- a/upb/bindings/lua/msg.c +++ b/upb/bindings/lua/msg.c @@ -2,6 +2,8 @@ ** lupb_msg -- Message/Array/Map objects in Lua/C that wrap upb/msg.h */ +#include "upb/msg.h" + #include #include #include @@ -10,575 +12,479 @@ #include "lauxlib.h" #include "upb/bindings/lua/upb.h" -#include "upb/handlers.h" -#include "upb/legacy_msg_reflection.h" -#include "upb/msg.h" +#include "upb/reflection.h" #include "upb/port_def.inc" /* - * Message/Array/Map objects can be constructed in one of two ways: - * - * 1. To point to existing msg/array/map data inside an arena. - * 2. To create and uniquely own some brand new data. - * - * Case (1) is for when we've parsed some data into an arena (which is faster - * than parsing directly into Lua objects) or when we're pointing at some - * read-only data (like custom options in a def). - * - * Case (2) is for when a user creates the object directly in Lua. - * - * We use the userval of container objects (Message/Array/Map) to store - * references to sub-objects (Strings/Messages/Arrays/Maps). But we need to - * keep the userval in sync with the underlying upb_msg/upb_array/upb_map. - * We populate the userval lazily from the underlying data. - * - * This means that no one may remove/replace any String/Message/Array/Map - * field/entry in the underlying upb_{msg,array,map} behind our back. It's ok - * for entries to be added or for primitives to be modified, but *replacing* - * sub-containers is not. - * - * Luckily parse/merge follow this rule. However clear does not, so it's not - * safe to clear behind our back. + * Message/Map/Array objects. These objects form a directed graph: a message + * can contain submessages, arrays, and maps, which can then point to other + * messages. This graph can technically be cyclic, though this is an error and + * a cyclic graph cannot be serialized. So it's better to think of this as a + * tree of objects. + * + * The actual data exists at the upb level (upb_msg, upb_map, upb_array), + * independently of Lua. The upb objects contain all the canonical data and + * edges between objects. Lua wrapper objects expose the upb objects to Lua, + * but ultimately they are just wrappers. They pass through all reads and + * writes to the underlying upb objects. + * + * Each upb object lives in a upb arena. We have a Lua object to wrap the upb + * arena, but arenas are never exposed to the user. The Lua arena object just + * serves to own the upb arena and free it at the proper time, once the Lua GC + * has determined that there are no more references to anything that lives in + * that arena. All wrapper objects strongly reference the arena to which they + * belong. + * + * A global object cache stores a mapping of C pointer (upb_msg*, upb_array*, + * upb_map*) to a corresponding Lua wrapper. These references are weak so that + * 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. + * + * arena + * +--------------------------->group<-----------------+ + * | | + * 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 + * +------|--+ +--^------+ + * +---------------------+ + * Key invariants: + * 1. every wrapper references the arena that contains it. + * 2. every arena group references 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. + * + * 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" - -#define LUPB_MSGCLASS "lupb.msgclass" -#define LUPB_MSGFACTORY "lupb.msgfactory" - #define LUPB_ARRAY "lupb.array" #define LUPB_MAP "lupb.map" #define LUPB_MSG "lupb.msg" -#define LUPB_STRING "lupb.string" -static int lupb_msg_pushnew(lua_State *L, int narg); +#define LUPB_ARENA_INDEX 1 +#define LUPB_MSGDEF_INDEX 2 /* For msg, and map/array that store msg */ -/* Lazily creates the uservalue if it doesn't exist. */ -static void lupb_getuservalue(lua_State *L, int index) { - lua_getuservalue(L, index); - if (lua_isnil(L, -1)) { - /* Lazily create and set userval. */ - lua_pop(L, 1); /* nil. */ - lua_pushvalue(L, index); /* userdata copy. */ - lua_newtable(L); - lua_setuservalue(L, -2); - lua_pop(L, 1); /* userdata copy. */ - lua_getuservalue(L, index); - } - assert(!lua_isnil(L, -1)); -} - -static void lupb_uservalseti(lua_State *L, int userdata, int index, int val) { - lupb_getuservalue(L, userdata); - lua_pushvalue(L, val); - lua_rawseti(L, -2, index); - lua_pop(L, 1); /* Uservalue. */ -} +static void lupb_msg_newmsgwrapper(lua_State *L, int narg, upb_msgval val); +static upb_msg *lupb_msg_check(lua_State *L, int narg); -static void lupb_uservalgeti(lua_State *L, int userdata, int index) { - lupb_getuservalue(L, userdata); - lua_rawgeti(L, -1, index); - lua_insert(L, -2); - lua_pop(L, 1); /* Uservalue. */ +static upb_fieldtype_t lupb_checkfieldtype(lua_State *L, int narg) { + uint32_t n = lupb_checkuint32(L, narg); + bool ok = n >= UPB_TYPE_BOOL && n <= UPB_TYPE_BYTES; + luaL_argcheck(L, ok, narg, "invalid field type"); + return n; } -/* Pushes a new userdata with the given metatable. */ -static void *lupb_newuserdata(lua_State *L, size_t size, const char *type) { - void *ret = lua_newuserdata(L, size); +char cache_key; - /* Set metatable. */ - luaL_getmetatable(L, type); - UPB_ASSERT(!lua_isnil(L, -1)); /* Should have been created by luaopen_upb. */ +/* lupb_cacheinit() + * + * Creates the global cache used by lupb_cacheget() and lupb_cacheset(). + */ +static void lupb_cacheinit(lua_State *L) { + /* Create our object cache. */ + lua_newtable(L); + + /* Cache metatable gives the cache weak values */ + lua_createtable(L, 0, 1); + lua_pushstring(L, "v"); + lua_setfield(L, -2, "__mode"); lua_setmetatable(L, -2); - /* We don't set a uservalue here -- we lazily create it later if necessary. */ + /* Set cache in the registry. */ + lua_rawsetp(L, LUA_REGISTRYINDEX, &cache_key); +} - return ret; +/* lupb_cacheget() + * + * Pushes cache[key] and returns true if this key is present in the cache. + * Otherwise returns false and leaves nothing on the stack. + */ +static bool lupb_cacheget(lua_State *L, const void *key) { + if (key == NULL) { + lua_pushnil(L); + return true; + } + + lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key); + lua_rawgetp(L, -1, key); + if (lua_isnil(L, -1)) { + lua_pop(L, 2); /* Pop table, nil. */ + return false; + } else { + lua_replace(L, -2); /* Replace cache table. */ + return true; + } } +/* lupb_cacheset() + * + * Sets cache[key] = val, where "val" is the value at the top of the stack. + * Does not pop the value. + */ +static void lupb_cacheset(lua_State *L, const void *key) { + lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key); + lua_pushvalue(L, -2); + lua_rawsetp(L, -2, key); + lua_pop(L, 1); /* Pop table. */ +} /* lupb_arena *****************************************************************/ -/* lupb_arena only exists to wrap a upb_arena. It is never exposed to users; - * it is an internal memory management detail. Other objects refer to this - * object from their userdata to keep the arena-owned data alive. */ +/* 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; -upb_arena *lupb_arena_check(lua_State *L, int narg) { +static upb_arena *lupb_arena_check(lua_State *L, int narg) { lupb_arena *a = luaL_checkudata(L, narg, LUPB_ARENA); - return a ? a->arena : NULL; + return a->arena; } -int lupb_arena_new(lua_State *L) { - lupb_arena *a = lupb_newuserdata(L, sizeof(lupb_arena), LUPB_ARENA); - - /* TODO(haberman): use Lua alloc func as block allocator? Would need to - * verify that all cases of upb_malloc in msg/table are longjmp-safe. */ +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(); - return 1; -} - -char lupb_arena_cache_key; + /* Create arena group table and add this arena to it. */ + lua_createtable(L, 0, 1); + lua_pushvalue(L, -2); + lua_rawseti(L, -2, 1); -/* Returns the global lupb_arena func that was created in our luaopen(). - * Callers can be guaranteed that it will be alive as long as |L| is. - * TODO(haberman): we shouldn't use a global arena! We should have - * one arena for a parse, or per independently-created message. */ -upb_arena *lupb_arena_get(lua_State *L) { - upb_arena *arena; + /* Set arena group as this object's userval. */ + lua_setiuservalue(L, -2, LUPB_ARENAGROUP_INDEX); - lua_pushlightuserdata(L, &lupb_arena_cache_key); - lua_gettable(L, LUA_REGISTRYINDEX); - arena = lua_touserdata(L, -1); - UPB_ASSERT(arena); - lua_pop(L, 1); - - return arena; + return a->arena; } -static void lupb_arena_initsingleton(lua_State *L) { - lua_pushlightuserdata(L, &lupb_arena_cache_key); - lupb_arena_new(L); - lua_settable(L, LUA_REGISTRYINDEX); -} - -static int lupb_arena_gc(lua_State *L) { - upb_arena *a = lupb_arena_check(L, 1); - upb_arena_free(a); - return 0; -} - -static const struct luaL_Reg lupb_arena_mm[] = { - {"__gc", lupb_arena_gc}, - {NULL, NULL} -}; - - -/* lupb_msgfactory ************************************************************/ - -/* Userval contains a map of: - * [1] -> SymbolTable (to keep GC-reachable) - * [const upb_msgdef*] -> [lupb_msgclass userdata] - */ - -#define LUPB_MSGFACTORY_SYMTAB 1 - -typedef struct lupb_msgfactory { - upb_msgfactory *factory; -} lupb_msgfactory; - -static int lupb_msgclass_pushnew(lua_State *L, int factory, - const upb_msgdef *md); - -/* lupb_msgfactory helpers. */ - -static lupb_msgfactory *lupb_msgfactory_check(lua_State *L, int narg) { - return luaL_checkudata(L, narg, LUPB_MSGFACTORY); -} - -static void lupb_msgfactory_pushmsgclass(lua_State *L, int narg, - const upb_msgdef *md) { - lupb_getuservalue(L, narg); - lua_pushlightuserdata(L, (void*)md); - lua_rawget(L, -2); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - /* TODO: verify md is in symtab? */ - lupb_msgclass_pushnew(L, narg, md); - - /* Set in userval. */ - lua_pushlightuserdata(L, (void*)md); - lua_pushvalue(L, -2); - lua_rawset(L, -4); +/** + * lupb_arena_merge() + * + * 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; } -} -static int lupb_msgfactory_gc(lua_State *L) { - lupb_msgfactory *lfactory = lupb_msgfactory_check(L, 1); + to_count = lua_rawlen(L, -2); + from_count = lua_rawlen(L, -1); - if (lfactory->factory) { - upb_msgfactory_free(lfactory->factory); - lfactory->factory = NULL; + /* 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); } - return 0; + /* Make |from| point to |to|'s table. */ + lua_pop(L, 1); + lua_setiuservalue(L, from, LUPB_ARENAGROUP_INDEX); } -/* lupb_msgfactory Public API. */ - /** - * lupb_msgfactory_new() + * lupb_arena_addobj() * - * Handles: - * msgfactory = upb.MessageFactory(symtab) + * 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. * - * Creates a new, empty MessageFactory for the given SymbolTable. - * Message classes will be created on demand when the user calls - * msgfactory.get_message_class(). - */ -static int lupb_msgfactory_new(lua_State *L) { - const upb_symtab *symtab = lupb_symtab_check(L, 1); - - lupb_msgfactory *lmsgfactory = - lupb_newuserdata(L, sizeof(lupb_msgfactory), LUPB_MSGFACTORY); - lmsgfactory->factory = upb_msgfactory_new(symtab); - lupb_uservalseti(L, -1, LUPB_MSGFACTORY_SYMTAB, 1); - - return 1; + * 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. */ } -/** - * lupb_msgfactory_getmsgclass() - * - * Handles: - * MessageClass = factory.get_message_class(message_name) - */ -static int lupb_msgfactory_getmsgclass(lua_State *L) { - lupb_msgfactory *lfactory = lupb_msgfactory_check(L, 1); - const upb_symtab *symtab = upb_msgfactory_symtab(lfactory->factory); - const upb_msgdef *m = upb_symtab_lookupmsg(symtab, luaL_checkstring(L, 2)); - - if (!m) { - luaL_error(L, "No such message type: %s\n", lua_tostring(L, 2)); - } - - lupb_msgfactory_pushmsgclass(L, 1, m); - - return 1; +static int lupb_arena_gc(lua_State *L) { + upb_arena *a = lupb_arena_check(L, 1); + upb_arena_free(a); + return 0; } -static const struct luaL_Reg lupb_msgfactory_m[] = { - {"get_message_class", lupb_msgfactory_getmsgclass}, - {NULL, NULL} -}; - -static const struct luaL_Reg lupb_msgfactory_mm[] = { - {"__gc", lupb_msgfactory_gc}, +static const struct luaL_Reg lupb_arena_mm[] = { + {"__gc", lupb_arena_gc}, {NULL, NULL} }; - -/* lupb_msgclass **************************************************************/ - -/* Userval contains a map of: - * [1] -> MessageFactory (to keep GC-reachable) - * [const upb_msgdef*] -> [lupb_msgclass userdata] - */ - -#define LUPB_MSGCLASS_FACTORY 1 - -struct lupb_msgclass { - const upb_msglayout *layout; - const upb_msgdef *msgdef; - const lupb_msgfactory *lfactory; -}; - -/* Type-checks for assigning to a message field. */ -static upb_msgval lupb_array_typecheck(lua_State *L, int narg, int msg, - const upb_fielddef *f); -static upb_msgval lupb_map_typecheck(lua_State *L, int narg, int msg, - const upb_fielddef *f); -static const lupb_msgclass *lupb_msg_getsubmsgclass(lua_State *L, int narg, - const upb_fielddef *f); -static const lupb_msgclass *lupb_msg_msgclassfor(lua_State *L, int narg, - const upb_msgdef *md); - -const lupb_msgclass *lupb_msgclass_check(lua_State *L, int narg) { - return luaL_checkudata(L, narg, LUPB_MSGCLASS); -} - -const upb_msglayout *lupb_msgclass_getlayout(lua_State *L, int narg) { - return lupb_msgclass_check(L, narg)->layout; -} - -const upb_msgdef *lupb_msgclass_getmsgdef(const lupb_msgclass *lmsgclass) { - return lmsgclass->msgdef; -} - -upb_msgfactory *lupb_msgclass_getfactory(const lupb_msgclass *lmsgclass) { - return lmsgclass->lfactory->factory; -} - -/** - * lupb_msgclass_typecheck() +/* lupb_arenaget() * - * Verifies that the expected msgclass matches the actual. If not, raises a Lua - * error. + * Returns the arena from the given message, array, or map object. */ -static void lupb_msgclass_typecheck(lua_State *L, const lupb_msgclass *expected, - const lupb_msgclass *actual) { - if (expected != actual) { - luaL_error(L, "Message had incorrect type, expected '%s', got '%s'", - upb_msgdef_fullname(expected->msgdef), - upb_msgdef_fullname(actual->msgdef)); - } -} - -static const lupb_msgclass *lupb_msgclass_msgclassfor(lua_State *L, int narg, - const upb_msgdef *md) { - lupb_uservalgeti(L, narg, LUPB_MSGCLASS_FACTORY); - lupb_msgfactory_pushmsgclass(L, -1, md); - return lupb_msgclass_check(L, -1); -} - -/** - * lupb_msgclass_getsubmsgclass() - * - * Given a MessageClass at index |narg| and the submessage field |f|, returns - * the message class for this field. - * - * Currently we do a hash table lookup for this. If we wanted we could try to - * optimize this by caching these pointers in our msgclass, in an array indexed - * by field index. We would still need to fall back to calling msgclassfor(), - * unless we wanted to eagerly create message classes for all submessages. But - * for big schemas that might be a lot of things to build, and we might end up - * not using most of them. */ -static const lupb_msgclass *lupb_msgclass_getsubmsgclass(lua_State *L, int narg, - const upb_fielddef *f) { - if (upb_fielddef_type(f) != UPB_TYPE_MESSAGE) { - return NULL; - } - - return lupb_msgclass_msgclassfor(L, narg, upb_fielddef_msgsubdef(f)); +static upb_arena *lupb_arenaget(lua_State *L, int narg) { + upb_arena *arena; + lua_getiuservalue(L, narg, LUPB_ARENA_INDEX); + arena = lupb_arena_check(L, -1); + lua_pop(L, 1); + return arena; } -static int lupb_msgclass_pushnew(lua_State *L, int factory, - const upb_msgdef *md) { - const lupb_msgfactory *lfactory = lupb_msgfactory_check(L, factory); - lupb_msgclass *lmc = lupb_newuserdata(L, sizeof(*lmc), LUPB_MSGCLASS); - - lupb_uservalseti(L, -1, LUPB_MSGCLASS_FACTORY, factory); - lmc->layout = upb_msgfactory_getlayout(lfactory->factory, md); - lmc->lfactory = lfactory; - lmc->msgdef = md; - - return 1; -} +/* upb <-> Lua type conversion ************************************************/ -/* MessageClass Public API. */ +/* Whether string data should be copied into the containing arena. We can + * avoid a copy if the string data is only needed temporarily (like for a map + * lookup). + */ +typedef enum { + LUPB_COPY, /* Copy string data into the arena. */ + LUPB_REF /* Reference the Lua copy of the string data. */ +} lupb_copy_t; /** - * lupb_msgclass_call() - * - * Handles: - * msg = MessageClass() + * lupb_tomsgval() * - * Creates a new message from the given MessageClass. + * Converts the given Lua value |narg| to a upb_msgval. */ -static int lupb_msgclass_call(lua_State *L) { - lupb_msg_pushnew(L, 1); - return 1; -} - -static const struct luaL_Reg lupb_msgclass_mm[] = { - {"__call", lupb_msgclass_call}, - {NULL, NULL} -}; - - -/* upb <-> Lua type conversion ************************************************/ - -static bool lupb_istypewrapped(upb_fieldtype_t type) { - return type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES || - type == UPB_TYPE_MESSAGE; -} - static upb_msgval lupb_tomsgval(lua_State *L, upb_fieldtype_t type, int narg, - const lupb_msgclass *lmsgclass) { + int container, lupb_copy_t copy) { + upb_msgval ret; switch (type) { case UPB_TYPE_INT32: case UPB_TYPE_ENUM: - return upb_msgval_int32(lupb_checkint32(L, narg)); + ret.int32_val = lupb_checkint32(L, narg); + break; case UPB_TYPE_INT64: - return upb_msgval_int64(lupb_checkint64(L, narg)); + ret.int64_val = lupb_checkint64(L, narg); + break; case UPB_TYPE_UINT32: - return upb_msgval_uint32(lupb_checkuint32(L, narg)); + ret.uint32_val = lupb_checkuint32(L, narg); + break; case UPB_TYPE_UINT64: - return upb_msgval_uint64(lupb_checkuint64(L, narg)); + ret.uint64_val = lupb_checkuint64(L, narg); + break; case UPB_TYPE_DOUBLE: - return upb_msgval_double(lupb_checkdouble(L, narg)); + ret.double_val = lupb_checkdouble(L, narg); + break; case UPB_TYPE_FLOAT: - return upb_msgval_float(lupb_checkfloat(L, narg)); + ret.float_val = lupb_checkfloat(L, narg); + break; case UPB_TYPE_BOOL: - return upb_msgval_bool(lupb_checkbool(L, narg)); + ret.bool_val = lupb_checkbool(L, narg); + break; case UPB_TYPE_STRING: case UPB_TYPE_BYTES: { size_t len; const char *ptr = lupb_checkstring(L, narg, &len); - return upb_msgval_makestr(ptr, len); + switch (copy) { + case LUPB_COPY: { + upb_arena *arena = lupb_arenaget(L, container); + char *data = upb_arena_malloc(arena, len); + memcpy(data, ptr, len); + ret.str_val = upb_strview_make(data, len); + break; + } + case LUPB_REF: + ret.str_val = upb_strview_make(ptr, len); + break; + } + break; } case UPB_TYPE_MESSAGE: - UPB_ASSERT(lmsgclass); - return upb_msgval_msg(lupb_msg_checkmsg(L, narg, lmsgclass)); + ret.msg_val = lupb_msg_check(L, narg); + /* Typecheck message. */ + lua_getiuservalue(L, container, LUPB_MSGDEF_INDEX); + lua_getiuservalue(L, narg, LUPB_MSGDEF_INDEX); + luaL_argcheck(L, lua_rawequal(L, -1, -2), narg, "message type mismatch"); + lua_pop(L, 2); + break; } - UPB_UNREACHABLE(); + return ret; } -static void lupb_pushmsgval(lua_State *L, upb_fieldtype_t type, +static void lupb_pushmsgval(lua_State *L, int container, upb_fieldtype_t type, upb_msgval val) { switch (type) { case UPB_TYPE_INT32: case UPB_TYPE_ENUM: - lupb_pushint32(L, upb_msgval_getint32(val)); + lupb_pushint32(L, val.int32_val); return; case UPB_TYPE_INT64: - lupb_pushint64(L, upb_msgval_getint64(val)); + lupb_pushint64(L, val.int64_val); return; case UPB_TYPE_UINT32: - lupb_pushuint32(L, upb_msgval_getuint32(val)); + lupb_pushuint32(L, val.uint32_val); return; case UPB_TYPE_UINT64: - lupb_pushuint64(L, upb_msgval_getuint64(val)); + lupb_pushuint64(L, val.uint64_val); return; case UPB_TYPE_DOUBLE: - lupb_pushdouble(L, upb_msgval_getdouble(val)); + lua_pushnumber(L, val.double_val); return; case UPB_TYPE_FLOAT: - lupb_pushfloat(L, upb_msgval_getfloat(val)); + lua_pushnumber(L, val.float_val); return; case UPB_TYPE_BOOL: - lua_pushboolean(L, upb_msgval_getbool(val)); + lua_pushboolean(L, val.bool_val); return; case UPB_TYPE_STRING: case UPB_TYPE_BYTES: + lua_pushlstring(L, val.str_val.data, val.str_val.size); + return; case UPB_TYPE_MESSAGE: - break; /* Shouldn't call this function. */ + assert(container); + if (!lupb_cacheget(L, val.msg_val)) { + lupb_msg_newmsgwrapper(L, container, val); + } + return; } - UPB_UNREACHABLE(); + LUPB_UNREACHABLE(); } /* lupb_array *****************************************************************/ -/* A strongly typed array. Implemented by wrapping upb_array. - * - * - we only allow integer indices. - * - all entries must have the correct type. - * - we do not allow "holes" in the array; you can only assign to an existing - * index or one past the end (which will grow the array by one). - * - * For string/submessage entries we keep in the userval: - * - * [number index] -> [lupb_string/lupb_msg userdata] - */ - typedef struct { - /* Only needed for array of message. This wastes space in the non-message - * case but simplifies the code. Could optimize away if desired. */ - const lupb_msgclass *lmsgclass; upb_array *arr; upb_fieldtype_t type; } lupb_array; -#define ARRAY_MSGCLASS_INDEX 0 - static lupb_array *lupb_array_check(lua_State *L, int narg) { return luaL_checkudata(L, narg, LUPB_ARRAY); } -/** - * lupb_array_typecheck() - * - * Verifies that the lupb_array object at index |narg| can be safely assigned - * to the field |f| of the lupb_msg object at index |msg|. If this is safe, - * returns a upb_msgval representing the array. Otherwise, throws a Lua error. - */ -static upb_msgval lupb_array_typecheck(lua_State *L, int narg, int msg, - const upb_fielddef *f) { - lupb_array *larray = lupb_array_check(L, narg); - - if (upb_array_type(larray->arr) != upb_fielddef_type(f) || - lupb_msg_getsubmsgclass(L, msg, f) != larray->lmsgclass) { - luaL_error(L, "Array had incorrect type (expected: %d, got: %d)", - (int)upb_fielddef_type(f), (int)upb_array_type(larray->arr)); - } - - if (upb_array_type(larray->arr) == UPB_TYPE_MESSAGE) { - lupb_msgclass_typecheck(L, lupb_msg_getsubmsgclass(L, msg, f), - larray->lmsgclass); - } - - return upb_msgval_arr(larray->arr); -} - /** * lupb_array_checkindex() * * Checks the array index at Lua stack index |narg| to verify that it is an * integer between 1 and |max|, inclusively. Also corrects it to be zero-based * for C. - * - * We use "int" because of lua_rawseti/lua_rawgeti -- can re-evaluate if we want - * arrays bigger than 2^31. */ static int lupb_array_checkindex(lua_State *L, int narg, uint32_t max) { uint32_t n = lupb_checkuint32(L, narg); - if (n == 0 || n > max || n > INT_MAX) { - luaL_error(L, "Invalid array index: expected between 1 and %d", (int)max); - } - return n - 1; /* Lua uses 1-based indexing. :( */ + luaL_argcheck(L, n != 0 && n <= max, narg, "invalid array index"); + return n - 1; /* Lua uses 1-based indexing. */ } /* lupb_array Public API */ +/* lupb_array_new(): + * + * Handles: + * Array(upb.TYPE_INT32) + * Array(message_type) + */ static int lupb_array_new(lua_State *L) { lupb_array *larray; - upb_fieldtype_t type; - const lupb_msgclass *lmsgclass = NULL; + upb_arena *arena; if (lua_type(L, 1) == LUA_TNUMBER) { - type = lupb_checkfieldtype(L, 1); + upb_fieldtype_t type = lupb_checkfieldtype(L, 1); + larray = lupb_newuserdata(L, sizeof(*larray), 1, LUPB_ARRAY); + larray->type = type; } else { - type = UPB_TYPE_MESSAGE; - lmsgclass = lupb_msgclass_check(L, 1); - lupb_uservalseti(L, -1, ARRAY_MSGCLASS_INDEX, 1); /* GC-root lmsgclass. */ + lupb_msgdef_check(L, 1); + larray = lupb_newuserdata(L, sizeof(*larray), 2, LUPB_ARRAY); + larray->type = UPB_TYPE_MESSAGE; + lua_pushvalue(L, 1); + lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX); } - larray = lupb_newuserdata(L, sizeof(*larray), LUPB_ARRAY); - larray->type = type; - larray->lmsgclass = lmsgclass; - larray->arr = upb_array_new(lupb_arena_get(L)); + arena = lupb_arena_pushnew(L); + lua_setiuservalue(L, -2, LUPB_ARENA_INDEX); + + larray->arr = upb_array_new(arena, larray->type); + lupb_cacheset(L, larray->arr); return 1; } +/* lupb_array_newindex(): + * + * Handles: + * array[idx] = val + * + * idx can be within the array or one past the end to extend. + */ static int lupb_array_newindex(lua_State *L) { lupb_array *larray = lupb_array_check(L, 1); - upb_fieldtype_t type = upb_array_type(larray->arr); - uint32_t n = lupb_array_checkindex(L, 2, upb_array_size(larray->arr) + 1); - upb_msgval msgval = lupb_tomsgval(L, type, 3, larray->lmsgclass); - - upb_array_set(larray->arr, larray->type, n, msgval, lupb_arena_get(L)); + size_t size = upb_array_size(larray->arr); + uint32_t n = lupb_array_checkindex(L, 2, size + 1); + upb_msgval msgval = lupb_tomsgval(L, larray->type, 3, 1, LUPB_COPY); - if (lupb_istypewrapped(type)) { - lupb_uservalseti(L, 1, n, 3); + if (n == size) { + upb_array_append(larray->arr, msgval, lupb_arenaget(L, 1)); + } else { + upb_array_set(larray->arr, n, msgval); } return 0; /* 1 for chained assignments? */ } +/* lupb_array_index(): + * + * Handles: + * array[idx] -> val + * + * idx must be within the array. + */ static int lupb_array_index(lua_State *L) { lupb_array *larray = lupb_array_check(L, 1); - upb_array *array = larray->arr; - uint32_t n = lupb_array_checkindex(L, 2, upb_array_size(array)); - upb_fieldtype_t type = upb_array_type(array); + size_t size = upb_array_size(larray->arr); + uint32_t n = lupb_array_checkindex(L, 2, size); + upb_msgval val = upb_array_get(larray->arr, n); - if (lupb_istypewrapped(type)) { - lupb_uservalgeti(L, 1, n); - } else { - lupb_pushmsgval(L, upb_array_type(array), - upb_array_get(array, larray->type, n)); - } + lupb_pushmsgval(L, 1, larray->type, val); return 1; } +/* lupb_array_len(): + * + * Handles: + * #array -> len + */ static int lupb_array_len(lua_State *L) { lupb_array *larray = lupb_array_check(L, 1); lua_pushnumber(L, upb_array_size(larray->arr)); @@ -595,61 +501,16 @@ static const struct luaL_Reg lupb_array_mm[] = { /* lupb_map *******************************************************************/ -/* A map object. Implemented by wrapping upb_map. - * - * When the value type is string/bytes/message, the userval consists of: - * - * [Lua number/string] -> [lupb_string/lupb_msg userdata] - * - * For other value types we don't use the userdata. - */ - typedef struct { - const lupb_msgclass *value_lmsgclass; upb_map *map; + upb_fieldtype_t key_type; + upb_fieldtype_t value_type; } lupb_map; -#define MAP_MSGCLASS_INDEX 0 - -/* lupb_map internal functions */ +#define MAP_MSGDEF_INDEX 1 static lupb_map *lupb_map_check(lua_State *L, int narg) { - return luaL_checkudata(L, narg, LUPB_ARRAY); -} - -/** - * lupb_map_typecheck() - * - * Checks that the lupb_map at index |narg| can be safely assigned to the - * field |f| of the message at index |msg|. If so, returns a upb_msgval for - * this map. Otherwise, raises a Lua error. - */ -static upb_msgval lupb_map_typecheck(lua_State *L, int narg, int msg, - const upb_fielddef *f) { - lupb_map *lmap = lupb_map_check(L, narg); - upb_map *map = lmap->map; - const upb_msgdef *entry = upb_fielddef_msgsubdef(f); - const upb_fielddef *key_field = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY); - const upb_fielddef *value_field = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE); - - UPB_ASSERT(entry && key_field && value_field); - - if (upb_map_keytype(map) != upb_fielddef_type(key_field)) { - luaL_error(L, "Map key type invalid"); - } - - if (upb_map_valuetype(map) != upb_fielddef_type(value_field)) { - luaL_error(L, "Map had incorrect value type (expected: %s, got: %s)", - upb_fielddef_type(value_field), upb_map_valuetype(map)); - } - - if (upb_map_valuetype(map) == UPB_TYPE_MESSAGE) { - lupb_msgclass_typecheck( - L, lupb_msg_msgclassfor(L, msg, upb_fielddef_msgsubdef(value_field)), - lmap->value_lmsgclass); - } - - return upb_msgval_map(map); + return luaL_checkudata(L, narg, LUPB_MAP); } /* lupb_map Public API */ @@ -659,28 +520,29 @@ static upb_msgval lupb_map_typecheck(lua_State *L, int narg, int msg, * * Handles: * new_map = upb.Map(key_type, value_type) + * new_map = upb.Map(key_type, value_msgdef) */ static int lupb_map_new(lua_State *L) { + upb_arena *arena; lupb_map *lmap; - upb_fieldtype_t key_type = lupb_checkfieldtype(L, 1); - upb_fieldtype_t value_type; - const lupb_msgclass *value_lmsgclass = NULL; if (lua_type(L, 2) == LUA_TNUMBER) { - value_type = lupb_checkfieldtype(L, 2); + lmap = lupb_newuserdata(L, sizeof(*lmap), 1, LUPB_MAP); + lmap->value_type = lupb_checkfieldtype(L, 2); } else { - value_type = UPB_TYPE_MESSAGE; + lupb_msgdef_check(L, 2); + lmap = lupb_newuserdata(L, sizeof(*lmap), 2, LUPB_MAP); + lmap->value_type = UPB_TYPE_MESSAGE; + lua_pushvalue(L, 2); + lua_setiuservalue(L, -2, MAP_MSGDEF_INDEX); } - lmap = lupb_newuserdata(L, sizeof(*lmap), LUPB_MAP); + arena = lupb_arena_pushnew(L); + lua_setiuservalue(L, -2, LUPB_ARENA_INDEX); - if (value_type == UPB_TYPE_MESSAGE) { - value_lmsgclass = lupb_msgclass_check(L, 2); - lupb_uservalseti(L, -1, MAP_MSGCLASS_INDEX, 2); /* GC-root lmsgclass. */ - } - - lmap->value_lmsgclass = value_lmsgclass; - lmap->map = upb_map_new(key_type, value_type, lupb_arena_get(L)); + lmap->key_type = lupb_checkfieldtype(L, 1); + lmap->map = upb_map_new(arena, lmap->key_type, lmap->value_type); + lupb_cacheset(L, lmap->map); return 1; } @@ -693,28 +555,13 @@ static int lupb_map_new(lua_State *L) { */ static int lupb_map_index(lua_State *L) { lupb_map *lmap = lupb_map_check(L, 1); - upb_map *map = lmap->map; - upb_fieldtype_t valtype = upb_map_valuetype(map); - /* We don't always use "key", but this call checks the key type. */ - upb_msgval key = lupb_tomsgval(L, upb_map_keytype(map), 2, NULL); + upb_msgval key = lupb_tomsgval(L, lmap->key_type, 2, 1, LUPB_REF); + upb_msgval val; - if (lupb_istypewrapped(valtype)) { - /* Userval contains the full map, lookup there by key. */ - lupb_getuservalue(L, 1); - lua_pushvalue(L, 2); - lua_rawget(L, -2); - - if (lua_isnil(L, -1)) { - /* TODO: lazy read from upb_map */ - } + if (upb_map_get(lmap->map, key, &val)) { + lupb_pushmsgval(L, 1, lmap->value_type, val); } else { - /* Lookup in upb_map. */ - upb_msgval val; - if (upb_map_get(map, key, &val)) { - lupb_pushmsgval(L, upb_map_valuetype(map), val); - } else { - lua_pushnil(L); - } + lua_pushnil(L); } return 1; @@ -742,80 +589,52 @@ static int lupb_map_len(lua_State *L) { static int lupb_map_newindex(lua_State *L) { lupb_map *lmap = lupb_map_check(L, 1); upb_map *map = lmap->map; - upb_msgval key = lupb_tomsgval(L, upb_map_keytype(map), 2, NULL); + upb_msgval key = lupb_tomsgval(L, lmap->key_type, 2, 1, LUPB_REF); if (lua_isnil(L, 3)) { - /* Delete from map. */ - upb_map_del(map, key); - - if (lupb_istypewrapped(upb_map_valuetype(map))) { - /* Delete in userval. */ - lupb_getuservalue(L, 1); - lua_pushvalue(L, 2); - lua_pushnil(L); - lua_rawset(L, -3); - lua_pop(L, 1); - } + upb_map_delete(map, key); } else { - /* Set in map. */ - upb_msgval val = - lupb_tomsgval(L, upb_map_valuetype(map), 3, lmap->value_lmsgclass); - - upb_map_set(map, key, val, NULL); - - if (lupb_istypewrapped(upb_map_valuetype(map))) { - /* Set in userval. */ - lupb_getuservalue(L, 1); - lua_pushvalue(L, 2); - lua_pushvalue(L, 3); - lua_rawset(L, -3); - lua_pop(L, 1); - } + upb_msgval val = lupb_tomsgval(L, lmap->value_type, 3, 1, LUPB_COPY); + upb_map_set(map, key, val, lupb_arenaget(L, 1)); } return 0; } -/* upb_mapiter [[[ */ - static int lupb_mapiter_next(lua_State *L) { - upb_mapiter *i = lua_touserdata(L, lua_upvalueindex(1)); - lupb_map *lmap = lupb_map_check(L, 1); - upb_map *map = lmap->map; - - if (upb_mapiter_done(i)) { + int map = lua_upvalueindex(2); + size_t *iter = lua_touserdata(L, lua_upvalueindex(1)); + lupb_map *lmap = lupb_map_check(L, map); + + if (upb_mapiter_next(lmap->map, iter)) { + upb_msgval key = upb_mapiter_key(lmap->map, *iter); + upb_msgval val = upb_mapiter_value(lmap->map, *iter); + lupb_pushmsgval(L, map, lmap->key_type, key); + lupb_pushmsgval(L, map, lmap->value_type, val); + return 2; + } else { return 0; } - lupb_pushmsgval(L, upb_map_keytype(map), upb_mapiter_key(i)); - lupb_pushmsgval(L, upb_map_valuetype(map), upb_mapiter_value(i)); - upb_mapiter_next(i); - - return 2; } +/** + * lupb_map_pairs() + * + * Handles: + * pairs(map) + */ static int lupb_map_pairs(lua_State *L) { - lupb_map *lmap = lupb_map_check(L, 1); - - if (lupb_istypewrapped(upb_map_keytype(lmap->map)) || - lupb_istypewrapped(upb_map_valuetype(lmap->map))) { - /* Complex key or value type. - * Sync upb_map to userval if necessary, then iterate over userval. */ - - /* TODO: Lua tables don't know how many entries they have, gah!. */ - return 1; - } else { - /* Simple key and value type, iterate over the upb_map directly. */ - upb_mapiter *i = lua_newuserdata(L, upb_mapiter_sizeof()); + lupb_map_check(L, 1); + size_t *iter = lua_newuserdata(L, sizeof(*iter)); - upb_mapiter_begin(i, lmap->map); - lua_pushvalue(L, 1); + *iter = UPB_MAP_BEGIN; + lua_pushvalue(L, 1); - /* Upvalues are [upb_mapiter, lupb_map]. */ - lua_pushcclosure(L, &lupb_mapiter_next, 2); + /* Upvalues are [iter, lupb_map]. */ + lua_pushcclosure(L, &lupb_mapiter_next, 2); - return 1; - } + return 1; } /* upb_mapiter ]]] */ @@ -831,100 +650,119 @@ static const struct luaL_Reg lupb_map_mm[] = { /* lupb_msg *******************************************************************/ -/* A message object. Implemented by wrapping upb_msg. - * - * Our userval contains: - * - * - [0] -> our message class - * - [lupb_fieldindex(f)] -> [lupb_{string,array,map,msg} userdata] - * - * Fields with scalar number/bool types don't go in the userval. - */ - -#define LUPB_MSG_MSGCLASSINDEX 0 -#define LUPB_MSG_ARENA -1 - -int lupb_fieldindex(const upb_fielddef *f) { - return upb_fielddef_index(f) + 1; /* 1-based Lua arrays. */ -} - - typedef struct { - const lupb_msgclass *lmsgclass; upb_msg *msg; } lupb_msg; /* lupb_msg helpers */ -static bool in_userval(const upb_fielddef *f) { - return lupb_istypewrapped(upb_fielddef_type(f)) || upb_fielddef_isseq(f) || - upb_fielddef_ismap(f); -} - -lupb_msg *lupb_msg_check(lua_State *L, int narg) { +static upb_msg *lupb_msg_check(lua_State *L, int narg) { lupb_msg *msg = luaL_checkudata(L, narg, LUPB_MSG); - if (!msg->lmsgclass) luaL_error(L, "called into dead msg"); - return msg; -} - -const upb_msg *lupb_msg_checkmsg(lua_State *L, int narg, - const lupb_msgclass *lmsgclass) { - lupb_msg *lmsg = lupb_msg_check(L, narg); - lupb_msgclass_typecheck(L, lmsgclass, lmsg->lmsgclass); - return lmsg->msg; + return msg->msg; } -upb_msg *lupb_msg_checkmsg2(lua_State *L, int narg, - const upb_msglayout **layout) { - lupb_msg *lmsg = lupb_msg_check(L, narg); - *layout = lmsg->lmsgclass->layout; - return lmsg->msg; -} - -const upb_msgdef *lupb_msg_checkdef(lua_State *L, int narg) { - return lupb_msg_check(L, narg)->lmsgclass->msgdef; -} - -static const upb_fielddef *lupb_msg_checkfield(lua_State *L, - const lupb_msg *msg, - int fieldarg) { +static const upb_fielddef *lupb_msg_checkfield(lua_State *L, int msg, + int field) { size_t len; - const char *fieldname = luaL_checklstring(L, fieldarg, &len); - const upb_msgdef *msgdef = msg->lmsgclass->msgdef; - const upb_fielddef *f = upb_msgdef_ntof(msgdef, fieldname, len); - - if (!f) { - const char *msg = lua_pushfstring(L, "no such field: %s", fieldname); - luaL_argerror(L, fieldarg, msg); - return NULL; /* Never reached. */ + const char *fieldname = luaL_checklstring(L, field, &len); + const upb_msgdef *m; + const upb_fielddef *f; + + lua_getiuservalue(L, msg, LUPB_MSGDEF_INDEX); + m = lupb_msgdef_check(L, -1); + f = upb_msgdef_ntof(m, fieldname, len); + if (f == NULL) { + luaL_error(L, "no such field '%s'", fieldname); } + lua_pop(L, 1); return f; } -static const lupb_msgclass *lupb_msg_msgclassfor(lua_State *L, int narg, - const upb_msgdef *md) { - lupb_uservalgeti(L, narg, LUPB_MSG_MSGCLASSINDEX); - return lupb_msgclass_msgclassfor(L, -1, md); +/** + * lupb_msg_newmsgwrapper() + * + * Creates a new wrapper for a message, copying the arena and msgdef references + * from |narg| (which should be an array or map). + */ +static void lupb_msg_newmsgwrapper(lua_State *L, int narg, upb_msgval val) { + lupb_msg *lmsg = lupb_newuserdata(L, sizeof(*lmsg), 2, LUPB_MSG); + lmsg->msg = (upb_msg*)val.msg_val; /* XXX: cast isn't great. */ + lupb_cacheset(L, lmsg->msg); + + /* Copy both arena and msgdef into the wrapper. */ + lua_getiuservalue(L, narg, LUPB_ARENA_INDEX); + lua_setiuservalue(L, -2, LUPB_ARENA_INDEX); + lua_getiuservalue(L, narg, LUPB_MSGDEF_INDEX); + lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX); } -static const lupb_msgclass *lupb_msg_getsubmsgclass(lua_State *L, int narg, - const upb_fielddef *f) { - lupb_uservalgeti(L, narg, LUPB_MSG_MSGCLASSINDEX); - return lupb_msgclass_getsubmsgclass(L, -1, f); +/** + * lupb_msg_newud() + * + * Creates the Lua userdata for a new wrapper object, adding a reference to + * the msgdef if necessary. + */ +static void *lupb_msg_newud(lua_State *L, int narg, size_t size, + const char *type, const upb_fielddef *f) { + if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) { + /* Wrapper needs a reference to the msgdef. */ + void* ud = lupb_newuserdata(L, size, 2, type); + lua_getiuservalue(L, narg, LUPB_MSGDEF_INDEX); + lupb_msgdef_pushsubmsgdef(L, f); + lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX); + return ud; + } else { + return lupb_newuserdata(L, size, 1, type); + } } -int lupb_msg_pushref(lua_State *L, int msgclass, upb_msg *msg) { - const lupb_msgclass *lmsgclass = lupb_msgclass_check(L, msgclass); - lupb_msg *lmsg = lupb_newuserdata(L, sizeof(lupb_msg), LUPB_MSG); +/** + * lupb_msg_newwrapper() + * + * Creates a new Lua wrapper object to wrap the given array, map, or message. + */ +static void lupb_msg_newwrapper(lua_State *L, int narg, const upb_fielddef *f, + upb_mutmsgval val) { + if (upb_fielddef_ismap(f)) { + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key_f = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY); + const upb_fielddef *val_f = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE); + lupb_map *lmap = lupb_msg_newud(L, narg, sizeof(*lmap), LUPB_MAP, val_f); + lmap->key_type = upb_fielddef_type(key_f); + lmap->value_type = upb_fielddef_type(val_f); + lmap->map = val.map; + } else if (upb_fielddef_isseq(f)) { + lupb_array *larr = lupb_msg_newud(L, narg, sizeof(*larr), LUPB_ARRAY, f); + larr->type = upb_fielddef_type(f); + larr->arr = val.array; + } else { + lupb_msg *lmsg = lupb_msg_newud(L, narg, sizeof(*lmsg), LUPB_MSG, f); + lmsg->msg = val.msg; + } - lmsg->lmsgclass = lmsgclass; - lmsg->msg = msg; + /* Copy arena ref to new wrapper. This may be a different arena than the + * underlying data was originally constructed from, but if so both arenas + * must be in the same group. */ + lua_getiuservalue(L, narg, LUPB_ARENA_INDEX); + lua_setiuservalue(L, -2, LUPB_ARENA_INDEX); - lupb_uservalseti(L, -1, LUPB_MSG_MSGCLASSINDEX, msgclass); - lupb_uservalseti(L, -1, LUPB_MSG_ARENA, -2); + lupb_cacheset(L, val.msg); +} - return 1; +/** + * lupb_msg_typechecksubmsg() + * + * Typechecks the given array, map, or msg against this upb_fielddef. + */ +static void lupb_msg_typechecksubmsg(lua_State *L, int narg, int msgarg, + const upb_fielddef *f) { + /* Typecheck this map's msgdef against this message field. */ + lua_getiuservalue(L, narg, LUPB_MSGDEF_INDEX); + lua_getiuservalue(L, msgarg, LUPB_MSGDEF_INDEX); + lupb_msgdef_pushsubmsgdef(L, f); + luaL_argcheck(L, lua_rawequal(L, -1, -2), narg, "message type mismatch"); + lua_pop(L, 2); } /* lupb_msg Public API */ @@ -934,15 +772,31 @@ int lupb_msg_pushref(lua_State *L, int msgclass, upb_msg *msg) { * * Handles: * new_msg = MessageClass() + * new_msg = MessageClass{foo = "bar", baz = 3, quux = {foo = 3}} */ -static int lupb_msg_pushnew(lua_State *L, int narg) { - const lupb_msgclass *lmsgclass = lupb_msgclass_check(L, narg); - lupb_msg *lmsg = lupb_newuserdata(L, sizeof(lupb_msg), LUPB_MSG); - - lmsg->lmsgclass = lmsgclass; - lmsg->msg = upb_msg_new(lmsgclass->layout, lupb_arena_get(L)); - - lupb_uservalseti(L, -1, LUPB_MSG_MSGCLASSINDEX, narg); +int lupb_msg_pushnew(lua_State *L) { + int argcount = lua_gettop(L); + const upb_msgdef *m = lupb_msgdef_check(L, 1); + lupb_msg *lmsg = lupb_newuserdata(L, sizeof(lupb_msg), 2, LUPB_MSG); + upb_arena *arena = lupb_arena_pushnew(L); + + lua_setiuservalue(L, -2, LUPB_ARENA_INDEX); + lua_pushvalue(L, 1); + lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX); + + lmsg->msg = upb_msg_new(m, arena); + lupb_cacheset(L, lmsg->msg); + + if (argcount > 1) { + /* Set initial fields from table. */ + int msg = lua_gettop(L); + lua_pushnil(L); + while (lua_next(L, 2) != 0) { + lua_pushvalue(L, -2); /* now stack is key, val, key */ + lua_insert(L, -3); /* now stack is key, key, val */ + lua_settable(L, msg); + } + } return 1; } @@ -956,33 +810,20 @@ static int lupb_msg_pushnew(lua_State *L, int narg) { * msg[field_descriptor] # (for extensions) (TODO) */ static int lupb_msg_index(lua_State *L) { - lupb_msg *lmsg = lupb_msg_check(L, 1); - const upb_fielddef *f = lupb_msg_checkfield(L, lmsg, 2); - const upb_msglayout *l = lmsg->lmsgclass->layout; - int field_index = upb_fielddef_index(f); - - if (in_userval(f)) { - lupb_uservalgeti(L, 1, lupb_fieldindex(f)); - - if (lua_isnil(L, -1)) { - /* Check if we need to lazily create wrapper. */ - if (upb_fielddef_isseq(f)) { - /* TODO(haberman) */ - } else if (upb_fielddef_issubmsg(f)) { - /* TODO(haberman) */ - } else { - UPB_ASSERT(upb_fielddef_isstring(f)); - if (upb_msg_has(lmsg->msg, field_index, l)) { - upb_msgval val = upb_msg_get(lmsg->msg, field_index, l); - lua_pop(L, 1); - lua_pushlstring(L, val.str.data, val.str.size); - lupb_uservalseti(L, 1, lupb_fieldindex(f), -1); - } - } + upb_msg *msg = lupb_msg_check(L, 1); + const upb_fielddef *f = lupb_msg_checkfield(L, 1, 2); + + if (upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f)) { + /* Wrapped type; get or create wrapper. */ + upb_arena *arena = upb_fielddef_isseq(f) ? lupb_arenaget(L, 1) : NULL; + upb_mutmsgval val = upb_msg_mutable(msg, f, arena); + if (!lupb_cacheget(L, val.msg)) { + lupb_msg_newwrapper(L, 1, f, val); } } else { - upb_msgval val = upb_msg_get(lmsg->msg, field_index, l); - lupb_pushmsgval(L, upb_fielddef_type(f), val); + /* Value type, just push value and return .*/ + upb_msgval val = upb_msg_get(msg, f); + lupb_pushmsgval(L, 0, upb_fielddef_type(f), val); } return 1; @@ -997,37 +838,53 @@ static int lupb_msg_index(lua_State *L) { * msg[field_descriptor] = bar # (for extensions) (TODO) */ static int lupb_msg_newindex(lua_State *L) { - lupb_msg *lmsg = lupb_msg_check(L, 1); - const upb_fielddef *f = lupb_msg_checkfield(L, lmsg, 2); - upb_fieldtype_t type = upb_fielddef_type(f); - int field_index = upb_fielddef_index(f); + upb_msg *msg = lupb_msg_check(L, 1); + const upb_fielddef *f = lupb_msg_checkfield(L, 1, 2); upb_msgval msgval; - - /* Typecheck and get msgval. */ - - if (upb_fielddef_isseq(f)) { - msgval = lupb_array_typecheck(L, 3, 1, f); - } else if (upb_fielddef_ismap(f)) { - msgval = lupb_map_typecheck(L, 3, 1, f); - } else { - const lupb_msgclass *lmsgclass = NULL; - + bool merge_arenas = true; + + if (upb_fielddef_ismap(f)) { + lupb_map *lmap = lupb_map_check(L, 3); + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key_f = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY); + const upb_fielddef *val_f = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE); + upb_fieldtype_t key_type = upb_fielddef_type(key_f); + upb_fieldtype_t value_type = upb_fielddef_type(val_f); + luaL_argcheck(L, lmap->key_type == key_type, 3, "key type mismatch"); + luaL_argcheck(L, lmap->value_type == value_type, 3, "value type mismatch"); + if (value_type == UPB_TYPE_MESSAGE) { + lupb_msg_typechecksubmsg(L, 3, 1, val_f); + } + msgval.map_val = lmap->map; + } else if (upb_fielddef_isseq(f)) { + lupb_array *larr = lupb_array_check(L, 3); + upb_fieldtype_t type = upb_fielddef_type(f); + luaL_argcheck(L, larr->type == type, 3, "array type mismatch"); if (type == UPB_TYPE_MESSAGE) { - lmsgclass = lupb_msg_getsubmsgclass(L, 1, f); + lupb_msg_typechecksubmsg(L, 3, 1, f); } - - msgval = lupb_tomsgval(L, type, 3, lmsgclass); + msgval.array_val = larr->arr; + } else if (upb_fielddef_issubmsg(f)) { + upb_msg *msg = lupb_msg_check(L, 3); + lupb_msg_typechecksubmsg(L, 3, 1, f); + msgval.msg_val = msg; + } else { + msgval = lupb_tomsgval(L, upb_fielddef_type(f), 3, 1, LUPB_COPY); + merge_arenas = false; } - /* Set in upb_msg and userval (if necessary). */ - - upb_msg_set(lmsg->msg, field_index, msgval, lmsg->lmsgclass->layout); - - if (in_userval(f)) { - lupb_uservalseti(L, 1, lupb_fieldindex(f), 3); + 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)); + lua_pop(L, 2); } - return 0; /* 1 for chained assignments? */ + upb_msg_set(msg, f, msgval, lupb_arenaget(L, 1)); + + /* Return the new value for chained assignments. */ + lua_pushvalue(L, 3); + return 1; } static const struct luaL_Reg lupb_msg_mm[] = { @@ -1039,22 +896,89 @@ static const struct luaL_Reg lupb_msg_mm[] = { /* lupb_msg toplevel **********************************************************/ +/** + * lupb_decode() + * + * Handles: + * msg = upb.decode(MessageClass, bin_string) + */ +static int lupb_decode(lua_State *L) { + size_t len; + 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); + upb_msg *msg; + upb_arena *arena; + bool ok; + + /* Create message. */ + lua_pushcfunction(L, &lupb_msg_pushnew); + lua_pushvalue(L, 1); + lua_call(L, 1, 1); + msg = lupb_msg_check(L, -1); + + 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); + + if (!ok) { + lua_pushstring(L, "Error decoding protobuf."); + return lua_error(L); + } + + return 1; +} + +/** + * lupb_encode() + * + * Handles: + * bin_string = upb.encode(msg) + */ +static int lupb_encode(lua_State *L) { + const upb_msg *msg = lupb_msg_check(L, 1); + const upb_msglayout *layout; + upb_arena *arena = lupb_arena_pushnew(L); + size_t size; + char *result; + + lua_getiuservalue(L, 1, LUPB_MSGDEF_INDEX); + layout = upb_msgdef_layout(lupb_msgdef_check(L, -1)); + lua_pop(L, 1); + + result = upb_encode(msg, (const void*)layout, arena, &size); + + if (!result) { + lua_pushstring(L, "Error encoding protobuf."); + return lua_error(L); + } + + lua_pushlstring(L, result, size); + + return 1; +} + static const struct luaL_Reg lupb_msg_toplevel_m[] = { {"Array", lupb_array_new}, {"Map", lupb_map_new}, - {"MessageFactory", lupb_msgfactory_new}, + {"decode", lupb_decode}, + {"encode", lupb_encode}, {NULL, NULL} }; void lupb_msg_registertypes(lua_State *L) { lupb_setfuncs(L, lupb_msg_toplevel_m); - lupb_register_type(L, LUPB_ARENA, NULL, lupb_arena_mm); - lupb_register_type(L, LUPB_MSGCLASS, NULL, lupb_msgclass_mm); - lupb_register_type(L, LUPB_MSGFACTORY, lupb_msgfactory_m, lupb_msgfactory_mm); - lupb_register_type(L, LUPB_ARRAY, NULL, lupb_array_mm); - lupb_register_type(L, LUPB_MAP, NULL, lupb_map_mm); - lupb_register_type(L, LUPB_MSG, NULL, lupb_msg_mm); + lupb_register_type(L, LUPB_ARENA, NULL, lupb_arena_mm); + lupb_register_type(L, LUPB_ARRAY, NULL, lupb_array_mm); + lupb_register_type(L, LUPB_MAP, NULL, lupb_map_mm); + lupb_register_type(L, LUPB_MSG, NULL, lupb_msg_mm); - lupb_arena_initsingleton(L); + lupb_cacheinit(L); } diff --git a/upb/bindings/lua/upb.c b/upb/bindings/lua/upb.c index 38fd24a27e..3630ae2ef3 100644 --- a/upb/bindings/lua/upb.c +++ b/upb/bindings/lua/upb.c @@ -20,103 +20,91 @@ ** domain of [u]int64 values. */ +#include "upb/bindings/lua/upb.h" + #include #include #include #include + #include "lauxlib.h" -#include "upb/bindings/lua/upb.h" -#include "upb/handlers.h" #include "upb/msg.h" - /* Lua compatibility code *****************************************************/ -/* Lua 5.1 and Lua 5.2 have slightly incompatible APIs. A little bit of - * compatibility code can help hide the difference. Not too many people still - * use Lua 5.1 but LuaJIT uses the Lua 5.1 API in some ways. */ +/* Shims for upcoming Lua 5.3 functionality. */ +static bool lua_isinteger(lua_State *L, int argn) { + LUPB_UNUSED(L); + LUPB_UNUSED(argn); + return false; +} -#if LUA_VERSION_NUM == 501 -/* taken from lua 5.2's source. */ -void *luaL_testudata(lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } +/* Utility functions **********************************************************/ + +void lupb_checkstatus(lua_State *L, upb_status *s) { + if (!upb_ok(s)) { + lua_pushstring(L, upb_status_errmsg(s)); + lua_error(L); } - return NULL; /* value is not a userdata with a metatable */ } -static void lupb_newlib(lua_State *L, const char *name, const luaL_Reg *funcs) { - luaL_register(L, name, funcs); -} +/* Pushes a new userdata with the given metatable. */ +void *lupb_newuserdata(lua_State *L, size_t size, int n, const char *type) { +#if LUA_VERSION_NUM >= 504 + void *ret = lua_newuserdatauv(L, size, n); +#else + void *ret = lua_newuserdata(L, size); + lua_createtable(L, 0, n); + lua_setuservalue(L, -2); +#endif -#elif LUA_VERSION_NUM == 502 + /* Set metatable. */ + luaL_getmetatable(L, type); + assert(!lua_isnil(L, -1)); /* Should have been created by luaopen_upb. */ + lua_setmetatable(L, -2); -int luaL_typerror(lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", - tname, luaL_typename(L, narg)); - return luaL_argerror(L, narg, msg); + return ret; } -static void lupb_newlib(lua_State *L, const char *name, const luaL_Reg *funcs) { - /* Lua 5.2 modules are not expected to set a global variable, so "name" is - * unused. */ - UPB_UNUSED(name); - - /* Can't use luaL_newlib(), because funcs is not the actual array. - * Could (micro-)optimize this a bit to count funcs for initial table size. */ - lua_createtable(L, 0, 8); - luaL_setfuncs(L, funcs, 0); +#if LUA_VERSION_NUM < 504 +int lua_setiuservalue(lua_State *L, int index, int n) { + lua_getuservalue(L, index); + lua_insert(L, -2); + lua_rawseti(L, -2, n); + lua_pop(L, 1); + return 1; } -#else -#error Only Lua 5.1 and 5.2 are supported -#endif - -/* Shims for upcoming Lua 5.3 functionality. */ -bool lua_isinteger(lua_State *L, int argn) { - UPB_UNUSED(L); - UPB_UNUSED(argn); - return false; +int lua_getiuservalue(lua_State *L, int index, int n) { + lua_getuservalue(L, index); + lua_rawgeti(L, -1, n); + lua_replace(L, -2); + return 1; } +#endif +void lupb_register_type(lua_State *L, const char *name, const luaL_Reg *m, + const luaL_Reg *mm) { + luaL_newmetatable(L, name); -/* Utility functions **********************************************************/ - -/* We store our module table in the registry, keyed by ptr. - * For more info about the motivation/rationale, see this thread: - * http://thread.gmane.org/gmane.comp.lang.lua.general/110632 */ -bool lupb_openlib(lua_State *L, void *ptr, const char *name, - const luaL_Reg *funcs) { - /* Lookup cached module table. */ - lua_pushlightuserdata(L, ptr); - lua_rawget(L, LUA_REGISTRYINDEX); - if (!lua_isnil(L, -1)) { - return true; + if (mm) { + lupb_setfuncs(L, mm); } - lupb_newlib(L, name, funcs); - - /* Save module table in cache. */ - lua_pushlightuserdata(L, ptr); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); - - return false; -} + if (m) { + /* Methods go in the mt's __index method. This implies that you can' + * implement __index and also have methods. */ + lua_getfield(L, -1, "__index"); + lupb_assert(L, lua_isnil(L, -1)); + lua_pop(L, 1); -void lupb_checkstatus(lua_State *L, upb_status *s) { - if (!upb_ok(s)) { - lua_pushstring(L, upb_status_errmsg(s)); - lua_error(L); + lua_createtable(L, 0, 0); + lupb_setfuncs(L, m); + lua_setfield(L, -2, "__index"); } + + lua_pop(L, 1); /* The mt. */ } /* Scalar type mapping ********************************************************/ @@ -204,42 +192,16 @@ void lupb_pushfloat(lua_State *L, float d) { lua_pushnumber(L, d); } +/* Library entry point ********************************************************/ -static const struct luaL_Reg lupb_toplevel_m[] = { - {NULL, NULL} -}; - -void lupb_register_type(lua_State *L, const char *name, const luaL_Reg *m, - const luaL_Reg *mm) { - luaL_newmetatable(L, name); - - if (mm) { - lupb_setfuncs(L, mm); - } - - if (m) { - /* Methods go in the mt's __index method. This implies that you can' - * implement __index and also have methods. */ - lua_getfield(L, -1, "__index"); - lupb_assert(L, lua_isnil(L, -1)); - lua_pop(L, 1); - - lua_createtable(L, 0, 0); - lupb_setfuncs(L, m); - lua_setfield(L, -2, "__index"); - } - - lua_pop(L, 1); /* The mt. */ -} - -int luaopen_upb_c(lua_State *L) { - static char module_key; - if (lupb_openlib(L, &module_key, "upb_c", lupb_toplevel_m)) { - return 1; - } - +int luaopen_lupb(lua_State *L) { +#if LUA_VERSION_NUM == 501 + const struct luaL_Reg funcs[] = {{NULL, NULL}}; + luaL_register(L, "upb_c", funcs); +#else + lua_createtable(L, 0, 8); +#endif lupb_def_registertypes(L); lupb_msg_registertypes(L); - return 1; /* Return package table. */ } diff --git a/upb/bindings/lua/upb.h b/upb/bindings/lua/upb.h index 51d8acf9e4..02ed341098 100644 --- a/upb/bindings/lua/upb.h +++ b/upb/bindings/lua/upb.h @@ -7,65 +7,46 @@ #include "lauxlib.h" #include "upb/def.h" -#include "upb/handlers.h" #include "upb/msg.h" -#include "upb/msgfactory.h" -/* Lua 5.1/5.2 compatibility code. */ -#if LUA_VERSION_NUM == 501 +/* Lua changes its API in incompatible ways in every minor release. + * This is some shim code to paper over the differences. */ +#if LUA_VERSION_NUM == 501 #define lua_rawlen lua_objlen - -/* Lua >= 5.2's getuservalue/setuservalue functions do not exist in prior - * versions but the older function lua_getfenv() can provide 100% of its - * capabilities (the reverse is not true). */ -#define lua_getuservalue(L, index) lua_getfenv(L, index) -#define lua_setuservalue(L, index) lua_setfenv(L, index) - -void *luaL_testudata(lua_State *L, int ud, const char *tname); - +#define lua_setuservalue(L, idx) lua_setfenv(L, idx) +#define lua_getuservalue(L, idx) lua_getfenv(L, idx) #define lupb_setfuncs(L, l) luaL_register(L, NULL, l) +#elif LUA_VERSION_NUM >= 502 && LUA_VERSION_NUM <= 504 +#define lupb_setfuncs(L, l) luaL_setfuncs(L, l, 0) +#else +#error Only Lua 5.1-5.4 are supported +#endif -#elif LUA_VERSION_NUM == 502 +/* Create a new userdata with the given type and |n| uservals, which are popped + * from the stack to initialize the userdata. */ +void *lupb_newuserdata(lua_State *L, size_t size, int n, const char *type); -int luaL_typerror(lua_State *L, int narg, const char *tname); +#if LUA_VERSION_NUM < 504 +/* Polyfills for this Lua 5.4 function. Pushes userval |n| for the userdata at + * |index|. */ +int lua_setiuservalue(lua_State *L, int index, int n); +int lua_getiuservalue(lua_State *L, int index, int n); +#endif -#define lupb_setfuncs(L, l) luaL_setfuncs(L, l, 0) +/* Registers a type with the given name, methods, and metamethods. */ +void lupb_register_type(lua_State *L, const char *name, const luaL_Reg *m, + const luaL_Reg *mm); -#else -#error Only Lua 5.1 and 5.2 are supported -#endif +/* Checks the given upb_status and throws a Lua error if it is not ok. */ +void lupb_checkstatus(lua_State *L, upb_status *s); -#define lupb_assert(L, predicate) \ - if (!(predicate)) \ - luaL_error(L, "internal error: %s, %s:%d ", #predicate, __FILE__, __LINE__); +int luaopen_lupb(lua_State *L); -/* Function for initializing the core library. This function is idempotent, - * and should be called at least once before calling any of the functions that - * construct core upb types. */ -int luaopen_upb(lua_State *L); - -/* Gets or creates a package table for a C module that is uniquely identified by - * "ptr". The easiest way to supply a unique "ptr" is to pass the address of a - * static variable private in the module's .c file. - * - * If this module has already been registered in this lua_State, pushes it and - * returns true. - * - * Otherwise, creates a new module table for this module with the given name, - * pushes it, and registers the given top-level functions in it. It also sets - * it as a global variable, but only if the current version of Lua expects that - * (ie Lua 5.1/LuaJIT). - * - * If "false" is returned, the caller is guaranteed that this lib has not been - * registered in this Lua state before (regardless of any funny business the - * user might have done to the global state), so the caller can safely perform - * one-time initialization. */ -bool lupb_openlib(lua_State *L, void *ptr, const char *name, - const luaL_Reg *funcs); +/* C <-> Lua value conversions. ***********************************************/ /* Custom check/push functions. Unlike the Lua equivalents, they are pinned to - * specific types (instead of lua_Number, etc), and do not allow any implicit + * specific C types (instead of lua_Number, etc), and do not allow any implicit * conversion or data loss. */ int64_t lupb_checkint64(lua_State *L, int narg); int32_t lupb_checkint32(lua_State *L, int narg); @@ -81,47 +62,35 @@ void lupb_pushint64(lua_State *L, int64_t val); void lupb_pushint32(lua_State *L, int32_t val); void lupb_pushuint64(lua_State *L, uint64_t val); void lupb_pushuint32(lua_State *L, uint32_t val); -void lupb_pushdouble(lua_State *L, double val); -void lupb_pushfloat(lua_State *L, float val); - -/* Registers a type with the given name, methods, and metamethods. */ -void lupb_register_type(lua_State *L, const char *name, const luaL_Reg *m, - const luaL_Reg *mm); - -/* Checks the given upb_status and throws a Lua error if it is not ok. */ -void lupb_checkstatus(lua_State *L, upb_status *s); - /** From def.c. ***************************************************************/ -upb_fieldtype_t lupb_checkfieldtype(lua_State *L, int narg); - const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg); const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg); const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg); upb_symtab *lupb_symtab_check(lua_State *L, int narg); +void lupb_msgdef_pushsubmsgdef(lua_State *L, const upb_fielddef *f); void lupb_def_registertypes(lua_State *L); - /** From msg.c. ***************************************************************/ -struct lupb_msgclass; -typedef struct lupb_msgclass lupb_msgclass; - -upb_arena *lupb_arena_check(lua_State *L, int narg); -int lupb_arena_new(lua_State *L); -upb_arena *lupb_arena_get(lua_State *L); -int lupb_msg_pushref(lua_State *L, int msgclass, void *msg); -const upb_msg *lupb_msg_checkmsg(lua_State *L, int narg, - const lupb_msgclass *lmsgclass); -upb_msg *lupb_msg_checkmsg2(lua_State *L, int narg, - const upb_msglayout **layout); - -const lupb_msgclass *lupb_msgclass_check(lua_State *L, int narg); -const upb_msglayout *lupb_msgclass_getlayout(lua_State *L, int narg); -const upb_msgdef *lupb_msgclass_getmsgdef(const lupb_msgclass *lmsgclass); -upb_msgfactory *lupb_msgclass_getfactory(const lupb_msgclass *lmsgclass); +int lupb_msg_pushnew(lua_State *L); +upb_arena *lupb_arena_pushnew(lua_State *L); + void lupb_msg_registertypes(lua_State *L); +#define lupb_assert(L, predicate) \ + if (!(predicate)) \ + luaL_error(L, "internal error: %s, %s:%d ", #predicate, __FILE__, __LINE__); + +#define LUPB_UNUSED(var) (void)var + +#if defined(__GNUC__) || defined(__clang__) +#define LUPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0) +#else +#define LUPB_UNREACHABLE() do { assert(0); } while(0) +#endif + + #endif /* UPB_LUA_UPB_H_ */ diff --git a/upb/bindings/lua/upb.lua b/upb/bindings/lua/upb.lua index 728852e997..ad6184a3d3 100644 --- a/upb/bindings/lua/upb.lua +++ b/upb/bindings/lua/upb.lua @@ -1,172 +1,30 @@ --- Before calling require on "upb_c", we need to load the same library --- as RTLD_GLOBAL, for the benefit of other C extensions that depend on --- C functions in the core. --- --- This has to happen *before* the require call, because if the module --- is loaded RTLD_LOCAL first, a subsequent load as RTLD_GLOBAL won't --- have the proper effect, at least on some platforms. -local so = package.searchpath and package.searchpath("upb_c", package.cpath) -if so then - package.loadlib(so, "*") -end - -local upb = require("upb_c") - --- A convenience function for building/linking/freezing defs --- while maintaining their original order. --- --- Sample usage: --- local m1, m2 = upb.build_defs{ --- upb.MessageDef{full_name = "M1", fields = { --- upb.FieldDef{ --- name = "m2", --- number = 1, --- type = upb.TYPE_MESSAGE, --- subdef_name = ".M2" --- }, --- } --- }, --- upb.MessageDef{full_name = "M2"} --- } -upb.build_defs = function(defs) - upb.SymbolTable(defs) - -- Lua 5.2 puts unpack in the table library. - return (unpack or table.unpack)(defs) -end +local upb = require("lupb") -local ipairs_iter = function(array, last_index) - local next_index = last_index + 1 - if next_index > #array then - return nil - end - return next_index, array[next_index] -end +upb.generated_pool = upb.SymbolTable() --- For iterating over the indexes and values of a upb.Array. --- --- for i, val in upb.ipairs(array) do --- -- ... --- end -upb.ipairs = function(array) - return ipairs_iter, array, 0 -end - -local set_named = function(obj, init) - for k, v in pairs(init) do - local func = obj["set_" .. k] - if not func then - error("Cannot set member: " .. k) +local module_metatable = { + __index = function(t, k) + local package = t._filedef:package() + if package then + k = package .. "." .. k end - func(obj, v) - end -end - --- Capture references to the functions we're wrapping. -local RealFieldDef = upb.FieldDef -local RealEnumDef = upb.EnumDef -local RealMessageDef = upb.MessageDef -local RealOneofDef = upb.OneofDef -local RealSymbolTable = upb.SymbolTable - --- FieldDef constructor; a wrapper around the real constructor that can --- set initial properties. --- --- User can specify initialization values like so: --- upb.FieldDef{label=upb.LABEL_REQUIRED, name="my_field", number=5, --- type=upb.TYPE_INT32, default_value=12, type_name="Foo"} -upb.FieldDef = function(init) - local f = RealFieldDef() - - if init then - -- Other members are often dependent on type, so set that first. - if init.type then - f:set_type(init.type) - init.type = nil - end - - set_named(f, init) - end - - return f -end - - --- MessageDef constructor; a wrapper around the real constructor that can --- set initial properties. --- --- User can specify initialization values like so: --- upb.MessageDef{full_name="MyMessage", extstart=8000, fields={...}} -upb.MessageDef = function(init) - local m = RealMessageDef() - - if init then - for _, f in pairs(init.fields or {}) do - m:add(f) + local pool = upb.generated_pool + local def = pool:lookup_msg(k) or pool:lookup_enum(k) + local v = nil + if def and def:file():name() == t._filedef:name() then + v = def + t[k] = v end - init.fields = nil - - set_named(m, init) - end - - return m -end - --- EnumDef constructor; a wrapper around the real constructor that can --- set initial properties. --- --- User can specify initialization values like so: --- upb.EnumDef{full_name="MyEnum", --- values={ --- {"FOO_VALUE_1", 1}, --- {"FOO_VALUE_2", 2} --- } --- } -upb.EnumDef = function(init) - local e = RealEnumDef() - - if init then - for _, val in pairs(init.values or {}) do - e:add(val[1], val[2]) - end - init.values = nil - - set_named(e, init) - end - - return e -end - --- OneofDef constructor; a wrapper around the real constructor that can --- set initial properties. --- --- User can specify initialization values like so: --- upb.OneofDef{name="foo", fields={...}} -upb.OneofDef = function(init) - local o = RealOneofDef() - - if init then - for _, val in pairs(init.fields or {}) do - o:add(val) - end - init.fields = nil - - set_named(o, init) - end - - return o -end - --- SymbolTable constructor; a wrapper around the real constructor that can --- add an initial set of defs. -upb.SymbolTable = function(defs) - local s = RealSymbolTable() - - if defs then - s:add(defs) + return v end +} - return s +function upb._generated_module(desc_string) + local file = upb.generated_pool:add_file(desc_string) + local module = {_filedef = file} + setmetatable(module, module_metatable) + return module end return upb diff --git a/upb/bindings/lua/upb/pb.c b/upb/bindings/lua/upb/pb.c deleted file mode 100644 index 266bd974c9..0000000000 --- a/upb/bindings/lua/upb/pb.c +++ /dev/null @@ -1,56 +0,0 @@ -/* -** require("upb.pb") -- A Lua extension for upb.pb. -** -** Exposes all the types defined in upb/pb/{*}.h -** Also defines a few convenience functions on top. -*/ - -#include "upb/bindings/lua/upb.h" -#include "upb/decode.h" -#include "upb/encode.h" - -#define LUPB_PBDECODERMETHOD "lupb.pb.decodermethod" - -static int lupb_pb_decode(lua_State *L) { - size_t len; - const upb_msglayout *layout; - upb_msg *msg = lupb_msg_checkmsg2(L, 1, &layout); - const char *pb = lua_tolstring(L, 2, &len); - - upb_decode(pb, len, msg, layout, lupb_arena_get(L)); - /* TODO(haberman): check for error. */ - - return 0; -} - -static int lupb_pb_encode(lua_State *L) { - const upb_msglayout *layout; - const upb_msg *msg = lupb_msg_checkmsg2(L, 1, &layout); - upb_arena *arena = upb_arena_new(); - size_t size; - char *result; - - result = upb_encode(msg, (const void*)layout, arena, &size); - - /* Free resources before we potentially bail on error. */ - lua_pushlstring(L, result, size); - upb_arena_free(arena); - /* TODO(haberman): check for error. */ - - return 1; -} - -static const struct luaL_Reg toplevel_m[] = { - {"decode", lupb_pb_decode}, - {"encode", lupb_pb_encode}, - {NULL, NULL} -}; - -int luaopen_upb_pb_c(lua_State *L) { - static char module_key; - if (lupb_openlib(L, &module_key, "upb.pb_c", toplevel_m)) { - return 1; - } - - return 1; -} diff --git a/upb/bindings/lua/upb/pb.lua b/upb/bindings/lua/upb/pb.lua deleted file mode 100644 index b865902d3a..0000000000 --- a/upb/bindings/lua/upb/pb.lua +++ /dev/null @@ -1,3 +0,0 @@ - -require "upb" -return require "upb.pb_c" diff --git a/upb/bindings/lua/upbc.cc b/upb/bindings/lua/upbc.cc new file mode 100644 index 0000000000..e7563bc0ba --- /dev/null +++ b/upb/bindings/lua/upbc.cc @@ -0,0 +1,112 @@ + +#include "absl/strings/string_view.h" +#include "absl/strings/substitute.h" +#include "absl/strings/str_replace.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include +#include + +namespace protoc = ::google::protobuf::compiler; +namespace protobuf = ::google::protobuf; + +class LuaGenerator : public protoc::CodeGenerator { + bool Generate(const protobuf::FileDescriptor* file, + const std::string& parameter, protoc::GeneratorContext* context, + std::string* error) const override; + +}; + +static std::string StripExtension(absl::string_view fname) { + size_t lastdot = fname.find_last_of("."); + if (lastdot == std::string::npos) { + return std::string(fname); + } + return std::string(fname.substr(0, lastdot)); +} + +static std::string Filename(const protobuf::FileDescriptor* file) { + return StripExtension(file->name()) + "_pb.lua"; +} + +static std::string ModuleName(const protobuf::FileDescriptor* file) { + std::string ret = StripExtension(file->name()) + "_pb"; + return absl::StrReplaceAll(ret, {{"/", "."}}); +} + +static void PrintHexDigit(char digit, protobuf::io::Printer* printer) { + char text; + if (digit < 10) { + text = '0' + digit; + } else { + text = 'A' + (digit - 10); + } + printer->WriteRaw(&text, 1); +} + +static void PrintString(int max_cols, absl::string_view* str, + protobuf::io::Printer* printer) { + printer->Print("\'"); + while (max_cols > 0 && !str->empty()) { + char ch = (*str)[0]; + if (ch == '\\') { + printer->PrintRaw("\\\\"); + max_cols--; + } else if (ch == '\'') { + printer->PrintRaw("\\'"); + max_cols--; + } else if (isprint(ch)) { + printer->WriteRaw(&ch, 1); + max_cols--; + } else { + unsigned char byte = ch; + printer->PrintRaw("\\x"); + PrintHexDigit(byte >> 4, printer); + PrintHexDigit(byte & 15, printer); + max_cols -= 4; + } + str->remove_prefix(1); + } + printer->Print("\'"); +} + +bool LuaGenerator::Generate( + const protobuf::FileDescriptor* file, + const std::string& parameter, + protoc::GeneratorContext* context, + std::string* error) const { + std::string filename = Filename(file); + protobuf::io::ZeroCopyOutputStream* out = context->Open(filename); + protobuf::io::Printer printer(out, '$'); + + for (int i = 0; i < file->dependency_count(); i++) { + const protobuf::FileDescriptor* dep = file->dependency(i); + printer.Print("require('$name$')\n", "name", ModuleName(dep)); + } + + printer.Print("local upb = require('upb')\n"); + + protobuf::FileDescriptorProto file_proto; + file->CopyTo(&file_proto); + std::string file_data; + file_proto.SerializeToString(&file_data); + + printer.Print("local descriptor = table.concat({\n"); + absl::string_view data(file_data); + while (!data.empty()) { + printer.Print(" "); + PrintString(72, &data, &printer); + printer.Print(",\n"); + } + printer.Print("})\n"); + + printer.Print("return upb._generated_module(descriptor)\n"); + + return true; +} + +int main(int argc, char** argv) { + LuaGenerator generator; + return google::protobuf::compiler::PluginMain(argc, argv, &generator); +} diff --git a/upb/decode.c b/upb/decode.c index 4672b1b84b..f1be7502c3 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -6,8 +6,8 @@ #include "upb/port_def.inc" /* Maps descriptor type -> upb field type. */ -const uint8_t upb_desctype_to_fieldtype[] = { - UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ +static const uint8_t desctype_to_fieldtype[] = { + -1, /* invalid descriptor type */ UPB_TYPE_DOUBLE, /* DOUBLE */ UPB_TYPE_FLOAT, /* FLOAT */ UPB_TYPE_INT64, /* INT64 */ @@ -28,6 +28,29 @@ const uint8_t upb_desctype_to_fieldtype[] = { 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 */ +}; + /* Data pertaining to the parse. */ typedef struct { const char *ptr; /* Current parsing position. */ @@ -166,35 +189,12 @@ static bool upb_skip_unknowngroup(upb_decstate *d, int field_number) { return true; } -static bool upb_array_grow(upb_array *arr, size_t elements, size_t elem_size, - upb_arena *arena) { - size_t needed = arr->len + elements; - size_t new_size = UPB_MAX(arr->size, 8); - size_t new_bytes; - size_t old_bytes; - void *new_data; - upb_alloc *alloc = upb_arena_alloc(arena); - - while (new_size < needed) { - new_size *= 2; - } - - old_bytes = arr->len * elem_size; - new_bytes = new_size * elem_size; - new_data = upb_realloc(alloc, arr->data, old_bytes, new_bytes); - CHK(new_data); - - arr->data = new_data; - arr->size = new_size; - return true; -} - 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_grow(arr, elements, elem_size, arena)); + CHK(_upb_array_realloc(arr, arr->len + elements, arena)); } - return (char*)arr->data + (arr->len * elem_size); + return (char*)_upb_array_ptr(arr) + (arr->len * elem_size); } bool upb_array_add(upb_array *arr, size_t elements, size_t elem_size, @@ -219,7 +219,8 @@ static upb_array *upb_getorcreatearr(upb_decframe *frame, upb_array *arr = upb_getarr(frame, field); if (!arr) { - arr = upb_array_new(frame->state->arena); + upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype]; + arr = _upb_array_new(frame->state->arena, type); CHK(arr); *(upb_array**)&frame->msg[field->offset] = arr; } @@ -236,7 +237,7 @@ static upb_msg *upb_getorcreatemsg(upb_decframe *frame, UPB_ASSERT(field->label != UPB_LABEL_REPEATED); if (!*submsg) { - *submsg = upb_msg_new(*subm, frame->state->arena); + *submsg = _upb_msg_new(*subm, frame->state->arena); CHK(*submsg); } @@ -254,7 +255,7 @@ static upb_msg *upb_addmsg(upb_decframe *frame, field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP); *subm = frame->layout->submsgs[field->submsg_index]; - submsg = upb_msg_new(*subm, frame->state->arena); + submsg = _upb_msg_new(*subm, frame->state->arena); CHK(submsg); upb_array_add(arr, 1, sizeof(submsg), &submsg, frame->state->arena); @@ -487,6 +488,35 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, UPB_UNREACHABLE(); } +static bool upb_decode_mapfield(upb_decstate *d, upb_decframe *frame, + const upb_msglayout_field *field, int len) { + upb_map *map = *(upb_map**)&frame->msg[field->offset]; + const upb_msglayout *entry = frame->layout->submsgs[field->submsg_index]; + upb_map_entry ent; + + if (!map) { + /* Lazily create map. */ + 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(frame->state->arena, key_size, val_size); + *(upb_map**)&frame->msg[field->offset] = map; + } + + /* Parse map entry. */ + memset(&ent, 0, sizeof(ent)); + CHK(upb_decode_msgfield(d, &ent.k, entry, len)); + + /* Insert into map. */ + _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena); + return true; +} + static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, const upb_msglayout_field *field) { int len; @@ -495,6 +525,8 @@ static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, if (field->label == UPB_LABEL_REPEATED) { return upb_decode_toarray(d, frame, field, len); + } else if (field->label == UPB_LABEL_MAP) { + return upb_decode_mapfield(d, frame, field, len); } else { switch (field->descriptortype) { case UPB_DESCRIPTOR_TYPE_STRING: diff --git a/upb/def.c b/upb/def.c index 98aead6b67..1a83687788 100644 --- a/upb/def.c +++ b/upb/def.c @@ -42,7 +42,8 @@ struct upb_fielddef { const google_protobuf_FieldDescriptorProto *unresolved; } sub; uint32_t number_; - uint32_t index_; + uint16_t index_; + uint16_t layout_index; uint32_t selector_base; /* Used to index into a upb::Handlers table. */ bool is_extension_; bool lazy_; @@ -52,6 +53,7 @@ struct upb_fielddef { }; struct upb_msgdef { + const upb_msglayout *layout; const upb_filedef *file; const char *full_name; uint32_t selector_count; @@ -379,7 +381,7 @@ const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) { } const char *upb_enum_iter_name(upb_enum_iter *iter) { - return upb_strtable_iter_key(iter); + return upb_strtable_iter_key(iter).data; } int32_t upb_enum_iter_number(upb_enum_iter *iter) { @@ -575,6 +577,10 @@ const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) { return f->sub.enumdef; } +const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) { + return &f->msgdef->layout->fields[f->layout_index]; +} + bool upb_fielddef_issubmsg(const upb_fielddef *f) { return upb_fielddef_type(f) == UPB_TYPE_MESSAGE; } @@ -697,6 +703,10 @@ int upb_msgdef_numoneofs(const upb_msgdef *m) { return upb_strtable_count(&m->ntof) - upb_inttable_count(&m->itof); } +const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) { + return m->layout; +} + bool upb_msgdef_mapentry(const upb_msgdef *m) { return m->map_entry; } @@ -819,6 +829,192 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter) { upb_inttable_iter_setdone(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; +} + +static size_t upb_msgval_sizeof(upb_fieldtype_t type) { + switch (type) { + case UPB_TYPE_DOUBLE: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + return 8; + case UPB_TYPE_ENUM: + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_FLOAT: + return 4; + case UPB_TYPE_BOOL: + return 1; + case UPB_TYPE_MESSAGE: + return sizeof(void*); + case UPB_TYPE_BYTES: + case UPB_TYPE_STRING: + return sizeof(upb_strview); + } + UPB_UNREACHABLE(); +} + +static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) { + if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) { + upb_map_entry ent; + UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v)); + return sizeof(ent.k); + } else if (upb_fielddef_isseq(f)) { + return sizeof(void*); + } else { + return upb_msgval_sizeof(upb_fielddef_type(f)); + } +} + +static size_t upb_msglayout_place(upb_msglayout *l, size_t size) { + size_t ret; + + l->size = align_up(l->size, size); + ret = l->size; + l->size += size; + return ret; +} + +/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc. + * It computes a dynamic layout for all of the fields in |m|. */ +static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { + upb_msglayout *l = (upb_msglayout*)m->layout; + upb_msg_field_iter it; + upb_msg_oneof_iter oit; + size_t hasbit; + size_t submsg_count = m->submsg_field_count; + const upb_msglayout **submsgs; + upb_msglayout_field *fields; + upb_alloc *alloc = upb_arena_alloc(symtab->arena); + + memset(l, 0, sizeof(*l)); + + fields = upb_malloc(alloc, upb_msgdef_numfields(m) * sizeof(*fields)); + submsgs = upb_malloc(alloc, submsg_count * sizeof(*submsgs)); + + if ((!fields && upb_msgdef_numfields(m)) || + (!submsgs && submsg_count)) { + /* OOM. */ + return false; + } + + l->field_count = upb_msgdef_numfields(m); + l->fields = fields; + l->submsgs = submsgs; + + /* Allocate data offsets in three stages: + * + * 1. hasbits. + * 2. regular fields. + * 3. oneof fields. + * + * OPT: There is a lot of room for optimization here to minimize the size. + */ + + /* Allocate hasbits and set basic field attributes. */ + submsg_count = 0; + for (upb_msg_field_begin(&it, m), hasbit = 0; + !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + upb_fielddef* f = upb_msg_iter_field(&it); + upb_msglayout_field *field = &fields[upb_fielddef_index(f)]; + + field->number = upb_fielddef_number(f); + field->descriptortype = upb_fielddef_descriptortype(f); + field->label = upb_fielddef_label(f); + + if (upb_fielddef_ismap(f)) { + field->label = UPB_LABEL_MAP; + } + + /* TODO: we probably should sort the fields by field number to match the + * output of upbc, and to improve search speed for the table parser. */ + f->layout_index = f->index_; + + if (upb_fielddef_issubmsg(f)) { + const upb_msgdef *subm = upb_fielddef_msgsubdef(f); + field->submsg_index = submsg_count++; + submsgs[field->submsg_index] = subm->layout; + } + + if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { + field->presence = (hasbit++); + } else { + field->presence = 0; + } + } + + /* Account for space used by hasbits. */ + l->size = div_round_up(hasbit, 8); + + /* Allocate non-oneof fields. */ + for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + const upb_fielddef* f = upb_msg_iter_field(&it); + size_t field_size = upb_msg_fielddefsize(f); + size_t index = upb_fielddef_index(f); + + if (upb_fielddef_containingoneof(f)) { + /* Oneofs are handled separately below. */ + continue; + } + + fields[index].offset = upb_msglayout_place(l, field_size); + } + + /* Allocate oneof fields. Each oneof field consists of a uint32 for the case + * and space for the actual data. */ + for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); + upb_msg_oneof_next(&oit)) { + const upb_oneofdef* o = upb_msg_iter_oneof(&oit); + upb_oneof_iter fit; + + size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ + size_t field_size = 0; + uint32_t case_offset; + uint32_t data_offset; + + /* Calculate field size: the max of all field sizes. */ + for (upb_oneof_begin(&fit, o); + !upb_oneof_done(&fit); + upb_oneof_next(&fit)) { + const upb_fielddef* f = upb_oneof_iter_field(&fit); + field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f)); + } + + /* Align and allocate case offset. */ + case_offset = upb_msglayout_place(l, case_size); + data_offset = upb_msglayout_place(l, field_size); + + for (upb_oneof_begin(&fit, o); + !upb_oneof_done(&fit); + upb_oneof_next(&fit)) { + const upb_fielddef* f = upb_oneof_iter_field(&fit); + fields[upb_fielddef_index(f)].offset = data_offset; + fields[upb_fielddef_index(f)].presence = ~case_offset; + } + } + + /* 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); + + return true; +} + /* Code to build defs from descriptor protos. *********************************/ /* There is a question of how much validation to do here. It will be difficult @@ -831,11 +1027,12 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter) { typedef struct { const upb_symtab *symtab; - upb_filedef *file; /* File we are building. */ - upb_alloc *alloc; /* Allocate defs here. */ - upb_alloc *tmp; /* Alloc for addtab and any other tmp data. */ - upb_strtable *addtab; /* full_name -> packed def ptr for new defs. */ - upb_status *status; /* Record errors here. */ + upb_filedef *file; /* File we are building. */ + upb_alloc *alloc; /* Allocate defs here. */ + upb_alloc *tmp; /* Alloc for addtab and any other tmp data. */ + upb_strtable *addtab; /* full_name -> packed def ptr for new defs */ + const upb_msglayout **layouts; /* NULL if we should build layouts. */ + upb_status *status; /* Record errors here. */ } symtab_addctx; static char* strviewdup(const symtab_addctx *ctx, upb_strview view) { @@ -990,7 +1187,7 @@ static bool parse_default(const symtab_addctx *ctx, const char *str, size_t len, } case UPB_TYPE_INT64: { /* XXX: Need to write our own strtoll, since it's not available in c89. */ - long long val = strtol(str, &end, 0); + int64_t val = strtol(str, &end, 0); CHK(val <= INT64_MAX && val >= INT64_MIN && errno != ERANGE && !*end); f->defaultval.sint = val; break; @@ -1003,7 +1200,7 @@ static bool parse_default(const symtab_addctx *ctx, const char *str, size_t len, } case UPB_TYPE_UINT64: { /* XXX: Need to write our own strtoull, since it's not available in c89. */ - unsigned long long val = strtoul(str, &end, 0); + uint64_t val = strtoul(str, &end, 0); CHK(val <= UINT64_MAX && errno != ERANGE && !*end); f->defaultval.uint = val; break; @@ -1121,6 +1318,21 @@ static bool create_fielddef( field_number); return false; } + + if (ctx->layouts) { + const upb_msglayout_field *fields = m->layout->fields; + int count = m->layout->field_count; + bool found = false; + int i; + for (i = 0; i < count; i++) { + if (fields[i].number == field_number) { + f->layout_index = i; + found = true; + break; + } + } + assert(found); + } } else { /* extension field. */ f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count]; @@ -1257,7 +1469,7 @@ static bool create_enumdef( return true; } -static bool create_msgdef(const symtab_addctx *ctx, const char *prefix, +static bool create_msgdef(symtab_addctx *ctx, const char *prefix, const google_protobuf_DescriptorProto *msg_proto) { upb_msgdef *m; const google_protobuf_MessageOptions *options; @@ -1287,6 +1499,14 @@ static bool create_msgdef(const symtab_addctx *ctx, const char *prefix, m->map_entry = google_protobuf_MessageOptions_map_entry(options); } + if (ctx->layouts) { + m->layout = *ctx->layouts; + ctx->layouts++; + } else { + /* Allocate now (to allow cross-linking), populate later. */ + m->layout = upb_malloc(ctx->alloc, sizeof(*m->layout)); + } + oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n); m->oneof_count = 0; m->oneofs = upb_malloc(ctx->alloc, sizeof(*m->oneofs) * n); @@ -1433,7 +1653,7 @@ static bool resolve_fielddef(const symtab_addctx *ctx, const char *prefix, } static bool build_filedef( - const symtab_addctx *ctx, upb_filedef *file, + symtab_addctx *ctx, upb_filedef *file, const google_protobuf_FileDescriptorProto *file_proto) { upb_alloc *alloc = ctx->alloc; const google_protobuf_FileOptions *file_options_proto; @@ -1547,7 +1767,7 @@ static bool build_filedef( CHK(create_fielddef(ctx, file->package, NULL, exts[i])); } - /* Now that all names are in the table, resolve references. */ + /* Now that all names are in the table, build layouts and resolve refs. */ for (i = 0; i < file->ext_count; i++) { CHK(resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i])); } @@ -1560,6 +1780,13 @@ static bool build_filedef( } } + if (!ctx->layouts) { + for (i = 0; i < file->msg_count; i++) { + const upb_msgdef *m = &file->msgs[i]; + make_layout(ctx->symtab, m); + } + } + return true; } @@ -1574,10 +1801,9 @@ static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx, upb_strtable_begin(&iter, ctx->addtab); for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - const char *key = upb_strtable_iter_key(&iter); - size_t keylen = upb_strtable_iter_keylength(&iter); + upb_strview key = upb_strtable_iter_key(&iter); upb_value value = upb_strtable_iter_value(&iter); - CHK_OOM(upb_strtable_insert3(&s->syms, key, keylen, value, alloc)); + CHK_OOM(upb_strtable_insert3(&s->syms, key.data, key.size, value, alloc)); } return true; @@ -1679,9 +1905,13 @@ const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) : NULL; } -const upb_filedef *upb_symtab_addfile( +int upb_symtab_filecount(const upb_symtab *s) { + return upb_strtable_count(&s->files); +} + +static const upb_filedef *_upb_symtab_addfile( upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, - upb_status *status) { + const upb_msglayout **layouts, upb_status *status) { upb_arena *tmparena = upb_arena_new(); upb_strtable addtab; upb_alloc *alloc = upb_arena_alloc(s->arena); @@ -1694,6 +1924,7 @@ const upb_filedef *upb_symtab_addfile( ctx.alloc = alloc; ctx.tmp = upb_arena_alloc(tmparena); ctx.addtab = &addtab; + ctx.layouts = layouts; ctx.status = status; ok = file && @@ -1705,6 +1936,12 @@ const upb_filedef *upb_symtab_addfile( return ok ? file : NULL; } +const upb_filedef *upb_symtab_addfile( + upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, + upb_status *status) { + return _upb_symtab_addfile(s, file_proto, NULL, status); +} + /* Include here since we want most of this file to be stdio-free. */ #include @@ -1740,7 +1977,7 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) { goto err; } - if (!upb_symtab_addfile(s, file, &status)) goto err; + if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err; upb_arena_free(arena); return true; diff --git a/upb/def.h b/upb/def.h index 9be285794e..0ff26eb09e 100644 --- a/upb/def.h +++ b/upb/def.h @@ -123,6 +123,7 @@ bool upb_fielddef_hassubdef(const upb_fielddef *f); bool upb_fielddef_haspresence(const upb_fielddef *f); const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f); const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f); +const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f); /* Internal only. */ uint32_t upb_fielddef_selectorbase(const upb_fielddef *f); @@ -425,6 +426,7 @@ 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); UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m, const char *name) { @@ -851,9 +853,10 @@ const upb_filedef *upb_symtab_addfile( /* For generated code only: loads a generated descriptor. */ typedef struct upb_def_init { - struct upb_def_init **deps; + struct upb_def_init **deps; /* Dependencies of this file. */ + const upb_msglayout **layouts; /* Pre-order layouts of all messages. */ const char *filename; - upb_strview descriptor; + upb_strview descriptor; /* Serialized descriptor. */ } upb_def_init; bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init); diff --git a/upb/encode.c b/upb/encode.c index 43d24cdbfc..d9adbff596 100644 --- a/upb/encode.c +++ b/upb/encode.c @@ -70,6 +70,7 @@ static bool upb_encode_reserve(upb_encstate *e, size_t bytes) { /* Writes the given bytes to the buffer, handling reserve/advance. */ static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) { + if (len == 0) return true; CHK(upb_encode_reserve(e, len)); memcpy(e->ptr, data, len); return true; @@ -130,12 +131,89 @@ static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) { static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr, size_t size) { size_t bytes = arr->len * size; - return upb_put_bytes(e, arr->data, bytes) && upb_put_varint(e, bytes); + const void* data = _upb_array_constptr(arr); + return upb_put_bytes(e, data, bytes) && upb_put_varint(e, bytes); } bool upb_encode_message(upb_encstate *e, const char *msg, const upb_msglayout *m, size_t *size); +static bool upb_encode_scalarfield(upb_encstate *e, const void *_field_mem, + const upb_msglayout *m, + const upb_msglayout_field *f, + bool skip_zero_value) { + const char *field_mem = _field_mem; +#define CASE(ctype, type, wire_type, encodeval) do { \ + ctype val = *(ctype*)field_mem; \ + if (skip_zero_value && val == 0) { \ + return true; \ + } \ + return upb_put_ ## type(e, encodeval) && \ + upb_put_tag(e, f->number, wire_type); \ +} while(0) + + switch (f->descriptortype) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + CASE(double, double, UPB_WIRE_TYPE_64BIT, val); + case UPB_DESCRIPTOR_TYPE_FLOAT: + CASE(float, float, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_UINT32: + CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val); + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val); + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_BOOL: + CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_SINT32: + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val)); + case UPB_DESCRIPTOR_TYPE_SINT64: + CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val)); + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + upb_strview view = *(upb_strview*)field_mem; + if (skip_zero_value && view.size == 0) { + return true; + } + return upb_put_bytes(e, view.data, view.size) && + upb_put_varint(e, view.size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + size_t size; + void *submsg = *(void **)field_mem; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (submsg == NULL) { + return true; + } + return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) && + upb_encode_message(e, submsg, subm, &size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); + } + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + size_t size; + void *submsg = *(void **)field_mem; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (submsg == NULL) { + return true; + } + return upb_encode_message(e, submsg, subm, &size) && + upb_put_varint(e, size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } + } +#undef CASE + UPB_UNREACHABLE(); +} + static bool upb_encode_array(upb_encstate *e, const char *field_mem, const upb_msglayout *m, const upb_msglayout_field *f) { @@ -146,8 +224,8 @@ static bool upb_encode_array(upb_encstate *e, const char *field_mem, } #define VARINT_CASE(ctype, encode) { \ - ctype *start = arr->data; \ - ctype *ptr = start + arr->len; \ + const ctype *start = _upb_array_constptr(arr); \ + const ctype *ptr = start + arr->len; \ size_t pre_len = e->limit - e->ptr; \ do { \ ptr--; \ @@ -189,8 +267,8 @@ do { ; } while(0) VARINT_CASE(int64_t, upb_zzencode_64(*ptr)); case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { - upb_strview *start = arr->data; - upb_strview *ptr = start + arr->len; + const upb_strview *start = _upb_array_constptr(arr); + const upb_strview *ptr = start + arr->len; do { ptr--; CHK(upb_put_bytes(e, ptr->data, ptr->size) && @@ -200,8 +278,8 @@ do { ; } while(0) return true; } case UPB_DESCRIPTOR_TYPE_GROUP: { - void **start = arr->data; - void **ptr = start + arr->len; + const void *const*start = _upb_array_constptr(arr); + const void *const*ptr = start + arr->len; const upb_msglayout *subm = m->submsgs[f->submsg_index]; do { size_t size; @@ -213,8 +291,8 @@ do { ; } while(0) return true; } case UPB_DESCRIPTOR_TYPE_MESSAGE: { - void **start = arr->data; - void **ptr = start + arr->len; + const void *const*start = _upb_array_constptr(arr); + const void *const*ptr = start + arr->len; const upb_msglayout *subm = m->submsgs[f->submsg_index]; do { size_t size; @@ -234,81 +312,40 @@ do { ; } while(0) return true; } -static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, - const upb_msglayout *m, - const upb_msglayout_field *f, - bool skip_zero_value) { -#define CASE(ctype, type, wire_type, encodeval) do { \ - ctype val = *(ctype*)field_mem; \ - if (skip_zero_value && val == 0) { \ - return true; \ - } \ - return upb_put_ ## type(e, encodeval) && \ - upb_put_tag(e, f->number, wire_type); \ -} while(0) +static bool upb_encode_map(upb_encstate *e, const char *field_mem, + const upb_msglayout *m, + const upb_msglayout_field *f) { + const upb_map *map = *(const upb_map**)field_mem; + const upb_msglayout *entry = m->submsgs[f->submsg_index]; + const upb_msglayout_field *key_field = &entry->fields[0]; + const upb_msglayout_field *val_field = &entry->fields[1]; + upb_strtable_iter i; + if (map == NULL) { + return true; + } - switch (f->descriptortype) { - case UPB_DESCRIPTOR_TYPE_DOUBLE: - CASE(double, double, UPB_WIRE_TYPE_64BIT, val); - case UPB_DESCRIPTOR_TYPE_FLOAT: - CASE(float, float, UPB_WIRE_TYPE_32BIT, val); - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_UINT64: - CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val); - case UPB_DESCRIPTOR_TYPE_UINT32: - CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val); - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_ENUM: - CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val); - case UPB_DESCRIPTOR_TYPE_SFIXED64: - case UPB_DESCRIPTOR_TYPE_FIXED64: - CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val); - case UPB_DESCRIPTOR_TYPE_FIXED32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val); - case UPB_DESCRIPTOR_TYPE_BOOL: - CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val); - case UPB_DESCRIPTOR_TYPE_SINT32: - CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val)); - case UPB_DESCRIPTOR_TYPE_SINT64: - CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val)); - case UPB_DESCRIPTOR_TYPE_STRING: - case UPB_DESCRIPTOR_TYPE_BYTES: { - upb_strview view = *(upb_strview*)field_mem; - if (skip_zero_value && view.size == 0) { - return true; - } - return upb_put_bytes(e, view.data, view.size) && - upb_put_varint(e, view.size) && - upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); - } - case UPB_DESCRIPTOR_TYPE_GROUP: { - size_t size; - void *submsg = *(void **)field_mem; - const upb_msglayout *subm = m->submsgs[f->submsg_index]; - if (submsg == NULL) { - return true; - } - return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) && - upb_encode_message(e, submsg, subm, &size) && - upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); - } - case UPB_DESCRIPTOR_TYPE_MESSAGE: { - size_t size; - void *submsg = *(void **)field_mem; - const upb_msglayout *subm = m->submsgs[f->submsg_index]; - if (submsg == NULL) { - return true; - } - return upb_encode_message(e, submsg, subm, &size) && - upb_put_varint(e, size) && - upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); - } + upb_strtable_begin(&i, &map->table); + for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + size_t pre_len = e->limit - e->ptr; + size_t size; + upb_strview key = upb_strtable_iter_key(&i); + const upb_value val = upb_strtable_iter_value(&i); + const void *keyp = + map->key_size == UPB_MAPTYPE_STRING ? (void *)&key : key.data; + const void *valp = + map->val_size == UPB_MAPTYPE_STRING ? upb_value_getptr(val) : &val; + + CHK(upb_encode_scalarfield(e, valp, entry, val_field, false)); + CHK(upb_encode_scalarfield(e, keyp, entry, key_field, false)); + size = (e->limit - e->ptr) - pre_len; + CHK(upb_put_varint(e, size)); + CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); } -#undef CASE - UPB_UNREACHABLE(); + + return true; } + bool upb_encode_message(upb_encstate *e, const char *msg, const upb_msglayout *m, size_t *size) { int i; @@ -316,11 +353,19 @@ bool upb_encode_message(upb_encstate *e, const char *msg, const char *unknown; size_t unknown_size; + unknown = upb_msg_getunknown(msg, &unknown_size); + + if (unknown) { + upb_put_bytes(e, unknown, unknown_size); + } + for (i = m->field_count - 1; i >= 0; i--) { const upb_msglayout_field *f = &m->fields[i]; if (f->label == UPB_LABEL_REPEATED) { CHK(upb_encode_array(e, msg + f->offset, m, f)); + } else if (f->label == UPB_LABEL_MAP) { + CHK(upb_encode_map(e, msg + f->offset, m, f)); } else { bool skip_empty = false; if (f->presence == 0) { @@ -341,12 +386,6 @@ bool upb_encode_message(upb_encstate *e, const char *msg, } } - unknown = upb_msg_getunknown(msg, &unknown_size); - - if (unknown) { - upb_put_bytes(e, unknown, unknown_size); - } - *size = (e->limit - e->ptr) - pre_len; return true; } diff --git a/upb/generated_util.h b/upb/generated_util.h deleted file mode 100644 index 234bcdad3c..0000000000 --- a/upb/generated_util.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -** Functions for use by generated code. These are not public and users must -** not call them directly. -*/ - -#ifndef UPB_GENERATED_UTIL_H_ -#define UPB_GENERATED_UTIL_H_ - -#include -#include "upb/msg.h" - -#include "upb/port_def.inc" - -#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs) - -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*); - if (arr) { - if (size) *size = arr->len; - return arr->data; - } else { - if (size) *size = 0; - return NULL; - } -} - -UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs, - size_t *size) { - upb_array *arr = *PTR_AT(msg, ofs, upb_array*); - if (arr) { - if (size) *size = arr->len; - return arr->data; - } else { - if (size) *size = 0; - return NULL; - } -} - -/* TODO(haberman): this is a mess. It will improve when upb_array no longer - * carries reflective state (type, elem_size). */ -UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size, - size_t elem_size, - upb_fieldtype_t type, - upb_arena *arena) { - upb_array *arr = *PTR_AT(msg, ofs, upb_array*); - - if (!arr) { - arr = upb_array_new(arena); - if (!arr) return NULL; - *PTR_AT(msg, ofs, upb_array*) = arr; - } - - if (size > arr->size) { - size_t new_size = UPB_MAX(arr->size, 4); - size_t old_bytes = arr->size * elem_size; - size_t new_bytes; - while (new_size < size) new_size *= 2; - new_bytes = new_size * elem_size; - arr->data = upb_arena_realloc(arena, arr->data, old_bytes, new_bytes); - if (!arr->data) { - return NULL; - } - arr->size = new_size; - } - - arr->len = size; - return arr->data; -} - -UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs, - size_t elem_size, - upb_fieldtype_t type, - const void *value, - upb_arena *arena) { - upb_array *arr = *PTR_AT(msg, ofs, upb_array*); - size_t i = arr ? arr->len : 0; - void *data = - _upb_array_resize_accessor(msg, ofs, i + 1, elem_size, type, arena); - if (!data) return false; - memcpy(PTR_AT(data, i * elem_size, char), value, elem_size); - return true; -} - -UPB_INLINE bool _upb_has_field(const void *msg, size_t idx) { - return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0; -} - -UPB_INLINE bool _upb_sethas(const void *msg, size_t idx) { - return (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8)); -} - -UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) { - return (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8))); -} - -UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t num) { - return *PTR_AT(msg, case_ofs, int32_t) == num; -} - -#undef PTR_AT - -#include "upb/port_undef.inc" - -#endif /* UPB_GENERATED_UTIL_H_ */ diff --git a/upb/json/printer.c b/upb/json/printer.c index 38f817d4d4..a3cb9bdb01 100644 --- a/upb/json/printer.c +++ b/upb/json/printer.c @@ -6,6 +6,7 @@ #include "upb/json/printer.h" #include +#include #include #include #include @@ -208,28 +209,26 @@ static size_t fmt_bool(bool val, char* buf, size_t length) { return n; } -static size_t fmt_int64_as_number(long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%lld", val); +static size_t fmt_int64_as_number(int64_t val, char* buf, size_t length) { + size_t n = _upb_snprintf(buf, length, "%" PRId64, val); CHKLENGTH(n > 0 && n < length); return n; } -static size_t fmt_uint64_as_number( - unsigned long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%llu", val); +static size_t fmt_uint64_as_number(uint64_t val, char* buf, size_t length) { + size_t n = _upb_snprintf(buf, length, "%" PRIu64, val); CHKLENGTH(n > 0 && n < length); return n; } -static size_t fmt_int64_as_string(long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "\"%lld\"", val); +static size_t fmt_int64_as_string(int64_t val, char* buf, size_t length) { + size_t n = _upb_snprintf(buf, length, "\"%" PRId64 "\"", val); CHKLENGTH(n > 0 && n < length); return n; } -static size_t fmt_uint64_as_string( - unsigned long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "\"%llu\"", val); +static size_t fmt_uint64_as_string(uint64_t val, char* buf, size_t length) { + size_t n = _upb_snprintf(buf, length, "\"%" PRIu64 "\"", val); CHKLENGTH(n > 0 && n < length); return n; } diff --git a/upb/legacy_msg_reflection.c b/upb/legacy_msg_reflection.c deleted file mode 100644 index 031aa4e9cc..0000000000 --- a/upb/legacy_msg_reflection.c +++ /dev/null @@ -1,399 +0,0 @@ - -#include "upb/legacy_msg_reflection.h" - -#include -#include "upb/table.int.h" -#include "upb/msg.h" - -#include "upb/port_def.inc" - -bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) { - return type == UPB_TYPE_BOOL || type == UPB_TYPE_INT32 || - type == UPB_TYPE_UINT32 || type == UPB_TYPE_INT64 || - type == UPB_TYPE_UINT64 || type == UPB_TYPE_STRING; -} - -#define PTR_AT(msg, ofs, type) (type*)((char*)msg + ofs) -#define VOIDPTR_AT(msg, ofs) PTR_AT(msg, ofs, void) -#define ENCODE_MAX_NESTING 64 -#define CHECK_TRUE(x) if (!(x)) { return false; } - -/** upb_msgval ****************************************************************/ - -/* These functions will generate real memcpy() calls on ARM sadly, because - * the compiler assumes they might not be aligned. */ - -static upb_msgval upb_msgval_read(const void *p, size_t ofs, - uint8_t size) { - upb_msgval val; - p = (char*)p + ofs; - memcpy(&val, p, size); - return val; -} - -static void upb_msgval_write(void *p, size_t ofs, upb_msgval val, - uint8_t size) { - p = (char*)p + ofs; - memcpy(p, &val, size); -} - -static size_t upb_msgval_sizeof(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_DOUBLE: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - return 8; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_FLOAT: - return 4; - case UPB_TYPE_BOOL: - return 1; - case UPB_TYPE_MESSAGE: - return sizeof(void*); - case UPB_TYPE_BYTES: - case UPB_TYPE_STRING: - return sizeof(upb_strview); - } - UPB_UNREACHABLE(); -} - -static uint8_t upb_msg_fieldsize(const upb_msglayout_field *field) { - if (field->label == UPB_LABEL_REPEATED) { - return sizeof(void*); - } else { - return upb_msgval_sizeof(upb_desctype_to_fieldtype[field->descriptortype]); - } -} - -/* TODO(haberman): this is broken right now because upb_msgval can contain - * a char* / size_t pair, which is too big for a upb_value. To fix this - * we'll probably need to dynamically allocate a upb_msgval and store a - * pointer to that in the tables for extensions/maps. */ -static upb_value upb_toval(upb_msgval val) { - upb_value ret; - UPB_UNUSED(val); - memset(&ret, 0, sizeof(upb_value)); /* XXX */ - return ret; -} - -static upb_msgval upb_msgval_fromval(upb_value val) { - upb_msgval ret; - UPB_UNUSED(val); - memset(&ret, 0, sizeof(upb_msgval)); /* XXX */ - return ret; -} - -static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_FLOAT: return UPB_CTYPE_FLOAT; - case UPB_TYPE_DOUBLE: return UPB_CTYPE_DOUBLE; - case UPB_TYPE_BOOL: return UPB_CTYPE_BOOL; - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - case UPB_TYPE_STRING: return UPB_CTYPE_CONSTPTR; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: return UPB_CTYPE_INT32; - case UPB_TYPE_UINT32: return UPB_CTYPE_UINT32; - case UPB_TYPE_INT64: return UPB_CTYPE_INT64; - case UPB_TYPE_UINT64: return UPB_CTYPE_UINT64; - default: UPB_ASSERT(false); return 0; - } -} - - -/** upb_msg *******************************************************************/ - -/* If we always read/write as a consistent type to each address, this shouldn't - * violate aliasing. - */ -#define DEREF(msg, ofs, type) *PTR_AT(msg, ofs, type) - -static const upb_msglayout_field *upb_msg_checkfield(int field_index, - const upb_msglayout *l) { - UPB_ASSERT(field_index >= 0 && field_index < l->field_count); - return &l->fields[field_index]; -} - -static bool upb_msg_inoneof(const upb_msglayout_field *field) { - return field->presence < 0; -} - -static uint32_t *upb_msg_oneofcase(const upb_msg *msg, int field_index, - const upb_msglayout *l) { - const upb_msglayout_field *field = upb_msg_checkfield(field_index, l); - UPB_ASSERT(upb_msg_inoneof(field)); - return PTR_AT(msg, ~field->presence, uint32_t); -} - -bool upb_msg_has(const upb_msg *msg, - int field_index, - const upb_msglayout *l) { - const upb_msglayout_field *field = upb_msg_checkfield(field_index, l); - - UPB_ASSERT(field->presence); - - if (upb_msg_inoneof(field)) { - /* Oneofs are set when the oneof number is set to this field. */ - return *upb_msg_oneofcase(msg, field_index, l) == field->number; - } else { - /* Other fields are set when their hasbit is set. */ - uint32_t hasbit = field->presence; - return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8)); - } -} - -upb_msgval upb_msg_get(const upb_msg *msg, int field_index, - const upb_msglayout *l) { - const upb_msglayout_field *field = upb_msg_checkfield(field_index, l); - int size = upb_msg_fieldsize(field); - return upb_msgval_read(msg, field->offset, size); -} - -void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val, - const upb_msglayout *l) { - const upb_msglayout_field *field = upb_msg_checkfield(field_index, l); - int size = upb_msg_fieldsize(field); - upb_msgval_write(msg, field->offset, val, size); -} - - -/** upb_array *****************************************************************/ - -#define DEREF_ARR(arr, i, type) ((type*)arr->data)[i] - -size_t upb_array_size(const upb_array *arr) { - return arr->len; -} - -upb_msgval upb_array_get(const upb_array *arr, upb_fieldtype_t type, size_t i) { - size_t element_size = upb_msgval_sizeof(type); - UPB_ASSERT(i < arr->len); - return upb_msgval_read(arr->data, i * element_size, element_size); -} - -bool upb_array_set(upb_array *arr, upb_fieldtype_t type, size_t i, - upb_msgval val, upb_arena *arena) { - size_t element_size = upb_msgval_sizeof(type); - UPB_ASSERT(i <= arr->len); - - if (i == arr->len) { - /* Extending the array. */ - - if (i == arr->size) { - /* Need to reallocate. */ - size_t new_size = UPB_MAX(arr->size * 2, 8); - size_t new_bytes = new_size * element_size; - size_t old_bytes = arr->size * element_size; - upb_alloc *alloc = upb_arena_alloc(arena); - upb_msgval *new_data = - upb_realloc(alloc, arr->data, old_bytes, new_bytes); - - if (!new_data) { - return false; - } - - arr->data = new_data; - arr->size = new_size; - } - - arr->len = i + 1; - } - - upb_msgval_write(arr->data, i * element_size, val, element_size); - return true; -} - -/** upb_map *******************************************************************/ - -struct upb_map { - upb_fieldtype_t key_type; - upb_fieldtype_t val_type; - /* We may want to optimize this to use inttable where possible, for greater - * efficiency and lower memory footprint. */ - upb_strtable strtab; - upb_arena *arena; -}; - -static void upb_map_tokey(upb_fieldtype_t type, upb_msgval *key, - const char **out_key, size_t *out_len) { - switch (type) { - case UPB_TYPE_STRING: - /* Point to string data of the input key. */ - *out_key = key->str.data; - *out_len = key->str.size; - return; - case UPB_TYPE_BOOL: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - /* Point to the key itself. XXX: big-endian. */ - *out_key = (const char*)key; - *out_len = upb_msgval_sizeof(type); - return; - case UPB_TYPE_BYTES: - case UPB_TYPE_DOUBLE: - case UPB_TYPE_ENUM: - case UPB_TYPE_FLOAT: - case UPB_TYPE_MESSAGE: - break; /* Cannot be a map key. */ - } - UPB_UNREACHABLE(); -} - -static upb_msgval upb_map_fromkey(upb_fieldtype_t type, const char *key, - size_t len) { - switch (type) { - case UPB_TYPE_STRING: - return upb_msgval_makestr(key, len); - case UPB_TYPE_BOOL: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - return upb_msgval_read(key, 0, upb_msgval_sizeof(type)); - case UPB_TYPE_BYTES: - case UPB_TYPE_DOUBLE: - case UPB_TYPE_ENUM: - case UPB_TYPE_FLOAT: - case UPB_TYPE_MESSAGE: - break; /* Cannot be a map key. */ - } - UPB_UNREACHABLE(); -} - -upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_arena *a) { - upb_ctype_t vtabtype = upb_fieldtotabtype(vtype); - upb_alloc *alloc = upb_arena_alloc(a); - upb_map *map = upb_malloc(alloc, sizeof(upb_map)); - - if (!map) { - return NULL; - } - - UPB_ASSERT(upb_fieldtype_mapkeyok(ktype)); - map->key_type = ktype; - map->val_type = vtype; - map->arena = a; - - if (!upb_strtable_init2(&map->strtab, vtabtype, alloc)) { - return NULL; - } - - return map; -} - -size_t upb_map_size(const upb_map *map) { - return upb_strtable_count(&map->strtab); -} - -upb_fieldtype_t upb_map_keytype(const upb_map *map) { - return map->key_type; -} - -upb_fieldtype_t upb_map_valuetype(const upb_map *map) { - return map->val_type; -} - -bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) { - upb_value tabval; - const char *key_str; - size_t key_len; - bool ret; - - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - ret = upb_strtable_lookup2(&map->strtab, key_str, key_len, &tabval); - if (ret) { - memcpy(val, &tabval, sizeof(tabval)); - } - - return ret; -} - -bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, - upb_msgval *removed) { - const char *key_str; - size_t key_len; - upb_value tabval = upb_toval(val); - upb_value removedtabval; - upb_alloc *a = upb_arena_alloc(map->arena); - - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - - /* TODO(haberman): add overwrite operation to minimize number of lookups. */ - if (upb_strtable_lookup2(&map->strtab, key_str, key_len, NULL)) { - upb_strtable_remove3(&map->strtab, key_str, key_len, &removedtabval, a); - memcpy(&removed, &removedtabval, sizeof(removed)); - } - - return upb_strtable_insert3(&map->strtab, key_str, key_len, tabval, a); -} - -bool upb_map_del(upb_map *map, upb_msgval key) { - const char *key_str; - size_t key_len; - upb_alloc *a = upb_arena_alloc(map->arena); - - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - return upb_strtable_remove3(&map->strtab, key_str, key_len, NULL, a); -} - - -/** upb_mapiter ***************************************************************/ - -struct upb_mapiter { - upb_strtable_iter iter; - upb_fieldtype_t key_type; -}; - -size_t upb_mapiter_sizeof(void) { - return sizeof(upb_mapiter); -} - -void upb_mapiter_begin(upb_mapiter *i, const upb_map *map) { - upb_strtable_begin(&i->iter, &map->strtab); - i->key_type = map->key_type; -} - -upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a) { - upb_mapiter *ret = upb_malloc(a, upb_mapiter_sizeof()); - - if (!ret) { - return NULL; - } - - upb_mapiter_begin(ret, t); - return ret; -} - -void upb_mapiter_free(upb_mapiter *i, upb_alloc *a) { - upb_free(a, i); -} - -void upb_mapiter_next(upb_mapiter *i) { - upb_strtable_next(&i->iter); -} - -bool upb_mapiter_done(const upb_mapiter *i) { - return upb_strtable_done(&i->iter); -} - -upb_msgval upb_mapiter_key(const upb_mapiter *i) { - return upb_map_fromkey(i->key_type, upb_strtable_iter_key(&i->iter), - upb_strtable_iter_keylength(&i->iter)); -} - -upb_msgval upb_mapiter_value(const upb_mapiter *i) { - return upb_msgval_fromval(upb_strtable_iter_value(&i->iter)); -} - -void upb_mapiter_setdone(upb_mapiter *i) { - upb_strtable_iter_setdone(&i->iter); -} - -bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2) { - return upb_strtable_iter_isequal(&i1->iter, &i2->iter); -} diff --git a/upb/legacy_msg_reflection.h b/upb/legacy_msg_reflection.h deleted file mode 100644 index c54bfb947a..0000000000 --- a/upb/legacy_msg_reflection.h +++ /dev/null @@ -1,191 +0,0 @@ - -#ifndef UPB_LEGACY_MSG_REFLECTION_H_ -#define UPB_LEGACY_MSG_REFLECTION_H_ - -#include "upb/upb.h" -#include "upb/msg.h" - -#include "upb/port_def.inc" - -struct upb_map; -typedef struct upb_map upb_map; - -struct upb_mapiter; -typedef struct upb_mapiter upb_mapiter; - -/** upb_msgval ****************************************************************/ - -/* A union representing all possible protobuf values. Used for generic get/set - * operations. */ - -typedef union { - bool b; - float flt; - double dbl; - int32_t i32; - int64_t i64; - uint32_t u32; - uint64_t u64; - const upb_map* map; - const upb_msg* msg; - const upb_array* arr; - const void* ptr; - upb_strview str; -} upb_msgval; - -#define ACCESSORS(name, membername, ctype) \ - UPB_INLINE ctype upb_msgval_get ## name(upb_msgval v) { \ - return v.membername; \ - } \ - UPB_INLINE void upb_msgval_set ## name(upb_msgval *v, ctype cval) { \ - v->membername = cval; \ - } \ - UPB_INLINE upb_msgval upb_msgval_ ## name(ctype v) { \ - upb_msgval ret; \ - ret.membername = v; \ - return ret; \ - } - -ACCESSORS(bool, b, bool) -ACCESSORS(float, flt, float) -ACCESSORS(double, dbl, double) -ACCESSORS(int32, i32, int32_t) -ACCESSORS(int64, i64, int64_t) -ACCESSORS(uint32, u32, uint32_t) -ACCESSORS(uint64, u64, uint64_t) -ACCESSORS(map, map, const upb_map*) -ACCESSORS(msg, msg, const upb_msg*) -ACCESSORS(ptr, ptr, const void*) -ACCESSORS(arr, arr, const upb_array*) -ACCESSORS(str, str, upb_strview) - -#undef ACCESSORS - -UPB_INLINE upb_msgval upb_msgval_makestr(const char *data, size_t size) { - return upb_msgval_str(upb_strview_make(data, size)); -} - -/** upb_msg *******************************************************************/ - -/* A upb_msg represents a protobuf message. It always corresponds to a specific - * upb_msglayout, which describes how it is laid out in memory. */ - -/* Read-only message API. Can be safely called by anyone. */ - -/* Returns the value associated with this field: - * - for scalar fields (including strings), the value directly. - * - return upb_msg*, or upb_map* for msg/map. - * If the field is unset for these field types, returns NULL. - * - * TODO(haberman): should we let users store cached array/map/msg - * pointers here for fields that are unset? Could be useful for the - * strongly-owned submessage model (ie. generated C API that doesn't use - * arenas). - */ -upb_msgval upb_msg_get(const upb_msg *msg, - int field_index, - const upb_msglayout *l); - -/* May only be called for fields where upb_fielddef_haspresence(f) == true. */ -bool upb_msg_has(const upb_msg *msg, - int field_index, - const upb_msglayout *l); - -/* Mutable message API. May only be called by the owner of the message who - * knows its ownership scheme and how to keep it consistent. */ - -/* Sets the given field to the given value. Does not perform any memory - * management: if you overwrite a pointer to a msg/array/map/string without - * cleaning it up (or using an arena) it will leak. - */ -void upb_msg_set(upb_msg *msg, - int field_index, - upb_msgval val, - const upb_msglayout *l); - -/* For a primitive field, set it back to its default. For repeated, string, and - * submessage fields set it back to NULL. This could involve releasing some - * internal memory (for example, from an extension dictionary), but it is not - * recursive in any way and will not recover any memory that may be used by - * arrays/maps/strings/msgs that this field may have pointed to. - */ -bool upb_msg_clearfield(upb_msg *msg, - int field_index, - const upb_msglayout *l); - -/* TODO(haberman): copyfrom()/mergefrom()? */ - -/** upb_array *****************************************************************/ - -/* A upb_array stores data for a repeated field. The memory management - * semantics are the same as upb_msg. A upb_array allocates dynamic - * memory internally for the array elements. */ - -upb_fieldtype_t upb_array_type(const upb_array *arr); - -/* Read-only interface. Safe for anyone to call. */ - -size_t upb_array_size(const upb_array *arr); -upb_msgval upb_array_get(const upb_array *arr, upb_fieldtype_t type, size_t i); - -/* Write interface. May only be called by the message's owner who can enforce - * its memory management invariants. */ - -bool upb_array_set(upb_array *arr, upb_fieldtype_t type, size_t i, - upb_msgval val, upb_arena *arena); - -/** upb_map *******************************************************************/ - -/* A upb_map stores data for a map field. The memory management semantics are - * the same as upb_msg, with one notable exception. upb_map will internally - * store a copy of all string keys, but *not* any string values or submessages. - * So you must ensure that any string or message values outlive the map, and you - * must delete them manually when they are no longer required. */ - -upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_arena *a); - -/* Read-only interface. Safe for anyone to call. */ - -size_t upb_map_size(const upb_map *map); -upb_fieldtype_t upb_map_keytype(const upb_map *map); -upb_fieldtype_t upb_map_valuetype(const upb_map *map); -bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val); - -/* Write interface. May only be called by the message's owner who can enforce - * its memory management invariants. */ - -/* Sets or overwrites an entry in the map. Return value indicates whether - * the operation succeeded or failed with OOM, and also whether an existing - * key was replaced or not. */ -bool upb_map_set(upb_map *map, - upb_msgval key, upb_msgval val, - upb_msgval *valremoved); - -/* Deletes an entry in the map. Returns true if the key was present. */ -bool upb_map_del(upb_map *map, upb_msgval key); - -/** upb_mapiter ***************************************************************/ - -/* For iterating over a map. Map iterators are invalidated by mutations to the - * map, but an invalidated iterator will never return junk or crash the process. - * An invalidated iterator may return entries that were already returned though, - * and if you keep invalidating the iterator during iteration, the program may - * enter an infinite loop. */ - -size_t upb_mapiter_sizeof(void); - -void upb_mapiter_begin(upb_mapiter *i, const upb_map *t); -upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a); -void upb_mapiter_free(upb_mapiter *i, upb_alloc *a); -void upb_mapiter_next(upb_mapiter *i); -bool upb_mapiter_done(const upb_mapiter *i); - -upb_msgval upb_mapiter_key(const upb_mapiter *i); -upb_msgval upb_mapiter_value(const upb_mapiter *i); -void upb_mapiter_setdone(upb_mapiter *i); -bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2); - -#include "upb/port_undef.inc" - -#endif /* UPB_LEGACY_MSG_REFLECTION_H_ */ diff --git a/upb/msg.c b/upb/msg.c index a77da5665c..db4de0983a 100644 --- a/upb/msg.c +++ b/upb/msg.c @@ -7,22 +7,27 @@ #define VOIDPTR_AT(msg, ofs) (void*)((char*)msg + (int)ofs) -/* Internal members of a upb_msg. We can change this without breaking binary - * compatibility. We put these before the user's data. The user's upb_msg* - * points after the upb_msg_internal. */ - -/* Used when a message is not extendable. */ -typedef struct { - char *unknown; - size_t unknown_len; - size_t unknown_size; -} upb_msg_internal; - -/* Used when a message is extendable. */ -typedef struct { - upb_inttable *extdict; - upb_msg_internal base; -} upb_msg_internal_withext; +/** upb_msg *******************************************************************/ + +static char _upb_fieldtype_to_sizelg2[12] = { + 0, + 0, /* UPB_TYPE_BOOL */ + 2, /* UPB_TYPE_FLOAT */ + 2, /* UPB_TYPE_INT32 */ + 2, /* UPB_TYPE_UINT32 */ + 2, /* UPB_TYPE_ENUM */ + UPB_SIZE(2, 3), /* UPB_TYPE_MESSAGE */ + 3, /* UPB_TYPE_DOUBLE */ + 3, /* UPB_TYPE_INT64 */ + 3, /* UPB_TYPE_UINT64 */ + UPB_SIZE(3, 4), /* UPB_TYPE_STRING */ + UPB_SIZE(3, 4), /* UPB_TYPE_BYTES */ +}; + +static uintptr_t tag_arrptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + return (uintptr_t)ptr | elem_size_lg2; +} static int upb_msg_internalsize(const upb_msglayout *l) { return sizeof(upb_msg_internal) - l->extendable * sizeof(void *); @@ -46,7 +51,7 @@ static upb_msg_internal_withext *upb_msg_getinternalwithext( return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext)); } -upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) { +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; @@ -74,20 +79,6 @@ upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) { return msg; } -upb_array *upb_array_new(upb_arena *a) { - upb_array *ret = upb_arena_malloc(a, sizeof(upb_array)); - - if (!ret) { - return NULL; - } - - ret->data = NULL; - ret->len = 0; - ret->size = 0; - - return ret; -} - void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, upb_arena *arena) { upb_msg_internal *in = upb_msg_getinternal(msg); @@ -108,4 +99,98 @@ const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) { return in->unknown; } +/** upb_array *****************************************************************/ + +upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type) { + upb_array *arr = upb_arena_malloc(a, sizeof(upb_array)); + + if (!arr) { + return NULL; + } + + arr->data = tag_arrptr(NULL, _upb_fieldtype_to_sizelg2[type]); + arr->len = 0; + arr->size = 0; + + return arr; +} + +bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) { + size_t new_size = UPB_MAX(arr->size, 4); + int elem_size_lg2 = arr->data & 7; + size_t old_bytes = arr->size << elem_size_lg2; + size_t new_bytes; + void* ptr = _upb_array_ptr(arr); + + /* Log2 ceiling of size. */ + while (new_size < min_size) new_size *= 2; + + new_bytes = new_size << elem_size_lg2; + ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes); + + if (!ptr) { + return false; + } + + arr->data = tag_arrptr(ptr, elem_size_lg2); + arr->size = new_size; + return true; +} + +static upb_array *getorcreate_array(upb_array **arr_ptr, upb_fieldtype_t type, + upb_arena *arena) { + upb_array *arr = *arr_ptr; + if (!arr) { + arr = _upb_array_new(arena, type); + if (!arr) return NULL; + *arr_ptr = arr; + } + 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; +} + +bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, + upb_fieldtype_t type, upb_arena *arena) { + upb_array *arr = getorcreate_array(arr_ptr, type, arena); + size_t elem = arr->len; + int lg2 = _upb_fieldtype_to_sizelg2[type]; + char *data; + + if (!arr || !resize_array(arr, elem + 1, arena)) return false; + + data = _upb_array_ptr(arr); + memcpy(data + (elem << lg2), value, 1 << lg2); + return true; +} + +/** upb_map *******************************************************************/ + +upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) { + upb_map *map = upb_arena_malloc(a, sizeof(upb_map)); + + if (!map) { + return NULL; + } + + upb_strtable_init2(&map->table, UPB_CTYPE_INT32, upb_arena_alloc(a)); + map->key_size = key_size; + map->val_size = value_size; + + return map; +} + #undef VOIDPTR_AT diff --git a/upb/msg.h b/upb/msg.h index 4bec023bd3..2b3274b6da 100644 --- a/upb/msg.h +++ b/upb/msg.h @@ -1,7 +1,6 @@ /* -** Data structures for message tables, used for parsing and serialization. -** This are much lighter-weight than full reflection, but they are do not -** have enough information to convert to text format, JSON, etc. +** Our memory representation for parsing tables and messages themselves. +** Functions in this file are used by generated code and possibly reflection. ** ** The definitions in this file are internal to upb. **/ @@ -11,12 +10,18 @@ #include #include + +#include "upb/table.int.h" #include "upb/upb.h" +#include "upb/port_def.inc" + #ifdef __cplusplus extern "C" { #endif +#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs) + typedef void upb_msg; /** upb_msglayout *************************************************************/ @@ -25,6 +30,12 @@ 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. */ +enum { + UPB_LABEL_MAP = 4 +}; + typedef struct { uint32_t number; uint16_t offset; @@ -44,26 +55,344 @@ typedef struct upb_msglayout { bool extendable; } upb_msglayout; -/** Message internal representation *******************************************/ +/** upb_msg *******************************************************************/ -/* Our internal representation for repeated fields. */ +/* Internal members of a upb_msg. We can change this without breaking binary + * compatibility. We put these before the user's data. The user's upb_msg* + * points after the upb_msg_internal. */ + +/* Used when a message is not extendable. */ typedef struct { - void *data; /* Each element is element_size. */ - size_t len; /* Measured in elements. */ - size_t size; /* Measured in elements. */ -} upb_array; + char *unknown; + size_t unknown_len; + size_t unknown_size; +} upb_msg_internal; -upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a); -upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a); +/* Used when a message is extendable. */ +typedef struct { + upb_inttable *extdict; + upb_msg_internal base; +} upb_msg_internal_withext; + +/* Maps upb_fieldtype_t -> memory size. */ +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); + +/* 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); + +/* Returns a reference to the message's unknown data. */ const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); -upb_array *upb_array_new(upb_arena *a); +UPB_INLINE bool _upb_has_field(const void *msg, size_t idx) { + return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0; +} + +UPB_INLINE bool _upb_sethas(const void *msg, size_t idx) { + return (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8)); +} + +UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) { + return (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8))); +} + +UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t num) { + return *PTR_AT(msg, case_ofs, int32_t) == num; +} + +/** upb_array *****************************************************************/ + +/* Our internal representation for repeated fields. */ +typedef struct { + uintptr_t data; /* Tagged ptr: low 2 bits of ptr are lg2(elem size). */ + size_t len; /* Measured in elements. */ + size_t size; /* Measured in elements. */ +} upb_array; + +UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) { + return (void*)((uintptr_t)arr->data & ~7UL); +} + +UPB_INLINE void *_upb_array_ptr(upb_array *arr) { + return (void*)_upb_array_constptr(arr); +} + +/* Creates a new array on the given arena. */ +upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type); + +/* Resizes the capacity of the array to be at least min_size. */ +bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena); + +/* Fallback functions for when the accessors require a resize. */ +void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, + upb_fieldtype_t type, upb_arena *arena); +bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, + upb_fieldtype_t type, upb_arena *arena); + +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*); + if (arr) { + if (size) *size = arr->len; + return _upb_array_constptr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} + +UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs, + size_t *size) { + upb_array *arr = *PTR_AT(msg, ofs, upb_array*); + if (arr) { + if (size) *size = arr->len; + return _upb_array_ptr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} + +UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size, + upb_fieldtype_t type, + upb_arena *arena) { + upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*); + upb_array *arr = *arr_ptr; + if (!arr || arr->size < size) { + return _upb_array_resize_fallback(arr_ptr, size, type, arena); + } + arr->len = size; + return _upb_array_ptr(arr); +} + + +UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs, + size_t elem_size, + upb_fieldtype_t type, + const void *value, + upb_arena *arena) { + upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*); + upb_array *arr = *arr_ptr; + void* ptr; + if (!arr || arr->len == arr->size) { + return _upb_array_append_fallback(arr_ptr, value, type, arena); + } + ptr = _upb_array_ptr(arr); + memcpy(PTR_AT(ptr, arr->len * elem_size, char), value, elem_size); + arr->len++; + return true; +} + +/** upb_map *******************************************************************/ + +/* Right now we use strmaps for everything. We'll likely want to use + * integer-specific maps for integer-keyed maps.*/ +typedef struct { + /* Size of key and val, based on the map type. Strings are represented as '0' + * because they must be handled specially. */ + char key_size; + char val_size; + + upb_strtable table; +} upb_map; + +/* Map entries aren't actually stored, they are only used during parsing. For + * parsing, it helps a lot if all map entry messages have the same layout. + * The compiler and def.c must ensure that all map entries have this layout. */ +typedef struct { + upb_msg_internal internal; + union { + upb_strview str; /* For str/bytes. */ + upb_value val; /* For all other types. */ + } k; + union { + upb_strview str; /* For str/bytes. */ + upb_value val; /* For all other types. */ + } v; +} upb_map_entry; + +/* Creates a new map on the given arena with this key/value type. */ +upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size); + +/* Converting between internal table representation and user values. + * + * _upb_map_tokey() and _upb_map_fromkey() are inverses. + * _upb_map_tovalue() and _upb_map_fromvalue() are inverses. + * + * These functions account for the fact that strings are treated differently + * from other types when stored in a map. + */ + +UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + return *(upb_strview*)key; + } else { + return upb_strview_make((const char*)key, size); + } +} + +UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + memcpy(out, &key, sizeof(key)); + } else { + memcpy(out, key.data, size); + } +} + +UPB_INLINE upb_value _upb_map_tovalue(const void *val, size_t size, + upb_arena *a) { + upb_value ret = {0}; + if (size == UPB_MAPTYPE_STRING) { + upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp)); + *strp = *(upb_strview*)val; + memcpy(&ret, &strp, sizeof(strp)); + } else { + memcpy(&ret, val, size); + } + return ret; +} + +UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + const upb_strview *strp = (const upb_strview*)upb_value_getptr(val); + memcpy(out, strp, sizeof(upb_strview)); + } else { + memcpy(out, &val, size); + } +} + +/* Map operations, shared by reflection and generated code. */ + +UPB_INLINE size_t _upb_map_size(const upb_map *map) { + return map->table.t.count; +} + +UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key, + size_t key_size, void *val, size_t val_size) { + 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) { + _upb_map_fromvalue(tabval, val, val_size); + } + return ret; +} + +UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) { + upb_strtable_iter it; + it.t = &map->table; + it.index = *iter; + upb_strtable_next(&it); + if (upb_strtable_done(&it)) return NULL; + *iter = it.index; + return (void*)str_tabent(&it); +} + +UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size, + void *val, size_t val_size, upb_arena *arena) { + upb_strview strkey = _upb_map_tokey(key, key_size); + upb_value tabval = _upb_map_tovalue(val, val_size, arena); + upb_alloc *a = upb_arena_alloc(arena); + + /* TODO(haberman): add overwrite operation to minimize number of lookups. */ + upb_strtable_remove3(&map->table, strkey.data, strkey.size, NULL, a); + return upb_strtable_insert3(&map->table, strkey.data, strkey.size, tabval, a); +} + +UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) { + upb_strview k = _upb_map_tokey(key, key_size); + return upb_strtable_remove3(&map->table, k.data, k.size, NULL, NULL); +} + +UPB_INLINE void _upb_map_clear(upb_map *map) { + upb_strtable_clear(&map->table); +} + +/* 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); + 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); + 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); + if (!map) return NULL; + return _upb_map_next(map, iter); +} + +UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key, + size_t key_size, void *val, size_t val_size, + upb_arena *arena) { + upb_map **map = PTR_AT(msg, ofs, upb_map *); + if (!*map) { + *map = _upb_map_new(arena, key_size, val_size); + } + return _upb_map_set(*map, key, key_size, val, val_size, arena); +} + +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); + 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); + if (!map) return; + _upb_map_clear(map); +} + +/* Accessing map key/value from a pointer, used by generated code only. */ + +UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) { + const upb_tabent *ent = (const upb_tabent*)msg; + uint32_t u32len; + upb_strview k; + k.data = upb_tabstr(ent->key, &u32len); + k.size = u32len; + _upb_map_fromkey(k, key, size); +} + +UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) { + const upb_tabent *ent = (const upb_tabent*)msg; + upb_value v; + _upb_value_setval(&v, ent->val.val); + _upb_map_fromvalue(v, val, size); +} + +UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) { + upb_tabent *ent = (upb_tabent*)msg; + /* This is like _upb_map_tovalue() except the entry already exists so we can + * reuse the allocated upb_strview for string fields. */ + if (size == UPB_MAPTYPE_STRING) { + upb_strview *strp = (upb_strview*)ent->val.val; + memcpy(strp, val, sizeof(*strp)); + } else { + memcpy(&ent->val.val, val, size); + } +} + +#undef PTR_AT #ifdef __cplusplus } /* extern "C" */ #endif +#include "upb/port_undef.inc" + #endif /* UPB_MSG_H_ */ diff --git a/upb/msgfactory.c b/upb/msgfactory.c deleted file mode 100644 index 4ecf2725b1..0000000000 --- a/upb/msgfactory.c +++ /dev/null @@ -1,248 +0,0 @@ - -#include "upb/msgfactory.h" - -#include "upb/port_def.inc" - -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; -} - -static size_t upb_msgval_sizeof2(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_DOUBLE: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT64: - return 8; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - case UPB_TYPE_UINT32: - case UPB_TYPE_FLOAT: - return 4; - case UPB_TYPE_BOOL: - return 1; - case UPB_TYPE_MESSAGE: - return sizeof(void*); - case UPB_TYPE_BYTES: - case UPB_TYPE_STRING: - return sizeof(upb_strview); - } - UPB_UNREACHABLE(); -} - -static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) { - if (upb_fielddef_isseq(f)) { - return sizeof(void*); - } else { - return upb_msgval_sizeof2(upb_fielddef_type(f)); - } -} - - -/** upb_msglayout *************************************************************/ - -static void upb_msglayout_free(upb_msglayout *l) { - upb_gfree(l); -} - -static size_t upb_msglayout_place(upb_msglayout *l, size_t size) { - size_t ret; - - l->size = align_up(l->size, size); - ret = l->size; - l->size += size; - return ret; -} - -static bool upb_msglayout_init(const upb_msgdef *m, - upb_msglayout *l, - upb_msgfactory *factory) { - upb_msg_field_iter it; - upb_msg_oneof_iter oit; - size_t hasbit; - size_t submsg_count = 0; - const upb_msglayout **submsgs; - upb_msglayout_field *fields; - - for (upb_msg_field_begin(&it, m); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - if (upb_fielddef_issubmsg(f)) { - submsg_count++; - } - } - - memset(l, 0, sizeof(*l)); - - fields = upb_gmalloc(upb_msgdef_numfields(m) * sizeof(*fields)); - submsgs = upb_gmalloc(submsg_count * sizeof(*submsgs)); - - if ((!fields && upb_msgdef_numfields(m)) || - (!submsgs && submsg_count)) { - /* OOM. */ - upb_gfree(fields); - upb_gfree(submsgs); - return false; - } - - l->field_count = upb_msgdef_numfields(m); - l->fields = fields; - l->submsgs = submsgs; - - /* Allocate data offsets in three stages: - * - * 1. hasbits. - * 2. regular fields. - * 3. oneof fields. - * - * OPT: There is a lot of room for optimization here to minimize the size. - */ - - /* Allocate hasbits and set basic field attributes. */ - submsg_count = 0; - for (upb_msg_field_begin(&it, m), hasbit = 0; - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - upb_msglayout_field *field = &fields[upb_fielddef_index(f)]; - - field->number = upb_fielddef_number(f); - field->descriptortype = upb_fielddef_descriptortype(f); - field->label = upb_fielddef_label(f); - - if (upb_fielddef_issubmsg(f)) { - const upb_msglayout *sub_layout = - upb_msgfactory_getlayout(factory, upb_fielddef_msgsubdef(f)); - field->submsg_index = submsg_count++; - submsgs[field->submsg_index] = sub_layout; - } - - if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { - field->presence = (hasbit++); - } else { - field->presence = 0; - } - } - - /* Account for space used by hasbits. */ - l->size = div_round_up(hasbit, 8); - - /* Allocate non-oneof fields. */ - for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - size_t field_size = upb_msg_fielddefsize(f); - size_t index = upb_fielddef_index(f); - - if (upb_fielddef_containingoneof(f)) { - /* Oneofs are handled separately below. */ - continue; - } - - fields[index].offset = upb_msglayout_place(l, field_size); - } - - /* Allocate oneof fields. Each oneof field consists of a uint32 for the case - * and space for the actual data. */ - for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); - upb_msg_oneof_next(&oit)) { - const upb_oneofdef* o = upb_msg_iter_oneof(&oit); - upb_oneof_iter fit; - - size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ - size_t field_size = 0; - uint32_t case_offset; - uint32_t data_offset; - - /* Calculate field size: the max of all field sizes. */ - for (upb_oneof_begin(&fit, o); - !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* f = upb_oneof_iter_field(&fit); - field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f)); - } - - /* Align and allocate case offset. */ - case_offset = upb_msglayout_place(l, case_size); - data_offset = upb_msglayout_place(l, field_size); - - for (upb_oneof_begin(&fit, o); - !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* f = upb_oneof_iter_field(&fit); - fields[upb_fielddef_index(f)].offset = data_offset; - fields[upb_fielddef_index(f)].presence = ~case_offset; - } - } - - /* 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); - - return true; -} - - -/** upb_msgfactory ************************************************************/ - -struct upb_msgfactory { - const upb_symtab *symtab; /* We own a ref. */ - upb_inttable layouts; -}; - -upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) { - upb_msgfactory *ret = upb_gmalloc(sizeof(*ret)); - - ret->symtab = symtab; - upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR); - - return ret; -} - -void upb_msgfactory_free(upb_msgfactory *f) { - upb_inttable_iter i; - upb_inttable_begin(&i, &f->layouts); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_msglayout *l = upb_value_getptr(upb_inttable_iter_value(&i)); - upb_msglayout_free(l); - } - - upb_inttable_uninit(&f->layouts); - upb_gfree(f); -} - -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) { - return f->symtab; -} - -const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, - const upb_msgdef *m) { - upb_value v; - UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m); - UPB_ASSERT(!upb_msgdef_mapentry(m)); - - if (upb_inttable_lookupptr(&f->layouts, m, &v)) { - UPB_ASSERT(upb_value_getptr(v)); - return upb_value_getptr(v); - } else { - /* In case of circular dependency, layout has to be inserted first. */ - upb_msglayout *l = upb_gmalloc(sizeof(*l)); - upb_msgfactory *mutable_f = (void*)f; - upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l)); - UPB_ASSERT(l); - if (!upb_msglayout_init(m, l, f)) { - upb_msglayout_free(l); - } - return l; - } -} diff --git a/upb/msgfactory.h b/upb/msgfactory.h deleted file mode 100644 index 9b3b599938..0000000000 --- a/upb/msgfactory.h +++ /dev/null @@ -1,48 +0,0 @@ - -#include "upb/def.h" -#include "upb/msg.h" - -#ifndef UPB_MSGFACTORY_H_ -#define UPB_MSGFACTORY_H_ - -/** upb_msgfactory ************************************************************/ - -struct upb_msgfactory; -typedef struct upb_msgfactory upb_msgfactory; - -#ifdef __cplusplus -extern "C" { -#endif - -/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and - * upb_visitorplan objects. These are the objects necessary to represent, - * populate, and and visit upb_msg objects. - * - * These caches are all populated by upb_msgdef, and lazily created on demand. - */ - -/* Creates and destroys a msgfactory, respectively. The messages for this - * msgfactory must come from |symtab| (which should outlive the msgfactory). */ -upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab); -void upb_msgfactory_free(upb_msgfactory *f); - -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f); - -/* The functions to get cached objects, lazily creating them on demand. These - * all require: - * - * - m is in upb_msgfactory_symtab(f) - * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts). - * - * The returned objects will live for as long as the msgfactory does. - * - * TODO(haberman): consider making this thread-safe and take a const - * upb_msgfactory. */ -const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, - const upb_msgdef *m); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_MSGFACTORY_H_ */ diff --git a/upb/pb/varint.int.h b/upb/pb/varint.int.h index ff1ca66149..293067a5cb 100644 --- a/upb/pb/varint.int.h +++ b/upb/pb/varint.int.h @@ -26,16 +26,16 @@ extern "C" { * descriptor type (upb_descriptortype_t). */ extern const uint8_t upb_pb_native_wire_types[]; -UPB_INLINE uint64_t byteswap64(uint64_t val) -{ - return ((((val) & 0xff00000000000000ull) >> 56) - | (((val) & 0x00ff000000000000ull) >> 40) - | (((val) & 0x0000ff0000000000ull) >> 24) - | (((val) & 0x000000ff00000000ull) >> 8) - | (((val) & 0x00000000ff000000ull) << 8) - | (((val) & 0x0000000000ff0000ull) << 24) - | (((val) & 0x000000000000ff00ull) << 40) - | (((val) & 0x00000000000000ffull) << 56)); +UPB_INLINE uint64_t byteswap64(uint64_t val) { + uint64_t byte = 0xff; + return (val & (byte << 56) >> 56) + | (val & (byte << 48) >> 40) + | (val & (byte << 40) >> 24) + | (val & (byte << 32) >> 8) + | (val & (byte << 24) << 8) + | (val & (byte << 16) << 24) + | (val & (byte << 8) << 40) + | (val & (byte << 0) << 56); } /* Zig-zag encoding/decoding **************************************************/ diff --git a/upb/port_def.inc b/upb/port_def.inc index b416eaeaf1..992148e736 100644 --- a/upb/port_def.inc +++ b/upb/port_def.inc @@ -28,6 +28,9 @@ #define UPB_SIZE(size32, size64) size64 #endif +/* These macros aren't really "port", they are helper macros that we don't want + * to leak. + */ #define UPB_FIELD_AT(msg, fieldtype, offset) \ *(fieldtype*)((const char*)(msg) + offset) @@ -40,6 +43,8 @@ UPB_FIELD_AT(msg, int, case_offset) = case_val; \ UPB_FIELD_AT(msg, fieldtype, offset) = value; +#define UPB_MAPTYPE_STRING 0 + /* UPB_INLINE: inline if possible, emit standalone code if required. */ #ifdef __cplusplus #define UPB_INLINE inline diff --git a/upb/port_undef.inc b/upb/port_undef.inc index 103180b7fb..6a4daa5076 100644 --- a/upb/port_undef.inc +++ b/upb/port_undef.inc @@ -1,5 +1,6 @@ /* See port_def.inc. This should #undef all macros #defined there. */ +#undef UPB_MAPTYPE_STRING #undef UPB_SIZE #undef UPB_FIELD_AT #undef UPB_READ_ONEOF diff --git a/upb/reflection.c b/upb/reflection.c new file mode 100644 index 0000000000..6d507233bb --- /dev/null +++ b/upb/reflection.c @@ -0,0 +1,251 @@ + +#include "upb/reflection.h" + +#include +#include "upb/table.int.h" +#include "upb/msg.h" + +#include "upb/port_def.inc" + +static char field_size[] = { + 0,/* 0 */ + 8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */ + 4, /* UPB_DESCRIPTOR_TYPE_FLOAT */ + 8, /* UPB_DESCRIPTOR_TYPE_INT64 */ + 8, /* UPB_DESCRIPTOR_TYPE_UINT64 */ + 4, /* UPB_DESCRIPTOR_TYPE_INT32 */ + 8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */ + 4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */ + 1, /* UPB_DESCRIPTOR_TYPE_BOOL */ + sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */ + sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */ + sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */ + sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */ + 4, /* UPB_DESCRIPTOR_TYPE_UINT32 */ + 4, /* UPB_DESCRIPTOR_TYPE_ENUM */ + 4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */ + 8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */ + 4, /* UPB_DESCRIPTOR_TYPE_SINT32 */ + 8, /* UPB_DESCRIPTOR_TYPE_SINT64 */ +}; + +/* Strings/bytes are special-cased in maps. */ +static char _upb_fieldtype_to_mapsize[12] = { + 0, + 1, /* UPB_TYPE_BOOL */ + 4, /* UPB_TYPE_FLOAT */ + 4, /* UPB_TYPE_INT32 */ + 4, /* UPB_TYPE_UINT32 */ + 4, /* UPB_TYPE_ENUM */ + sizeof(void*), /* UPB_TYPE_MESSAGE */ + 8, /* UPB_TYPE_DOUBLE */ + 8, /* UPB_TYPE_INT64 */ + 8, /* UPB_TYPE_UINT64 */ + 0, /* UPB_TYPE_STRING */ + 0, /* UPB_TYPE_BYTES */ +}; + +/** 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); +} + +static bool in_oneof(const upb_msglayout_field *field) { + return field->presence < 0; +} + +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); +} + +bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + UPB_ASSERT(field->presence); + if (in_oneof(field)) { + return *oneofcase(msg, field) == field->number; + } else { + uint32_t hasbit = field->presence; + return *PTR_AT(msg, hasbit / 8, char) | (1 << (hasbit % 8)); + } +} + +upb_msgval upb_msg_get(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); + upb_msgval val; + if (field->presence == 0 || upb_msg_has(msg, f)) { + int size = upb_fielddef_isseq(f) ? sizeof(void *) + : field_size[field->descriptortype]; + memcpy(&val, mem, size); + } else { + /* TODO(haberman): change upb_fielddef to not require this switch(). */ + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: + val.int32_val = upb_fielddef_defaultint32(f); + break; + case UPB_TYPE_INT64: + val.int64_val = upb_fielddef_defaultint64(f); + break; + case UPB_TYPE_UINT32: + val.uint32_val = upb_fielddef_defaultuint32(f); + break; + case UPB_TYPE_UINT64: + val.uint64_val = upb_fielddef_defaultuint64(f); + break; + case UPB_TYPE_FLOAT: + val.float_val = upb_fielddef_defaultfloat(f); + break; + case UPB_TYPE_DOUBLE: + val.double_val = upb_fielddef_defaultdouble(f); + break; + case UPB_TYPE_BOOL: + val.double_val = upb_fielddef_defaultbool(f); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size); + break; + case UPB_TYPE_MESSAGE: + val.msg_val = NULL; + break; + } + } + return val; +} + +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); + memcpy(&ret, mem, sizeof(void*)); + if (a && !ret.msg) { + if (upb_fielddef_ismap(f)) { + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY); + const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE); + ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value)); + } else if (upb_fielddef_isseq(f)) { + ret.array = upb_array_new(a, upb_fielddef_type(f)); + } else { + UPB_ASSERT(upb_fielddef_issubmsg(f)); + ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a); + } + memcpy(mem, &ret, sizeof(void*)); + } + return ret; +} + +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); + int size = upb_fielddef_isseq(f) ? sizeof(void *) + : field_size[field->descriptortype]; + memcpy(mem, &val, size); + if (in_oneof(field)) { + *oneofcase(msg, field) = field->number; + } +} + +#undef DEREF + +/** upb_array *****************************************************************/ + +upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) { + return _upb_array_new(a, type); +} + +size_t upb_array_size(const upb_array *arr) { + return arr->len; +} + +upb_msgval upb_array_get(const upb_array *arr, size_t i) { + upb_msgval ret; + const char* data = _upb_array_constptr(arr); + int lg2 = arr->data & 7; + UPB_ASSERT(i < arr->len); + memcpy(&ret, data + (i << lg2), 1 << lg2); + return ret; +} + +void upb_array_set(upb_array *arr, size_t i, upb_msgval val) { + char* data = _upb_array_ptr(arr); + int lg2 = arr->data & 7; + UPB_ASSERT(i < arr->len); + memcpy(data + (i << lg2), &val, 1 << lg2); +} + +bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) { + if (!_upb_array_realloc(arr, arr->len + 1, arena)) { + return false; + } + arr->len++; + upb_array_set(arr, arr->len - 1, val); + 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); +} + +/** upb_map *******************************************************************/ + +upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type, + upb_fieldtype_t value_type) { + return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type], + _upb_fieldtype_to_mapsize[value_type]); +} + +size_t upb_map_size(const upb_map *map) { + return _upb_map_size(map); +} + +bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) { + return _upb_map_get(map, &key, map->key_size, val, map->val_size); +} + +bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, + upb_arena *arena) { + return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena); +} + +bool upb_map_delete(upb_map *map, upb_msgval key) { + return _upb_map_delete(map, &key, map->key_size); +} + +bool upb_mapiter_next(const upb_map *map, size_t *iter) { + return _upb_map_next(map, 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_strtable_iter i; + upb_msgval ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size); + return ret; +} + +upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) { + upb_strtable_iter i; + upb_msgval ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size); + return ret; +} + +/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */ diff --git a/upb/reflection.h b/upb/reflection.h new file mode 100644 index 0000000000..b099d345e6 --- /dev/null +++ b/upb/reflection.h @@ -0,0 +1,126 @@ + +#ifndef UPB_REFLECTION_H_ +#define UPB_REFLECTION_H_ + +#include "upb/def.h" +#include "upb/msg.h" +#include "upb/upb.h" + +#include "upb/port_def.inc" + +typedef union { + bool bool_val; + float float_val; + double double_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + const upb_map* map_val; + const upb_msg* msg_val; + const upb_array* array_val; + upb_strview str_val; +} upb_msgval; + +typedef union { + upb_map* map; + upb_msg* msg; + upb_array* array; +} upb_mutmsgval; + +/** upb_msg *******************************************************************/ + +/* Creates a new message of the given type in the given arena. */ +upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a); + +/* Returns the value associated with this field. */ +upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f); + +/* Returns a mutable pointer to a map, array, or submessage value. If the given + * arena is non-NULL this will construct a new object if it was not previously + * present. May not be called for primitive fields. */ +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); + +/* Sets the given field to the given value. For a msg/array/map/string, the + * value must be in the same arena. */ +void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val, + upb_arena *a); + +/* Clears any field presence and sets the value back to its default. */ +void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f); + +/** upb_array *****************************************************************/ + +/* Creates a new array on the given arena that holds elements of this type. */ +upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type); + +/* Returns the size of the array. */ +size_t upb_array_size(const upb_array *arr); + +/* Returns the given element, which must be within the array's current size. */ +upb_msgval upb_array_get(const upb_array *arr, size_t i); + +/* Sets the given element, which must be within the array's current size. */ +void upb_array_set(upb_array *arr, size_t i, upb_msgval val); + +/* Appends an element to the array. Returns false on allocation failure. */ +bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena); + +/* Changes the size of a vector. New elements are initialized to empty/0. + * Returns false on allocation failure. */ +bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena); + +/** upb_map *******************************************************************/ + +/* Creates a new map on the given arena with the given key/value size. */ +upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type, + upb_fieldtype_t value_type); + +/* Returns the number of entries in the map. */ +size_t upb_map_size(const upb_map *map); + +/* Stores a value for the given key into |*val| (or the zero value if the key is + * not present). Returns whether the key was present. The |val| pointer may be + * NULL, in which case the function tests whether the given key is present. */ +bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val); + +/* Removes all entries in the map. */ +void upb_map_clear(upb_map *map); + +/* Sets the given key to the given value. Returns true if this was a new key in + * the map, or false if an existing key was replaced. */ +bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, + upb_arena *arena); + +/* Deletes this key from the table. Returns true if the key was present. */ +bool upb_map_delete(upb_map *map, upb_msgval key); + +/* Map iteration: + * + * size_t iter = UPB_MAP_BEGIN; + * while (upb_mapiter_next(map, &iter)) { + * upb_msgval key = upb_mapiter_key(map, iter); + * upb_msgval val = upb_mapiter_value(map, iter); + * + * // If mutating is desired. + * upb_mapiter_setvalue(map, iter, value2); + * } + */ + +/* 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 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); + +/* Sets the value for this entry. The iterator must not be done, and the + * iterator must not have been initialized const. */ +void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); + +#include "upb/port_undef.inc" + +#endif /* UPB_REFLECTION_H_ */ diff --git a/upb/table.c b/upb/table.c index fd5bc53f96..21f8fcf6f8 100644 --- a/upb/table.c +++ b/upb/table.c @@ -16,12 +16,6 @@ #define ARRAY_SIZE(x) \ ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) -static void upb_check_alloc(upb_table *t, upb_alloc *a) { - UPB_UNUSED(t); - UPB_UNUSED(a); - UPB_ASSERT_DEBUGVAR(t->alloc == a); -} - static const double MAX_LOAD = 0.85; /* The minimum utilization of the array part of a mixed hash/array table. This @@ -100,17 +94,12 @@ static bool isfull(upb_table *t) { } } -static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2, - upb_alloc *a) { +static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) { size_t bytes; t->count = 0; - t->ctype = ctype; t->size_lg2 = size_lg2; t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0; -#ifndef NDEBUG - t->alloc = a; -#endif bytes = upb_table_size(t) * sizeof(upb_tabent); if (bytes > 0) { t->entries = upb_malloc(a, bytes); @@ -123,7 +112,6 @@ static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2, } static void uninit(upb_table *t, upb_alloc *a) { - upb_check_alloc(t, a); upb_free(a, mutable_entries(t)); } @@ -159,7 +147,7 @@ static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, const upb_tabent *e = findentry(t, key, hash, eql); if (e) { if (v) { - _upb_value_setval(v, e->val.val, t->ctype); + _upb_value_setval(v, e->val.val); } return true; } else { @@ -175,7 +163,6 @@ static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, upb_tabent *our_e; UPB_ASSERT(findentry(t, key, hash, eql) == NULL); - UPB_ASSERT_DEBUGVAR(val.ctype == t->ctype); t->count++; mainpos_e = getentry_mutable(t, hash); @@ -221,7 +208,7 @@ static bool rm(upb_table *t, lookupkey_t key, upb_value *val, if (eql(chain->key, key)) { /* Element to remove is at the head of its chain. */ t->count--; - if (val) _upb_value_setval(val, chain->val.val, t->ctype); + if (val) _upb_value_setval(val, chain->val.val); if (removed) *removed = chain->key; if (chain->next) { upb_tabent *move = (upb_tabent*)chain->next; @@ -241,7 +228,7 @@ static bool rm(upb_table *t, lookupkey_t key, upb_value *val, /* Found element to remove. */ upb_tabent *rm = (upb_tabent*)chain->next; t->count--; - if (val) _upb_value_setval(val, chain->next->val.val, t->ctype); + if (val) _upb_value_setval(val, chain->next->val.val); if (removed) *removed = rm->key; rm->key = 0; /* Make the slot empty. */ chain->next = rm->next; @@ -294,7 +281,13 @@ static bool streql(upb_tabkey k1, lookupkey_t k2) { } bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) { - return init(&t->t, ctype, 2, a); + return init(&t->t, 2, a); +} + +void upb_strtable_clear(upb_strtable *t) { + size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent); + t->t.count = 0; + memset((char*)t->t.entries, 0, bytes); } void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) { @@ -308,18 +301,14 @@ bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) { upb_strtable new_table; upb_strtable_iter i; - upb_check_alloc(&t->t, a); - - if (!init(&new_table.t, t->t.ctype, size_lg2, a)) + if (!init(&new_table.t, size_lg2, a)) return false; upb_strtable_begin(&i, t); for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { + upb_strview key = upb_strtable_iter_key(&i); upb_strtable_insert3( - &new_table, - upb_strtable_iter_key(&i), - upb_strtable_iter_keylength(&i), - upb_strtable_iter_value(&i), - a); + &new_table, key.data, key.size, + upb_strtable_iter_value(&i), a); } upb_strtable_uninit2(t, a); *t = new_table; @@ -332,8 +321,6 @@ bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len, upb_tabkey tabkey; uint32_t hash; - upb_check_alloc(&t->t, a); - if (isfull(&t->t)) { /* Need to resize. New table of double the size, add old elements to it. */ if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) { @@ -361,7 +348,10 @@ bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, uint32_t hash = upb_murmur_hash2(key, len, 0); upb_tabkey tabkey; if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) { - upb_free(alloc, (void*)tabkey); + if (alloc) { + /* Arena-based allocs don't need to free and won't pass this. */ + upb_free(alloc, (void*)tabkey); + } return true; } else { return false; @@ -370,10 +360,6 @@ bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, /* Iteration */ -static const upb_tabent *str_tabent(const upb_strtable_iter *i) { - return &i->t->t.entries[i->index]; -} - void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) { i->t = t; i->index = begin(&t->t); @@ -389,21 +375,18 @@ bool upb_strtable_done(const upb_strtable_iter *i) { upb_tabent_isempty(str_tabent(i)); } -const char *upb_strtable_iter_key(const upb_strtable_iter *i) { - UPB_ASSERT(!upb_strtable_done(i)); - return upb_tabstr(str_tabent(i)->key, NULL); -} - -size_t upb_strtable_iter_keylength(const upb_strtable_iter *i) { +upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) { + upb_strview key; uint32_t len; UPB_ASSERT(!upb_strtable_done(i)); - upb_tabstr(str_tabent(i)->key, &len); - return len; + key.data = upb_tabstr(str_tabent(i)->key, &len); + key.size = len; + return key; } upb_value upb_strtable_iter_value(const upb_strtable_iter *i) { UPB_ASSERT(!upb_strtable_done(i)); - return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype); + return _upb_value_val(str_tabent(i)->val.val); } void upb_strtable_iter_setdone(upb_strtable_iter *i) { @@ -469,11 +452,11 @@ static void check(upb_inttable *t) { #endif } -bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, - size_t asize, int hsize_lg2, upb_alloc *a) { +bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2, + upb_alloc *a) { size_t array_bytes; - if (!init(&t->t, ctype, hsize_lg2, a)) return false; + if (!init(&t->t, hsize_lg2, a)) return false; /* Always make the array part at least 1 long, so that we know key 0 * won't be in the hash part, which simplifies things. */ t->array_size = UPB_MAX(1, asize); @@ -490,7 +473,7 @@ bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, } bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) { - return upb_inttable_sizedinit(t, ctype, 0, 4, a); + return upb_inttable_sizedinit(t, 0, 4, a); } void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) { @@ -504,8 +487,6 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, tabval.val = val.val; UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */ - upb_check_alloc(&t->t, a); - if (key < t->array_size) { UPB_ASSERT(!upb_arrhas(t->array[key])); t->array_count++; @@ -516,7 +497,7 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, size_t i; upb_table new_table; - if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1, a)) { + if (!init(&new_table, t->t.size_lg2 + 1, a)) { return false; } @@ -525,7 +506,7 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, uint32_t hash; upb_value v; - _upb_value_setval(&v, e->val.val, t->t.ctype); + _upb_value_setval(&v, e->val.val); hash = upb_inthash(e->key); insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql); } @@ -544,7 +525,7 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) { const upb_tabval *table_v = inttable_val_const(t, key); if (!table_v) return false; - if (v) _upb_value_setval(v, table_v->val, t->t.ctype); + if (v) _upb_value_setval(v, table_v->val); return true; } @@ -562,7 +543,7 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { upb_tabval empty = UPB_TABVALUE_EMPTY_INIT; t->array_count--; if (val) { - _upb_value_setval(val, t->array[key].val, t->t.ctype); + _upb_value_setval(val, t->array[key].val); } mutable_array(t)[key] = empty; success = true; @@ -577,7 +558,6 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { } bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) { - upb_check_alloc(&t->t, a); return upb_inttable_insert2(t, upb_inttable_count(t), val, a); } @@ -590,7 +570,6 @@ upb_value upb_inttable_pop(upb_inttable *t) { bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, upb_alloc *a) { - upb_check_alloc(&t->t, a); return upb_inttable_insert2(t, (uintptr_t)key, val, a); } @@ -615,8 +594,6 @@ void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { int size_lg2; upb_inttable new_t; - upb_check_alloc(&t->t, a); - upb_inttable_begin(&i, t); for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { uintptr_t key = upb_inttable_iter_key(&i); @@ -649,7 +626,7 @@ void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0; int hashsize_lg2 = log2ceil(hash_size); - upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2, a); + upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a); upb_inttable_begin(&i, t); for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { uintptr_t k = upb_inttable_iter_key(&i); @@ -715,8 +692,7 @@ uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { UPB_ASSERT(!upb_inttable_done(i)); return _upb_value_val( - i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val, - i->t->t.ctype); + i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val); } void upb_inttable_iter_setdone(upb_inttable_iter *i) { diff --git a/upb/table.int.h b/upb/table.int.h index 23b0b2f221..75575eb7d5 100644 --- a/upb/table.int.h +++ b/upb/table.int.h @@ -52,19 +52,8 @@ typedef enum { typedef struct { uint64_t val; -#ifndef NDEBUG - /* In debug mode we carry the value type around also so we can check accesses - * to be sure the right member is being read. */ - upb_ctype_t ctype; -#endif } upb_value; -#ifdef NDEBUG -#define SET_TYPE(dest, val) UPB_UNUSED(val) -#else -#define SET_TYPE(dest, val) dest = val -#endif - /* Like strdup(), which isn't always available since it's not ANSI C. */ char *upb_strdup(const char *s, upb_alloc *a); /* Variant that works with a length-delimited rather than NULL-delimited string, @@ -75,15 +64,13 @@ UPB_INLINE char *upb_gstrdup(const char *s) { return upb_strdup(s, &upb_alloc_global); } -UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val, - upb_ctype_t ctype) { +UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) { v->val = val; - SET_TYPE(v->ctype, ctype); } -UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) { +UPB_INLINE upb_value _upb_value_val(uint64_t val) { upb_value ret; - _upb_value_setval(&ret, val, ctype); + _upb_value_setval(&ret, val); return ret; } @@ -98,7 +85,6 @@ UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) { #define FUNCS(name, membername, type_t, converter, proto_type) \ UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \ val->val = (converter)cval; \ - SET_TYPE(val->ctype, proto_type); \ } \ UPB_INLINE upb_value upb_value_ ## name(type_t val) { \ upb_value ret; \ @@ -106,7 +92,6 @@ UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) { return ret; \ } \ UPB_INLINE type_t upb_value_get ## name(upb_value val) { \ - UPB_ASSERT_DEBUGVAR(val.ctype == proto_type); \ return (type_t)(converter)val.val; \ } @@ -124,12 +109,10 @@ FUNCS(fptr, fptr, upb_func*, uintptr_t, UPB_CTYPE_FPTR) UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) { memcpy(&val->val, &cval, sizeof(cval)); - SET_TYPE(val->ctype, UPB_CTYPE_FLOAT); } UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) { memcpy(&val->val, &cval, sizeof(cval)); - SET_TYPE(val->ctype, UPB_CTYPE_DOUBLE); } UPB_INLINE upb_value upb_value_float(float cval) { @@ -173,7 +156,6 @@ typedef struct { #define UPB_TABVALUE_EMPTY_INIT {-1} - /* upb_table ******************************************************************/ typedef struct _upb_tabent { @@ -190,7 +172,6 @@ typedef struct _upb_tabent { typedef struct { size_t count; /* Number of entries in the hash part. */ size_t mask; /* Mask to turn hash value -> bucket. */ - upb_ctype_t ctype; /* Type of all values. */ uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ /* Hash table entries. @@ -200,17 +181,6 @@ typedef struct { * initialize const hash tables. Then we cast away const when we have to. */ const upb_tabent *entries; - -#ifndef NDEBUG - /* This table's allocator. We make the user pass it in to every relevant - * function and only use this to check it in debug mode. We do this solely - * to keep upb_table as small as possible. This might seem slightly paranoid - * but the plan is to use upb_table for all map fields and extension sets in - * a forthcoming message representation, so there could be a lot of these. - * If this turns out to be too annoying later, we can change it (since this - * is an internal-only header file). */ - upb_alloc *alloc; -#endif } upb_table; typedef struct { @@ -224,12 +194,6 @@ typedef struct { size_t array_count; /* Array part number of elements. */ } upb_inttable; -#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \ - {UPB_TABLE_INIT(count, mask, ctype, size_lg2, ent), a, asize, acount} - -#define UPB_EMPTY_INTTABLE_INIT(ctype) \ - UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0) - #define UPB_ARRAY_EMPTYENT -1 UPB_INLINE size_t upb_table_size(const upb_table *t) { @@ -298,6 +262,7 @@ upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs, size_t size); upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs, size_t size); +void upb_strtable_clear(upb_strtable *t); /* Inserts the given key into the hashtable with the given value. The key must * not already exist in the hash table. For string tables, the key must be @@ -399,7 +364,7 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, if (key < t->array_size) { upb_tabval arrval = t->array[key]; if (upb_arrhas(arrval)) { - _upb_value_setval(v, arrval.val, t->t.ctype); + _upb_value_setval(v, arrval.val); return true; } else { return false; @@ -409,7 +374,7 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, if (t->t.entries == NULL) return false; for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) { if ((uint32_t)e->key == key) { - _upb_value_setval(v, e->val.val, t->t.ctype); + _upb_value_setval(v, e->val.val); return true; } if (e->next == NULL) return false; @@ -463,8 +428,7 @@ typedef struct { void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t); void upb_strtable_next(upb_strtable_iter *i); bool upb_strtable_done(const upb_strtable_iter *i); -const char *upb_strtable_iter_key(const upb_strtable_iter *i); -size_t upb_strtable_iter_keylength(const upb_strtable_iter *i); +upb_strview upb_strtable_iter_key(const upb_strtable_iter *i); upb_value upb_strtable_iter_value(const upb_strtable_iter *i); void upb_strtable_iter_setdone(upb_strtable_iter *i); bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, @@ -488,6 +452,10 @@ typedef struct { bool array_part; } upb_inttable_iter; +UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) { + return &i->t->t.entries[i->index]; +} + void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t); void upb_inttable_next(upb_inttable_iter *i); bool upb_inttable_done(const upb_inttable_iter *i); diff --git a/upb/upb.h b/upb/upb.h index 79c19d281e..011103d949 100644 --- a/upb/upb.h +++ b/upb/upb.h @@ -318,14 +318,15 @@ typedef enum { UPB_TYPE_INT32 = 3, UPB_TYPE_UINT32 = 4, UPB_TYPE_ENUM = 5, /* Enum values are int32. */ - /* Types stored as pointers (probably 4 or 8 bytes). */ - UPB_TYPE_STRING = 6, - UPB_TYPE_BYTES = 7, - UPB_TYPE_MESSAGE = 8, + /* Types stored as void* (probably 4 or 8 bytes). */ + UPB_TYPE_MESSAGE = 6, /* Types stored as 8 bytes. */ - UPB_TYPE_DOUBLE = 9, - UPB_TYPE_INT64 = 10, - UPB_TYPE_UINT64 = 11 + 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; /* The repeated-ness of each field; this matches descriptor.proto. */ @@ -357,7 +358,7 @@ typedef enum { UPB_DESCRIPTOR_TYPE_SINT64 = 18 } upb_descriptortype_t; -extern const uint8_t upb_desctype_to_fieldtype[]; +#define UPB_MAP_BEGIN -1 #include "upb/port_undef.inc" diff --git a/upbc/generator.cc b/upbc/generator.cc index 7096278180..50fb42d564 100644 --- a/upbc/generator.cc +++ b/upbc/generator.cc @@ -331,21 +331,24 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output("/* $0 */\n\n", message->full_name()); std::string msgname = ToCIdent(message->full_name()); - output( - "UPB_INLINE $0 *$0_new(upb_arena *arena) {\n" - " return ($0 *)upb_msg_new(&$1, arena);\n" - "}\n" - "UPB_INLINE $0 *$0_parse(const char *buf, size_t size,\n" - " upb_arena *arena) {\n" - " $0 *ret = $0_new(arena);\n" - " return (ret && upb_decode(buf, size, ret, &$1, arena)) ? ret : NULL;\n" - "}\n" - "UPB_INLINE char *$0_serialize(const $0 *msg, upb_arena *arena, size_t " - "*len) {\n" - " return upb_encode(msg, &$1, arena, len);\n" - "}\n" - "\n", - MessageName(message), MessageInit(message)); + + if (!message->options().map_entry()) { + output( + "UPB_INLINE $0 *$0_new(upb_arena *arena) {\n" + " return ($0 *)_upb_msg_new(&$1, arena);\n" + "}\n" + "UPB_INLINE $0 *$0_parse(const char *buf, size_t size,\n" + " upb_arena *arena) {\n" + " $0 *ret = $0_new(arena);\n" + " return (ret && upb_decode(buf, size, ret, &$1, arena)) ? ret : NULL;\n" + "}\n" + "UPB_INLINE char *$0_serialize(const $0 *msg, upb_arena *arena, size_t " + "*len) {\n" + " return upb_encode(msg, &$1, arena, len);\n" + "}\n" + "\n", + MessageName(message), MessageInit(message)); + } for (int i = 0; i < message->oneof_decl_count(); i++) { const protobuf::OneofDescriptor* oneof = message->oneof_decl(i); @@ -367,8 +370,10 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output GetSizeInit(layout.GetOneofCaseOffset(oneof))); } - for (auto field : FieldNumberOrder(message)) { + // Generate const methods. + for (auto field : FieldNumberOrder(message)) { + // Generate hazzer (if any). if (layout.HasHasbit(field)) { output( "UPB_INLINE bool $0_has_$1(const $0 *msg) { " @@ -383,7 +388,43 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output field->number()); } - if (field->is_repeated()) { + // Generate getter. + if (field->is_map()) { + const protobuf::Descriptor* entry = field->message_type(); + const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1); + const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2); + output( + "UPB_INLINE size_t $0_$1_size(const $0 *msg) {" + "return _upb_msg_map_size(msg, $2); }\n", + msgname, field->name(), GetSizeInit(layout.GetFieldOffset(field))); + output( + "UPB_INLINE bool $0_$1_get(const $0 *msg, $2 key, $3 *val) { " + "return _upb_msg_map_get(msg, $4, &key, $5, val, $6); }\n", + msgname, field->name(), CType(key), CType(val), + GetSizeInit(layout.GetFieldOffset(field)), + key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(key)", + val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(*val)"); + output( + "UPB_INLINE $0 $1_$2_next(const $1 *msg, size_t* iter) { " + "return ($0)_upb_msg_map_next(msg, $3, iter); }\n", + CTypeConst(field), msgname, field->name(), + GetSizeInit(layout.GetFieldOffset(field))); + } else if (message->options().map_entry()) { + output( + "UPB_INLINE $0 $1_$2(const $1 *msg) {\n" + " $3 ret;\n" + " _upb_msg_map_$2(msg, &ret, $4);\n" + " return ret;\n" + "}\n", + CTypeConst(field), msgname, field->name(), CType(field), + field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(ret)"); + } else if (field->is_repeated()) { output( "UPB_INLINE $0 const* $1_$2(const $1 *msg, size_t *len) { " "return ($0 const*)_upb_array_accessor(msg, $3, len); }\n", @@ -408,8 +449,43 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output("\n"); + // Generate mutable methods. + for (auto field : FieldNumberOrder(message)) { - if (field->is_repeated()) { + if (field->is_map()) { + // TODO(haberman): add map-based mutators. + const protobuf::Descriptor* entry = field->message_type(); + const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1); + const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2); + output( + "UPB_INLINE void $0_$1_clear($0 *msg) { _upb_msg_map_clear(msg, $2); }\n", + msgname, field->name(), + GetSizeInit(layout.GetFieldOffset(field))); + output( + "UPB_INLINE bool $0_$1_set($0 *msg, $2 key, $3 val, upb_arena *a) { " + "return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a); }\n", + msgname, field->name(), CType(key), CType(val), + GetSizeInit(layout.GetFieldOffset(field)), + key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(key)", + val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(val)"); + output( + "UPB_INLINE bool $0_$1_delete($0 *msg, $2 key) { " + "return _upb_msg_map_delete(msg, $3, &key, $4); }\n", + msgname, field->name(), CType(key), + GetSizeInit(layout.GetFieldOffset(field)), + key->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(key)"); + output( + "UPB_INLINE $0 $1_$2_nextmutable($1 *msg, size_t* iter) { " + "return ($0)_upb_msg_map_next(msg, $3, iter); }\n", + CType(field), msgname, field->name(), + GetSizeInit(layout.GetFieldOffset(field))); + } else if (field->is_repeated()) { output( "UPB_INLINE $0* $1_mutable_$2($1 *msg, size_t *len) {\n" " return ($0*)_upb_array_mutable_accessor(msg, $3, len);\n" @@ -419,17 +495,15 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output output( "UPB_INLINE $0* $1_resize_$2($1 *msg, size_t len, " "upb_arena *arena) {\n" - " return ($0*)_upb_array_resize_accessor(msg, $3, len, $4, $5, " - "arena);\n" + " return ($0*)_upb_array_resize_accessor(msg, $3, len, $4, arena);\n" "}\n", CType(field), msgname, field->name(), GetSizeInit(layout.GetFieldOffset(field)), - GetSizeInit(MessageLayout::SizeOfUnwrapped(field).size), UpbType(field)); if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { output( "UPB_INLINE struct $0* $1_add_$2($1 *msg, upb_arena *arena) {\n" - " struct $0* sub = (struct $0*)upb_msg_new(&$3, arena);\n" + " struct $0* sub = (struct $0*)_upb_msg_new(&$3, arena);\n" " bool ok = _upb_array_append_accessor(\n" " msg, $4, $5, $6, &sub, arena);\n" " if (!ok) return NULL;\n" @@ -443,8 +517,8 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output } else { output( "UPB_INLINE bool $1_add_$2($1 *msg, $0 val, upb_arena *arena) {\n" - " return _upb_array_append_accessor(\n" - " msg, $3, $4, $5, &val, arena);\n" + " return _upb_array_append_accessor(msg, $3, $4, $5, &val,\n" + " arena);\n" "}\n", CType(field), msgname, field->name(), GetSizeInit(layout.GetFieldOffset(field)), @@ -452,9 +526,25 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output UpbType(field)); } } else { + // Non-repeated field. + if (message->options().map_entry() && field->name() == "key") { + // Key cannot be mutated. + continue; + } + + // The common function signature for all setters. Varying implementations + // follow. output("UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msgname, field->name(), CType(field)); - if (field->containing_oneof()) { + + if (message->options().map_entry()) { + output( + " _upb_msg_map_set_value(msg, &value, $0);\n" + "}\n", + field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING + ? "0" + : "sizeof(" + CType(field) + ")"); + } else if (field->containing_oneof()) { output( " UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n" "}\n", @@ -470,12 +560,14 @@ void GenerateMessageInHeader(const protobuf::Descriptor* message, Output& output "}\n", CType(field), GetSizeInit(layout.GetFieldOffset(field))); } - if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + + if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE && + !message->options().map_entry()) { output( "UPB_INLINE struct $0* $1_mutable_$2($1 *msg, upb_arena *arena) {\n" " struct $0* sub = (struct $0*)$1_$2(msg);\n" " if (sub == NULL) {\n" - " sub = (struct $0*)upb_msg_new(&$3, arena);\n" + " sub = (struct $0*)_upb_msg_new(&$3, arena);\n" " if (!sub) return NULL;\n" " $1_set_$2(msg, sub);\n" " }\n" @@ -495,7 +587,6 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) { output( "#ifndef $0_UPB_H_\n" "#define $0_UPB_H_\n\n" - "#include \"upb/generated_util.h\"\n" "#include \"upb/msg.h\"\n" "#include \"upb/decode.h\"\n" "#include \"upb/encode.h\"\n\n", @@ -661,6 +752,8 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output) { case_offset.size64 = -case_offset.size64 - 1; presence = GetSizeInit(case_offset); } + // Sync '4' with UPB_LABEL_MAP in upb/msg.h. + int label = field->is_map() ? 4 : field->label(); output(" {$0, $1, $2, $3, $4, $5},\n", field->number(), @@ -668,7 +761,7 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output) { presence, submsg_index, field->type(), - field->label()); + label); } output("};\n\n"); } @@ -752,12 +845,27 @@ void WriteDefSource(const protobuf::FileDescriptor* file, Output& output) { output("extern upb_def_init $0;\n", DefInitSymbol(file->dependency(i))); } + std::vector file_messages = + SortedMessages(file); + + for (auto message : file_messages) { + output("extern const upb_msglayout $0;\n", MessageInit(message)); + } + output("\n"); + + output("static const upb_msglayout *layouts[$0] = {\n", file_messages.size()); + for (auto message : file_messages) { + output(" &$0,\n", MessageInit(message)); + } + output("};\n"); + output("\n"); + protobuf::FileDescriptorProto file_proto; file->CopyTo(&file_proto); std::string file_data; file_proto.SerializeToString(&file_data); - output("static const char descriptor[$0] =\n", file_data.size()); + output("static const char descriptor[$0] =", file_data.size()); { if (file_data.size() > 65535) { @@ -777,13 +885,15 @@ void WriteDefSource(const protobuf::FileDescriptor* file, Output& output) { // 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\"\n", + " \"$0\"", EscapeTrigraphs(absl::CEscape(file_data.substr(i, kBytesPerLine)))); } } output(";\n"); } + output("\n"); output("static upb_def_init *deps[$0] = {\n", file->dependency_count() + 1); for (int i = 0; i < file->dependency_count(); i++) { @@ -791,9 +901,11 @@ void WriteDefSource(const protobuf::FileDescriptor* file, Output& output) { } output(" NULL\n"); output("};\n"); + output("\n"); output("upb_def_init $0 = {\n", DefInitSymbol(file)); output(" deps,\n"); + output(" layouts,\n"); output(" \"$0\",\n", file->name()); output(" UPB_STRVIEW_INIT(descriptor, $0)\n", file_data.size()); output("};\n"); diff --git a/upbc/message_layout.cc b/upbc/message_layout.cc index f0a68725c2..bf3eb2b3bd 100644 --- a/upbc/message_layout.cc +++ b/upbc/message_layout.cc @@ -1,5 +1,6 @@ #include "upbc/message_layout.h" +#include "google/protobuf/descriptor.pb.h" namespace upbc { @@ -25,12 +26,18 @@ MessageLayout::Size MessageLayout::Place( bool MessageLayout::HasHasbit(const protobuf::FieldDescriptor* field) { return field->file()->syntax() == protobuf::FileDescriptor::SYNTAX_PROTO2 && field->label() != protobuf::FieldDescriptor::LABEL_REPEATED && - !field->containing_oneof(); + !field->containing_oneof() && + !field->containing_type()->options().map_entry(); } MessageLayout::SizeAndAlign MessageLayout::SizeOf( const protobuf::FieldDescriptor* field) { - if (field->is_repeated()) { + if (field->containing_type()->options().map_entry()) { + // Map entries aren't actually stored, they are only used during parsing. + // For parsing, it helps a lot if all map entry messages have the same + // layout. + return {{8, 16}, {4, 8}}; // upb_stringview + } else if (field->is_repeated()) { return {{4, 8}, {4, 8}}; // Pointer to array object. } else { return SizeOfUnwrapped(field);