json/upb: Implement json EnumValueName for upb

PiperOrigin-RevId: 956632937
This commit is contained in:
Tony Liao 2026-07-30 11:17:22 -07:00 committed by Copybara-Service
parent 2a36520396
commit 8111a7473d
38 changed files with 1026 additions and 147 deletions

View file

@ -506,6 +506,12 @@ alias(
visibility = ["//visibility:public"],
)
alias(
name = "json_enumvalue_options_proto_srcs",
actual = "//src/google/protobuf:json_enumvalue_options_proto_srcs",
visibility = ["//visibility:public"],
)
alias(
name = "json_enumvalue_options_cc_proto",
actual = "//src/google/protobuf:json_enumvalue_options_cc_proto",

View file

@ -115,6 +115,8 @@ if (protobuf_BUILD_LIBUPB)
FILES
${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/descriptor.upb.h
${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/descriptor.upb_minitable.h
${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb.h
${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/json_enumvalue_options.upb_minitable.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/google/protobuf
COMPONENT protobuf-headers
)

View file

@ -95,6 +95,8 @@ google/protobuf/java_features.proto
google/protobuf/json/json.h
google/protobuf/json_enumvalue_options.pb.h
google/protobuf/json_enumvalue_options.proto
google/protobuf/json_enumvalue_options.upb.h
google/protobuf/json_enumvalue_options.upb_minitable.h
google/protobuf/map.h
google/protobuf/map_entry.h
google/protobuf/map_field.h
@ -222,6 +224,7 @@ upb/reflection/enum_value_def.h
upb/reflection/extension_range.h
upb/reflection/field_def.h
upb/reflection/file_def.h
upb/reflection/json_enumvalue_options_bootstrap.h
upb/reflection/message.h
upb/reflection/message_def.h
upb/reflection/message_reserved_range.h

View file

@ -9,6 +9,9 @@ set(bootstrap_sources
${bootstrap_cmake_dir}/google/protobuf/descriptor.upb.h
${bootstrap_cmake_dir}/google/protobuf/descriptor.upb_minitable.h
${bootstrap_cmake_dir}/google/protobuf/descriptor.upb_minitable.c
${bootstrap_cmake_dir}/google/protobuf/json_enumvalue_options.upb.h
${bootstrap_cmake_dir}/google/protobuf/json_enumvalue_options.upb_minitable.h
${bootstrap_cmake_dir}/google/protobuf/json_enumvalue_options.upb_minitable.c
)
# Note: upb does not support shared library builds, and is intended to be

View file

@ -252,7 +252,11 @@ pkg_files(
"//src/google/protobuf:descriptor_upb_c_proto",
"//src/google/protobuf:descriptor_upb_minitable_proto",
"//src/google/protobuf:descriptor_upb_reflection_proto",
"//src/google/protobuf:json_enumvalue_options_upb_c_proto",
"//src/google/protobuf:json_enumvalue_options_upb_minitable_proto",
"//src/google/protobuf:json_enumvalue_options_upb_reflection_proto",
"//upb/reflection:descriptor_upb_proto",
"//upb/reflection:json_enumvalue_options_upb_proto",
],
prefix = "google/protobuf",
)

View file

@ -24,6 +24,7 @@ STALENESS_TESTS=(
"php:proto_staleness_test"
"ruby/ext/google/protobuf_c:test_amalgamation_staleness"
"upb/reflection:descriptor_upb_proto_staleness_test"
"upb/reflection:json_enumvalue_options_upb_proto_staleness_test"
"upb_generator:plugin_upb_proto_staleness_test"
)

View file

@ -405,6 +405,24 @@ cc_proto_library(
deps = [":json_enumvalue_options_proto"],
)
upb_c_proto_library(
name = "json_enumvalue_options_upb_c_proto",
visibility = ["//:__subpackages__"],
deps = [":json_enumvalue_options_proto"],
)
upb_minitable_proto_library(
name = "json_enumvalue_options_upb_minitable_proto",
visibility = ["//:__subpackages__"],
deps = [":json_enumvalue_options_proto"],
)
upb_proto_reflection_library(
name = "json_enumvalue_options_upb_reflection_proto",
visibility = ["//:__subpackages__"],
deps = [":json_enumvalue_options_proto"],
)
################################################################################
# C++ Runtime Library
################################################################################
@ -1207,6 +1225,12 @@ filegroup(
visibility = ["//:__subpackages__"],
)
filegroup(
name = "json_enumvalue_options_proto_srcs",
srcs = ["json_enumvalue_options.proto"],
visibility = ["//:__subpackages__"],
)
filegroup(
name = "cpp_features_proto_srcs",
srcs = ["cpp_features.proto"],
@ -1559,7 +1583,7 @@ exports_files(
"//:__pkg__",
"//python:__pkg__",
"//ruby:__pkg__",
"//upb:__pkg__",
"//upb:__subpackages__",
],
)

View file

@ -111,7 +111,6 @@ cc_library(
"//src/google/protobuf/stubs",
"@abseil-cpp//absl/algorithm:container",
"@abseil-cpp//absl/log:absl_check",
"@abseil-cpp//absl/log:absl_log",
"@abseil-cpp//absl/status",
"@abseil-cpp//absl/status:statusor",
"@abseil-cpp//absl/strings",
@ -293,7 +292,6 @@ cc_library(
"//src/google/protobuf/io:zero_copy_sink",
"//src/google/protobuf/stubs",
"//src/google/protobuf/util:type_resolver",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/log:absl_check",
"@abseil-cpp//absl/log:absl_log",
"@abseil-cpp//absl/status",
@ -319,6 +317,7 @@ proto_library(
visibility = [
"//:__subpackages__",
"//src/google/protobuf:__subpackages__",
"//upb:__subpackages__",
],
deps = ["//src/google/protobuf:json_options_proto"],
)

View file

@ -24,6 +24,7 @@ enum Armor {
ARMOR_SABATON = 7 [(pb.enumvalue.json).string = "sabaton"];
ARMOR_SOLLERET = 7 [(pb.enumvalue.json).string = "sabaton"];
ARMOR_HACHI_MAI_DO = 8 [(pb.enumvalue.json).string = "8"];
ARMOR_GREAVES = 9 [(pb.enumvalue.json).string = "ARMOR_GREAVES"];
}
message Knight {

View file

@ -32,8 +32,10 @@ UPB_CONFIG_VISIBILITY = [
"//hpb_generator:__subpackages__",
"//lua:__pkg__",
"//python:__pkg__",
"//src/google/protobuf/compiler:__subpackages__",
"//upb:__subpackages__",
"//upb_generator:__subpackages__",
"//src/google/protobuf/compiler:__subpackages__",
]
config_setting(
@ -159,6 +161,8 @@ upb_amalgamation(
":generated_code_support",
"//src/google/protobuf:descriptor_upb_c_proto",
"//src/google/protobuf:descriptor_upb_minitable_proto",
"//src/google/protobuf:json_enumvalue_options_upb_c_proto",
"//src/google/protobuf:json_enumvalue_options_upb_minitable_proto",
"//upb/base",
"//upb/base:internal",
"//upb/hash:hash",
@ -179,6 +183,7 @@ upb_amalgamation(
"//upb/port",
"//upb/reflection",
"//upb/reflection:descriptor_upb_proto",
"//upb/reflection:json_enumvalue_options_upb_proto",
"//upb/reflection:internal",
"//upb/text:debug",
"//upb/text:internal",
@ -216,6 +221,9 @@ upb_amalgamation(
"//src/google/protobuf:descriptor_upb_c_proto",
"//src/google/protobuf:descriptor_upb_minitable_proto",
"//src/google/protobuf:descriptor_upb_reflection_proto",
"//src/google/protobuf:json_enumvalue_options_upb_c_proto",
"//src/google/protobuf:json_enumvalue_options_upb_minitable_proto",
"//src/google/protobuf:json_enumvalue_options_upb_reflection_proto",
"//upb/base",
"//upb/base:internal",
"//upb/hash:hash",
@ -237,6 +245,7 @@ upb_amalgamation(
"//upb/port",
"//upb/reflection",
"//upb/reflection:descriptor_upb_proto",
"//upb/reflection:json_enumvalue_options_upb_proto",
"//upb/reflection:internal",
"//upb/wire",
"//upb/wire:back_alloc",
@ -271,6 +280,8 @@ upb_amalgamation(
":generated_code_support",
"//src/google/protobuf:descriptor_upb_c_proto",
"//src/google/protobuf:descriptor_upb_minitable_proto",
"//src/google/protobuf:json_enumvalue_options_upb_c_proto",
"//src/google/protobuf:json_enumvalue_options_upb_minitable_proto",
"//upb/base",
"//upb/base:internal",
"//upb/hash:hash",
@ -292,6 +303,7 @@ upb_amalgamation(
"//upb/port",
"//upb/reflection",
"//upb/reflection:descriptor_upb_proto",
"//upb/reflection:json_enumvalue_options_upb_proto",
"//upb/reflection:internal",
"//upb/util:def_to_proto",
"//upb/wire",
@ -336,6 +348,7 @@ filegroup(
filegroup(
name = "test_protos",
testonly = 1,
srcs = [
"//src/google/protobuf:test_messages_proto2.proto",
"//src/google/protobuf:test_messages_proto3.proto",

View file

@ -26,11 +26,16 @@ genrule(
srcs = [
"//src/google/protobuf:descriptor_upb_c_proto",
"//src/google/protobuf:descriptor_upb_minitable_proto",
"//src/google/protobuf:json_enumvalue_options_upb_c_proto",
"//src/google/protobuf:json_enumvalue_options_upb_minitable_proto",
],
outs = [
"generated-in/google/protobuf/descriptor.upb.h",
"generated-in/google/protobuf/descriptor.upb_minitable.c",
"generated-in/google/protobuf/descriptor.upb_minitable.h",
"generated-in/google/protobuf/json_enumvalue_options.upb.h",
"generated-in/google/protobuf/json_enumvalue_options.upb_minitable.c",
"generated-in/google/protobuf/json_enumvalue_options.upb_minitable.h",
],
cmd = "cp $(SRCS) $(@D)/generated-in/google/protobuf",
)

View file

@ -42,6 +42,8 @@ cc_test(
srcs = ["decode_test.cc"],
deps = [
":json",
":json_enumval_custom_string_upb_proto",
":json_enumval_custom_string_upb_reflection_proto",
":test_upb_proto",
":test_upb_proto_reflection",
"//:any_upb_proto",
@ -49,6 +51,7 @@ cc_test(
"//:struct_upb_proto",
"//upb/base",
"//upb/mem",
"//upb/message",
"//upb/reflection",
"//upb/reflection:internal_cc",
"//upb/reflection:reflection_cc",
@ -62,6 +65,8 @@ cc_test(
srcs = ["encode_test.cc"],
deps = [
":json",
":json_enumval_custom_string_upb_proto",
":json_enumval_custom_string_upb_reflection_proto",
":test_upb_proto",
":test_upb_proto_reflection",
"//:any_upb_proto",
@ -69,6 +74,7 @@ cc_test(
"//:struct_upb_proto",
"//upb/base",
"//upb/mem",
"//upb/message",
"//upb/reflection",
"//upb/reflection:internal_cc",
"//upb/reflection:reflection_cc",
@ -100,6 +106,18 @@ upb_proto_reflection_library(
deps = [":test_proto"],
)
upb_c_proto_library(
name = "json_enumval_custom_string_upb_proto",
testonly = 1,
deps = ["//src/google/protobuf/json:json_enumval_custom_string_proto"],
)
upb_proto_reflection_library(
name = "json_enumval_custom_string_upb_reflection_proto",
testonly = 1,
deps = ["//src/google/protobuf/json:json_enumval_custom_string_proto"],
)
filegroup(
name = "test_srcs",
srcs = glob(
@ -113,10 +131,15 @@ filegroup(
filegroup(
name = "test_protos",
testonly = 1,
srcs = glob(
[
"**/*test.proto",
],
),
) + [
"//src/google/protobuf:json_enumvalue_options.proto",
"//src/google/protobuf:json_options.proto",
"//src/google/protobuf/json:json_enumval_custom_string_proto_srcs",
],
visibility = ["//upb:__pkg__"],
)

View file

@ -830,7 +830,7 @@ static upb_JsonMessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) {
upb_StringView str = jsondec_string(d);
const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f);
const upb_EnumValueDef* ev =
upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size);
upb_EnumDef_FindByJsonNameWithSize(e, str.data, str.size);
upb_JsonMessageValue val = {.ignore = false};
if (ev) {
val.value.int32_val = upb_EnumValueDef_Number(ev);

View file

@ -7,38 +7,61 @@
#include "upb/json/decode.h"
#include <cstring>
#include <string>
#include <vector>
#include "google/protobuf/struct.upb.h"
#include <gtest/gtest.h>
#include "google/protobuf/json/json_enumval_custom_string.upb.h"
#include "google/protobuf/json/json_enumval_custom_string.upbdefs.h"
#include "upb/base/status.hpp"
#include "upb/base/upcast.h"
#include "upb/json/test.upb.h"
#include "upb/json/test.upbdefs.h"
#include "upb/mem/arena.h"
#include "upb/mem/arena.hpp"
#include "upb/message/message.h"
#include "upb/reflection/def.h"
#include "upb/reflection/def.hpp"
static upb_test_Box* JsonDecode(const char* json, upb_Arena* a) {
static bool JsonDecodeGeneric(const char* json, upb_Message* msg,
const upb_MessageDef* (*getmsgdef)(upb_DefPool*),
upb_Arena* arena) {
upb::Status status;
upb::DefPool defpool;
upb::MessageDefPtr m(upb_test_Box_getmsgdef(defpool.ptr()));
EXPECT_TRUE(m.ptr() != nullptr);
const upb_MessageDef* m = getmsgdef(defpool.ptr());
EXPECT_TRUE(m != nullptr);
upb_test_Box* box = upb_test_Box_new(a);
int options = 0;
bool ok = upb_JsonDecode(json, strlen(json), UPB_UPCAST(box), m.ptr(),
defpool.ptr(), options, a, status.ptr());
return ok ? box : nullptr;
return upb_JsonDecode(json, strlen(json), msg, m, defpool.ptr(), options,
arena, status.ptr());
}
static upb_test_Box* JsonDecode(const char* json, upb_Arena* a) {
upb_test_Box* box = upb_test_Box_new(a);
if (JsonDecodeGeneric(json, UPB_UPCAST(box), upb_test_Box_getmsgdef, a)) {
return box;
}
return nullptr;
}
static json_enumval_custom_string_Knight* JsonDecodeKnight(const char* json,
upb_Arena* a) {
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a);
if (JsonDecodeGeneric(json, UPB_UPCAST(knight),
json_enumval_custom_string_Knight_getmsgdef, a)) {
return knight;
}
return nullptr;
}
struct FloatTest {
const std::string json;
const char* json;
float f;
};
static const std::vector<FloatTest> FloatTestsPass = {
static const FloatTest kFloatTestsPass[] = {
{R"({"f": 0})", 0},
{R"({"f": 1})", 1},
{R"({"f": 1.000000})", 1},
@ -53,7 +76,7 @@ static const std::vector<FloatTest> FloatTestsPass = {
-340282346638528859811704183484516925440.0},
};
static const std::vector<FloatTest> FloatTestsFail = {
static const FloatTest kFloatTestsFail[] = {
{R"({"f": 1z})", 0},
{R"({"f": 3.4028236e+38})", 0},
{R"({"f": -3.4028236e+38})", 0},
@ -63,15 +86,15 @@ static const std::vector<FloatTest> FloatTestsFail = {
TEST(JsonTest, DecodeFloats) {
upb::Arena a;
for (const auto& test : FloatTestsPass) {
upb_test_Box* box = JsonDecode(test.json.c_str(), a.ptr());
for (const auto& test : kFloatTestsPass) {
upb_test_Box* box = JsonDecode(test.json, a.ptr());
EXPECT_NE(box, nullptr);
float f = upb_test_Box_f(box);
EXPECT_EQ(f, test.f);
}
for (const auto& test : FloatTestsFail) {
upb_test_Box* box = JsonDecode(test.json.c_str(), a.ptr());
for (const auto& test : kFloatTestsFail) {
upb_test_Box* box = JsonDecode(test.json, a.ptr());
EXPECT_EQ(box, nullptr);
}
}
@ -111,6 +134,181 @@ TEST(JsonTest, RejectsBase64WithHighBitBytes) {
EXPECT_EQ(box, nullptr);
}
// Test decoding when the enum value has no custom string option set, falling
// back to the default enum value name.
TEST(JsonTest, DecodeEnumMissingCustomStringOption) {
upb::Arena a;
std::string json = R"({"armor":"ARMOR_GORGET"})";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_GORGET,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding when a standard custom string option is provided.
TEST(JsonTest, DecodeEnumWithCustomString) {
upb::Arena a;
std::string json = R"({"armor":"gr8 helm"})";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_GREAT_HELM,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding when the custom string option contains escaped double quotes.
TEST(JsonTest, DecodeEnumCustomStringWithEscapedQuotes) {
upb::Arena a;
std::string json = "{\"armor\":\"a\\\"b\"}";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_GAUNTLET,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding when the custom string option is an empty string ("").
TEST(JsonTest, DecodeEnumEmptyCustomString) {
upb::Arena a;
std::string json = R"({"armor":""})";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_COIF,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding when the custom string option contains escaped control
// characters (tab and newline).
TEST(JsonTest, DecodeEnumCustomStringWithEscapedControlChars) {
upb::Arena a;
std::string json = R"({"armor":"p\taul\ndron"})";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_PAULDRON,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding an enum value passed as a raw integer literal.
TEST(JsonTest, DecodeEnumFromIntegerLiteral) {
upb::Arena a;
std::string json = R"({"armor":1})";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_GREAT_HELM,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding by raw enum name even when a custom string option is defined.
TEST(JsonTest, DecodeEnumRawNameWhenCustomStringDefined) {
upb::Arena a;
std::string json = R"({"armor":"ARMOR_GREAT_HELM"})";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_GREAT_HELM,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding when the custom string option is enclosed within double quotes.
TEST(JsonTest, DecodeEnumCustomStringEnclosedInQuotes) {
upb::Arena a;
std::string json = "{\"armor\":\"\\\"plate\\\"\"}";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_PLATE,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding a custom string that maps to aliased enum values.
TEST(JsonTest, DecodeEnumAliasedCustomString) {
upb::Arena a;
std::string json = R"({"armor":"sabaton"})";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_SABATON,
json_enumval_custom_string_Knight_armor(knight));
EXPECT_EQ(json_enumval_custom_string_ARMOR_SOLLERET,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding when the custom string option consists of numeric digits ("8").
TEST(JsonTest, DecodeEnumNumericCustomString) {
upb::Arena a;
std::string json = R"({"armor":"8"})";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_HACHI_MAI_DO,
json_enumval_custom_string_Knight_armor(knight));
}
// Test decoding an enum value whose custom string option is identical to its
// original enum value name. Also verify that normal name lookup by original
// name is not marked as JSON-only.
TEST(JsonTest, DecodeEnumCustomStringSameAsName) {
upb::Arena a;
std::string json = R"({"armor":"ARMOR_GREAVES"})";
json_enumval_custom_string_Knight* knight =
JsonDecodeKnight(json.c_str(), a.ptr());
EXPECT_NE(knight, nullptr);
EXPECT_EQ(json_enumval_custom_string_ARMOR_GREAVES,
json_enumval_custom_string_Knight_armor(knight));
upb::DefPool defpool;
const upb_MessageDef* m =
json_enumval_custom_string_Knight_getmsgdef(defpool.ptr());
ASSERT_NE(m, nullptr);
const upb_FieldDef* f = upb_MessageDef_FindFieldByName(m, "armor");
ASSERT_NE(f, nullptr);
const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f);
ASSERT_NE(e, nullptr);
const upb_EnumValueDef* ev = upb_EnumDef_FindValueByName(e, "ARMOR_GREAVES");
ASSERT_NE(ev, nullptr);
EXPECT_EQ(upb_EnumValueDef_Number(ev),
json_enumval_custom_string_ARMOR_GREAVES);
}
// Test that decoding fails on case mismatch against a custom string.
TEST(JsonTest, DecodeEnumCustomStringCaseMismatchFails) {
upb::Arena a;
std::string json = "{\"armor\":\"A\\\"b\"}";
EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr);
}
// Test that decoding fails on case mismatch against a raw enum name.
TEST(JsonTest, DecodeEnumRawNameCaseMismatchFails) {
upb::Arena a;
std::string json = R"({"armor":"armor_GAUNtlet"})";
EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr);
}
// Test that decoding fails on an unknown enum value string.
TEST(JsonTest, DecodeEnumUnknownStringFails) {
upb::Arena a;
std::string json = R"({"armor":"UNKNOWN_1"})";
EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr);
}
// Test that decoding fails when the JSON payload is an array.
TEST(JsonTest, DecodeEnumInvalidArrayPayloadFails) {
upb::Arena a;
std::string json = R"({"armor":["gr8 helm"]})";
EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr);
}
// Test that decoding fails when the JSON payload is a boolean.
TEST(JsonTest, DecodeEnumInvalidBooleanPayloadFails) {
upb::Arena a;
std::string json = R"({"armor":true})";
EXPECT_EQ(JsonDecodeKnight(json.c_str(), a.ptr()), nullptr);
}
#include "upb/mem/alloc.h"
struct FailAfterAlloc {

View file

@ -7,16 +7,25 @@
#include "upb/json/encode.h"
#include <ctype.h>
#include <float.h>
#include <inttypes.h>
#include <math.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include "upb/base/descriptor_constants.h"
#include "upb/base/status.h"
#include "upb/base/string_view.h"
#include "upb/lex/round_trip.h"
#include "upb/mem/arena.h"
#include "upb/message/array.h"
#include "upb/message/map.h"
#include "upb/message/message.h"
#include "upb/mini_table/message.h"
#include "upb/port/vsnprintf_compat.h"
#include "upb/reflection/def.h"
#include "upb/reflection/message.h"
#include "upb/wire/decode.h"
@ -44,6 +53,7 @@ static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg,
const upb_MessageDef* m, bool first);
static void jsonenc_value(jsonenc* e, const upb_Message* msg,
const upb_MessageDef* m);
static void jsonenc_string(jsonenc* e, upb_StringView str);
UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) {
upb_Status_SetErrorMessage(e->status, msg);
@ -205,7 +215,8 @@ static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) {
: upb_EnumDef_FindValueByNumber(e_def, val);
if (ev) {
jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev));
const char* name = upb_EnumValueDef_JsonName(ev);
jsonenc_string(e, upb_StringView_FromString(name));
} else {
jsonenc_printf(e, "%" PRId32, val);
}

View file

@ -12,31 +12,47 @@
#include "google/protobuf/struct.upb.h"
#include <gtest/gtest.h>
#include "google/protobuf/json/json_enumval_custom_string.upb.h"
#include "google/protobuf/json/json_enumval_custom_string.upbdefs.h"
#include "upb/base/status.hpp"
#include "upb/base/upcast.h"
#include "upb/json/test.upb.h"
#include "upb/json/test.upbdefs.h"
#include "upb/mem/arena.h"
#include "upb/mem/arena.hpp"
#include "upb/message/message.h"
#include "upb/reflection/def.h"
#include "upb/reflection/def.hpp"
static std::string JsonEncode(const upb_test_Box* msg, int options) {
static std::string JsonEncodeGeneric(
const upb_Message* msg, const upb_MessageDef* (*getmsgdef)(upb_DefPool*),
int options) {
upb::Arena a;
upb::Status status;
upb::DefPool defpool;
upb::MessageDefPtr m(upb_test_Box_getmsgdef(defpool.ptr()));
EXPECT_TRUE(m.ptr() != nullptr);
const upb_MessageDef* m = getmsgdef(defpool.ptr());
EXPECT_TRUE(m != nullptr);
size_t json_size = upb_JsonEncode(UPB_UPCAST(msg), m.ptr(), defpool.ptr(),
options, nullptr, 0, status.ptr());
size_t json_size =
upb_JsonEncode(msg, m, defpool.ptr(), options, nullptr, 0, status.ptr());
char* json_buf = (char*)upb_Arena_Malloc(a.ptr(), json_size + 1);
size_t size = upb_JsonEncode(UPB_UPCAST(msg), m.ptr(), defpool.ptr(), options,
json_buf, json_size + 1, status.ptr());
size_t size = upb_JsonEncode(msg, m, defpool.ptr(), options, json_buf,
json_size + 1, status.ptr());
EXPECT_EQ(size, json_size);
return std::string(json_buf, json_size);
}
static std::string JsonEncode(const upb_test_Box* msg, int options) {
return JsonEncodeGeneric(UPB_UPCAST(msg), upb_test_Box_getmsgdef, options);
}
static std::string JsonEncodeKnight(
const json_enumval_custom_string_Knight* msg, int options) {
return JsonEncodeGeneric(
UPB_UPCAST(msg), json_enumval_custom_string_Knight_getmsgdef, options);
}
// Encode a single optional enum.
TEST(JsonTest, EncodeEnum) {
upb::Arena a;
@ -96,3 +112,111 @@ TEST(JsonTest, EncodeConflictJsonName) {
upb_test_Box_set_new_value(new_box, 2);
EXPECT_EQ(R"({"value":2})", JsonEncode(new_box, 0));
}
// Test encoding when the enum value has no custom string option set, verifying
// it falls back to the default enum value name ("ARMOR_GORGET").
TEST(JsonTest, EncodeEnumMissingCustomStringOption) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_GORGET);
EXPECT_EQ(R"({"armor":"ARMOR_GORGET"})", JsonEncodeKnight(knight, 0));
}
// Test encoding when a standard custom string option is defined ("gr8 helm").
TEST(JsonTest, EncodeEnumWithCustomString) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_GREAT_HELM);
EXPECT_EQ(R"({"armor":"gr8 helm"})", JsonEncodeKnight(knight, 0));
}
// Test encoding when the custom string option contains double quotes requiring
// escaping ("a\"b").
TEST(JsonTest, EncodeEnumCustomStringWithEscapedQuotes) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_GAUNTLET);
EXPECT_EQ("{\"armor\":\"a\\\"b\"}", JsonEncodeKnight(knight, 0));
}
// Test encoding when the custom string option is enclosed within double quotes
// ("\"plate\"").
TEST(JsonTest, EncodeEnumCustomStringEnclosedInQuotes) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_PLATE);
EXPECT_EQ("{\"armor\":\"\\\"plate\\\"\"}", JsonEncodeKnight(knight, 0));
}
// Test encoding when the custom string option is an empty string ("").
TEST(JsonTest, EncodeEnumEmptyCustomString) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_COIF);
EXPECT_EQ(R"({"armor":""})", JsonEncodeKnight(knight, 0));
}
// Test encoding when the custom string option contains control characters (tab
// and newline) requiring escaping ("p\taul\ndron").
TEST(JsonTest, EncodeEnumCustomStringWithEscapedControlChars) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_PAULDRON);
EXPECT_EQ(R"({"armor":"p\taul\ndron"})", JsonEncodeKnight(knight, 0));
}
// Test encoding an enum value that has aliased values sharing a custom string
// option ("sabaton").
TEST(JsonTest, EncodeEnumAliasedCustomString) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_SABATON);
EXPECT_EQ(R"({"armor":"sabaton"})", JsonEncodeKnight(knight, 0));
}
// Test encoding when the custom string option consists of numeric digits ("8").
TEST(JsonTest, EncodeEnumNumericCustomString) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_HACHI_MAI_DO);
EXPECT_EQ(R"({"armor":"8"})", JsonEncodeKnight(knight, 0));
}
// Test encoding an enum value whose custom string option is identical to its
// original enum value name.
TEST(JsonTest, EncodeEnumCustomStringSameAsName) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_GREAVES);
EXPECT_EQ(R"({"armor":"ARMOR_GREAVES"})", JsonEncodeKnight(knight, 0));
}
// Test encoding when upb_JsonEncode_FormatEnumsAsIntegers is set, verifying
// integer format option overrides the custom string option.
TEST(JsonTest, EncodeEnumWithIntegerFormatOverride) {
upb::Arena a;
json_enumval_custom_string_Knight* knight =
json_enumval_custom_string_Knight_new(a.ptr());
json_enumval_custom_string_Knight_set_armor(
knight, json_enumval_custom_string_ARMOR_GREAT_HELM);
EXPECT_EQ(R"({"armor":1})",
JsonEncodeKnight(knight, upb_JsonEncode_FormatEnumsAsIntegers));
}

View file

@ -726,7 +726,8 @@ Error, UINTPTR_MAX is undefined
: "X"(UPB_PRIVATE(name))); \
__VA_ARGS__ \
}
#elif defined(__ELF__) || defined(__wasm__) || defined(__MACH__)
#elif defined(__ELF__) || defined(__wasm__) || defined(__MACH__) || \
defined(__MINGW32__)
#define UPB_CONSTRUCTOR(name, unique_name, ...) \
_UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \
__attribute__((weak, visibility("hidden"), constructor)) void UPB_PRIVATE( \
@ -752,9 +753,14 @@ Error, UINTPTR_MAX is undefined
static void __cdecl UPB_PRIVATE(name)(void) { __VA_ARGS__ }
#else
// No constructor support, nothing we can do except not break builds.
#if defined(__GNUC__) || defined(__clang__)
#define UPB_CONSTRUCTOR(name, unique_name, ...) \
static __attribute__((used)) void UPB_PRIVATE(name)(void) { __VA_ARGS__ }
#else
#define UPB_CONSTRUCTOR(name, unique_name, ...) \
static void UPB_PRIVATE(name)(void) { __VA_ARGS__ }
#endif
#endif
//
// Weak alias platform support. Theoretically this should be possible to do with
@ -791,9 +797,9 @@ Error, UINTPTR_MAX is undefined
#elif defined(__ELF__) || defined(__wasm__)
// On ELF, weak aliases work properly, so we can have all weak MiniTables
// point to the same empty singleton MiniTable. This reduces code size if many
// MiniTables are tree shaken.
// On ELF, weak aliases work properly, so we can have all weak MiniTables
// point to the same empty singleton MiniTable. This reduces code size if many
// MiniTables are tree shaken.
#define UPB_WEAK_SINGLETON_PLACEHOLDER_MINITABLE() \
__attribute__((weak)) \
const upb_MiniTable kUpb_WeakSingletonPlaceholderMiniTable = { \

View file

@ -34,6 +34,19 @@ bootstrap_upb_proto_library(
strip_prefix = "third_party/protobuf/github/bootstrap/src",
)
bootstrap_upb_proto_library(
name = "json_enumvalue_options_upb_proto",
bootstrap_hdr = "json_enumvalue_options_bootstrap.h",
proto_lib_deps = ["//src/google/protobuf:json_enumvalue_options_proto"],
src_files = ["google/protobuf/json_enumvalue_options.proto"],
src_rules = [
"//:descriptor_proto_srcs",
"//:json_enumvalue_options_proto_srcs",
],
strip_prefix = "third_party/protobuf/github/bootstrap/src",
deps = [":descriptor_upb_proto"],
)
bootstrap_cc_library(
name = "reflection",
hdrs = [
@ -139,7 +152,10 @@ bootstrap_cc_library(
"oneof_def.h",
"service_def.h",
],
bootstrap_deps = [":descriptor_upb_proto"],
bootstrap_deps = [
":descriptor_upb_proto",
":json_enumvalue_options_upb_proto",
],
copts = UPB_DEFAULT_COPTS,
features = UPB_DEFAULT_FEATURES,
visibility = ["//visibility:public"],

View file

@ -405,6 +405,7 @@ class EnumValDefPtr {
int32_t number() const { return upb_EnumValueDef_Number(ptr_); }
const char* full_name() const { return upb_EnumValueDef_FullName(ptr_); }
const char* json_name() const { return upb_EnumValueDef_JsonName(ptr_); }
const char* name() const { return upb_EnumValueDef_Name(ptr_); }
private:
@ -458,6 +459,10 @@ class EnumDefPtr {
return EnumValDefPtr(upb_EnumDef_Value(ptr_, i));
}
EnumValDefPtr FindValueByJsonName(const char* name) const {
return EnumValDefPtr(upb_EnumDef_FindByJsonName(ptr_, name));
}
// Lookups from name to integer, returning true if found.
EnumValDefPtr FindValueByName(const char* name) const {
return EnumValDefPtr(upb_EnumDef_FindValueByName(ptr_, name));

View file

@ -54,6 +54,28 @@ struct upb_EnumDef {
bool is_sorted; // Whether all of the values are defined in ascending order.
};
// We store both regular proto enum names and custom JSON enum names in the
// same strtable (ntoi). This is safe because protoc enforces that custom JSON
// enum names never conflict with default enum names across different enum
// values (or are identical, in which case we leave the entry untagged). Because
// upb_EnumValueDef pointers are arena-aligned to at least 4 bytes (bit 0 is
// always 0 for untagged pointers), we set bit 0 to tag custom JSON-only names
// so that regular name lookups can ignore them.
static const uintptr_t kUpb_EnumDef_JsonOnlyTag = 1ULL;
static upb_value _upb_EnumDef_TagJsonOnly(upb_value v) {
v.val |= kUpb_EnumDef_JsonOnlyTag;
return v;
}
static bool _upb_EnumDef_IsJsonOnly(upb_value v) {
return (v.val & kUpb_EnumDef_JsonOnlyTag) != 0;
}
static const upb_EnumValueDef* _upb_EnumDef_Untag(upb_value v) {
return (const upb_EnumValueDef*)(v.val & ~kUpb_EnumDef_JsonOnlyTag);
}
upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i) {
return (upb_EnumDef*)&e[i];
}
@ -62,18 +84,43 @@ const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e) {
return e->layout;
}
bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a) {
void _upb_EnumDef_Insert(upb_DefBuilder* ctx, upb_EnumDef* e,
upb_EnumValueDef* v) {
const char* name = upb_EnumValueDef_Name(v);
const upb_value val = upb_value_constptr(v);
bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, a);
if (!ok) return false;
bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, ctx->arena);
if (!ok) _upb_DefBuilder_OomErr(ctx);
// Multiple enumerators can have the same number, first one wins.
// Aliased enum values can share the same custom JSON name, first one wins.
const char* json_name = upb_EnumValueDef_JsonName(v);
size_t json_len = strlen(json_name);
if (strcmp(json_name, name) != 0) {
upb_value existing_value;
if (upb_strtable_lookup2(&e->ntoi, json_name, json_len, &existing_value)) {
const upb_EnumValueDef* enumval = _upb_EnumDef_Untag(existing_value);
if (upb_EnumValueDef_Number(enumval) != upb_EnumValueDef_Number(v)) {
// If the custom JSON name exists, but points to a value with a
// different number, then this is a parse/conflict error.
_upb_DefBuilder_Errf(ctx,
"duplicate custom json_name (%s) in enum (%s)",
json_name, upb_EnumDef_FullName(e));
}
} else {
upb_value json_val = _upb_EnumDef_TagJsonOnly(val);
if (!upb_strtable_insert(&e->ntoi, json_name, json_len, json_val,
ctx->arena)) {
_upb_DefBuilder_OomErr(ctx);
}
}
}
// Multiple enum values can have the same number, first one wins.
const int number = upb_EnumValueDef_Number(v);
if (!upb_inttable_lookup(&e->iton, number, NULL)) {
return upb_inttable_insert(&e->iton, number, val, a);
if (!upb_inttable_insert(&e->iton, number, val, ctx->arena)) {
_upb_DefBuilder_OomErr(ctx);
}
}
return true;
}
const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) {
@ -130,6 +177,16 @@ upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i) {
int upb_EnumDef_ValueCount(const upb_EnumDef* e) { return e->value_count; }
const upb_EnumValueDef* upb_EnumDef_FindByJsonNameWithSize(const upb_EnumDef* e,
const char* name,
size_t size) {
upb_value v;
if (!upb_strtable_lookup2(&e->ntoi, name, size, &v)) {
return NULL;
}
return _upb_EnumDef_Untag(v);
}
const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e,
const char* name) {
return upb_EnumDef_FindValueByNameWithSize(e, name, strlen(name));
@ -138,9 +195,13 @@ const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e,
const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
const upb_EnumDef* e, const char* name, size_t size) {
upb_value v;
return upb_strtable_lookup2(&e->ntoi, name, size, &v)
? upb_value_getconstptr(v)
: NULL;
if (!upb_strtable_lookup2(&e->ntoi, name, size, &v)) {
return NULL;
}
if (_upb_EnumDef_IsJsonOnly(v)) {
return NULL;
}
return upb_value_getconstptr(v);
}
const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e,
@ -281,7 +342,7 @@ static void create_enumdef(upb_DefBuilder* ctx, const char* prefix,
upb_EnumDef_FullName(e));
}
bool ok = upb_strtable_init(&e->ntoi, n_value, ctx->arena);
bool ok = upb_strtable_init(&e->ntoi, n_value * 2, ctx->arena);
if (!ok) _upb_DefBuilder_OomErr(ctx);
ok = upb_inttable_init(&e->iton, ctx->arena);

View file

@ -12,6 +12,7 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "upb/base/string_view.h"
#include "upb/mem/arena.h"
@ -29,6 +30,12 @@ bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num);
const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e);
int32_t upb_EnumDef_Default(const upb_EnumDef* e);
UPB_API const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e);
UPB_API const upb_EnumValueDef* upb_EnumDef_FindByJsonNameWithSize(
const upb_EnumDef* e, const char* name, size_t size);
UPB_INLINE const upb_EnumValueDef* upb_EnumDef_FindByJsonName(
const upb_EnumDef* e, const char* name) {
return upb_EnumDef_FindByJsonNameWithSize(e, name, strlen(name));
}
const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e,
const char* name);
UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(

View file

@ -20,6 +20,8 @@
#include "upb/reflection/enum_value_def.h"
#include "upb/reflection/internal/def_builder.h"
#include "upb/reflection/internal/enum_def.h"
#include "upb/reflection/internal/strdup2.h"
#include "upb/reflection/json_enumvalue_options_bootstrap.h"
// Must be last.
#include "upb/port/def.inc"
@ -29,6 +31,7 @@ struct upb_EnumValueDef {
const google_protobuf_FeatureSet* resolved_features;
const upb_EnumDef* parent;
const char* full_name;
const char* json_name;
int32_t number;
};
@ -50,7 +53,7 @@ const upb_EnumValueDef** _upb_EnumValueDefs_Sorted(const upb_EnumValueDef* v,
(upb_EnumValueDef**)upb_Arena_Malloc(a, n * sizeof(void*));
if (!out) return NULL;
for (int i = 0; i < n; i++) {
for (size_t i = 0; i < n; i++) {
out[i] = (upb_EnumValueDef*)&v[i];
}
qsort(out, n, sizeof(void*), _upb_EnumValueDef_Compare);
@ -80,6 +83,10 @@ const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v) {
return v->full_name;
}
const char* upb_EnumValueDef_JsonName(const upb_EnumValueDef* v) {
return v->json_name ? v->json_name : upb_EnumValueDef_Name(v);
}
const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v) {
return _upb_DefBuilder_FullToShort(v->full_name);
}
@ -91,6 +98,19 @@ uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v) {
return v - upb_EnumDef_Value(v->parent, 0);
}
static const char* _upb_EnumValueDef_ExtractJsonName(
upb_DefBuilder* ctx, const upb_EnumValueDef* v) {
if (!upb_EnumValueDef_HasOptions(v)) return NULL;
const google_protobuf_EnumValueOptions* opts = (const google_protobuf_EnumValueOptions*)v->opts;
if (!pb_enumvalue_has_json(opts)) return NULL;
const pb_enumvalue_JsonEnumValueOptions* json_opts = pb_enumvalue_json(opts);
if (!json_opts || !pb_enumvalue_JsonEnumValueOptions_has_string(json_opts)) {
return NULL;
}
upb_StringView str = pb_enumvalue_JsonEnumValueOptions_string(json_opts);
return upb_strdup2(str.data, str.size, ctx->arena);
}
static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix,
const google_protobuf_EnumValueDescriptorProto* val_proto,
const google_protobuf_FeatureSet* parent_features,
@ -105,11 +125,11 @@ static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix,
v->parent = e; // Must happen prior to _upb_DefBuilder_Add()
v->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name);
v->number = google_protobuf_EnumValueDescriptorProto_number(val_proto);
v->json_name = _upb_EnumValueDef_ExtractJsonName(ctx, v);
_upb_DefBuilder_Add(ctx, v->full_name,
_upb_DefType_Pack(v, UPB_DEFTYPE_ENUMVAL));
bool ok = _upb_EnumDef_Insert(e, v, ctx->arena);
if (!ok) _upb_DefBuilder_OomErr(ctx);
_upb_EnumDef_Insert(ctx, e, v);
}
// Allocate and initialize an array of |n| enum value defs owned by |e|.

View file

@ -10,6 +10,8 @@
#ifndef UPB_REFLECTION_ENUM_VALUE_DEF_H_
#define UPB_REFLECTION_ENUM_VALUE_DEF_H_
#include <stdint.h>
#include "upb/reflection/common.h"
#include "upb/reflection/descriptor_bootstrap.h"
@ -24,6 +26,7 @@ const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v);
const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v);
bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v);
uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v);
UPB_API const char* upb_EnumValueDef_JsonName(const upb_EnumValueDef* v);
UPB_API const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v);
UPB_API int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v);
const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(

View file

@ -21,7 +21,8 @@ extern "C" {
#endif
upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i);
bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a);
void _upb_EnumDef_Insert(upb_DefBuilder* ctx, upb_EnumDef* e,
upb_EnumValueDef* v);
const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e);
// Allocate and initialize an array of |n| enum defs.

View file

@ -0,0 +1,19 @@
#ifndef GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__
#define GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__
// IWYU pragma: begin_exports
#if defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0
// This header is checked in.
#include "upb/reflection/stage0/google/protobuf/json_enumvalue_options.upb.h"
#elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 1
// This header is generated at build time by the bootstrapping process.
#include "upb/reflection/stage1/google/protobuf/json_enumvalue_options.upb.h"
#else
// This is the normal header, generated by upb_c_proto_library().
#include "google/protobuf/json_enumvalue_options.upb.h"
#endif
// IWYU pragma: end_exports
#endif // GOOGLE_UPB_UPB_REFLECTION_JSON_ENUMVALUE_OPTIONS_BOOTSTRAP_H__

View file

@ -389,5 +389,77 @@ TEST(ReflectionTest, ZeroWeakDependencyIndexWithNoDeps) {
EXPECT_THAT(std::string(status.message()), HasSubstr("out of range"));
}
// Sets (pb.enumvalue.json).string option (extension field 998) on
// EnumValueOptions.
static void SetCustomJsonOption(google::protobuf::EnumValueOptions* options,
absl::string_view json_name) {
// Wire format for JsonEnumValueOptions { string string = 1 }:
// Field 1 (string, length-delimited): tag = (1 << 3) | 2 = 0x0a.
std::string payload;
payload.push_back('\x0a');
payload.push_back(static_cast<char>(json_name.size()));
payload.append(json_name);
// Field 998 is extension (pb.enumvalue.json) on EnumValueOptions.
options->mutable_unknown_fields()->AddLengthDelimited(998, payload);
}
struct TestEnumValueSpec {
std::string name;
int number;
std::string json_name;
};
static absl::StatusOr<upb::DefPool> LoadEnumDescriptorWithValues(
absl::Span<const TestEnumValueSpec> values) {
google::protobuf::FileDescriptorProto file_proto;
file_proto.set_name("test.proto");
file_proto.set_syntax("editions");
file_proto.set_edition(google::protobuf::EDITION_2026);
google::protobuf::EnumDescriptorProto* enum_proto = file_proto.add_enum_type();
enum_proto->set_name("TestEnum");
for (const TestEnumValueSpec& v : values) {
google::protobuf::EnumValueDescriptorProto* val_proto = enum_proto->add_value();
val_proto->set_name(v.name);
val_proto->set_number(v.number);
if (!v.json_name.empty()) {
SetCustomJsonOption(val_proto->mutable_options(), v.json_name);
}
}
google::protobuf::FileDescriptorSet set;
*set.add_file() = file_proto;
return LoadDescriptorSetFromProto(set);
}
TEST(ReflectionTest, EnumCustomJsonNameConflictDifferentNumberFails) {
// Two enum values with DIFFERENT numbers (1 and 2) sharing the same custom
// JSON name must fail descriptor validation.
absl::Status status =
LoadEnumDescriptorWithValues({
{"VAL_ZERO", 0, ""},
{"VAL_A", 1, "custom_name"},
{"VAL_B", 2, "custom_name"},
})
.status();
EXPECT_FALSE(status.ok());
EXPECT_THAT(std::string(status.message()),
HasSubstr("duplicate custom json_name (custom_name) in enum"));
}
TEST(ReflectionTest, EnumCustomJsonNameAliasedSameNumberSucceeds) {
// Two aliased enum values with the SAME number (1 and 1) sharing the same
// custom JSON name must succeed descriptor validation.
absl::Status status =
LoadEnumDescriptorWithValues({
{"VAL_ZERO", 0, ""},
{"VAL_A", 1, "custom_name"},
{"VAL_B", 1, "custom_name"},
})
.status();
EXPECT_TRUE(status.ok()) << status.message();
}
} // namespace
} // namespace upb_test

View file

@ -2,13 +2,13 @@
#include "upb/generated_code_support.h"
#include "upb/reflection/descriptor_bootstrap.h"
static upb_Arena* upb_BootstrapArena() {
static upb_Arena* upb_BootstrapArena(void) {
static upb_Arena* arena = NULL;
if (!arena) arena = upb_Arena_New();
return arena;
}
const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init() {
const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$PG";
if (mini_table) return mini_table;
@ -32,7 +32,7 @@ const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init() {
const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$11EGGGG33<<1a4E";
if (mini_table) return mini_table;
@ -104,7 +104,7 @@ const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__DescriptorProto_msg_init() {
const upb_MiniTable* google__protobuf__DescriptorProto_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$1GGGGG3GGE4";
if (mini_table) return mini_table;
@ -192,7 +192,7 @@ const upb_MiniTable* google__protobuf__DescriptorProto_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init() {
const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$((3";
if (mini_table) return mini_table;
@ -216,7 +216,7 @@ const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init(
return mini_table;
}
const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init() {
const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$((";
if (mini_table) return mini_table;
@ -232,7 +232,7 @@ const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init()
return mini_table;
}
const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init() {
const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$PaG4n`3t|G";
if (mini_table) return mini_table;
@ -280,7 +280,7 @@ const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_init() {
const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$(11a//";
if (mini_table) return mini_table;
@ -296,7 +296,7 @@ const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_in
return mini_table;
}
const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init() {
const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$11(44113(1f/";
if (mini_table) return mini_table;
@ -336,7 +336,7 @@ const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init() {
const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$13";
if (mini_table) return mini_table;
@ -360,7 +360,7 @@ const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init() {
const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$1G3GE4";
if (mini_table) return mini_table;
@ -408,7 +408,7 @@ const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init() {
const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$((";
if (mini_table) return mini_table;
@ -424,7 +424,7 @@ const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_ms
return mini_table;
}
const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init() {
const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$1(3";
if (mini_table) return mini_table;
@ -448,7 +448,7 @@ const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init() {
const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$1G3";
if (mini_table) return mini_table;
@ -480,7 +480,7 @@ const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init() {
const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$1113//";
if (mini_table) return mini_table;
@ -504,7 +504,7 @@ const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__FileOptions_msg_init() {
const upb_MiniTable* google__protobuf__FileOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$P1f14/1d///a/b/c/c/d11a111b11d3t|G";
if (mini_table) return mini_table;
@ -544,7 +544,7 @@ const upb_MiniTable* google__protobuf__FileOptions_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__MessageOptions_msg_init() {
const upb_MiniTable* google__protobuf__MessageOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$P///c/c/3z}G";
if (mini_table) return mini_table;
@ -576,7 +576,7 @@ const upb_MiniTable* google__protobuf__MessageOptions_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__FieldOptions_msg_init() {
const upb_MiniTable* google__protobuf__FieldOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$P4//a/4c/d//4aHG33p}G";
if (mini_table) return mini_table;
@ -656,7 +656,7 @@ const upb_MiniTable* google__protobuf__FieldOptions_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init() {
const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$a14";
if (mini_table) return mini_table;
@ -680,7 +680,7 @@ const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init() {
const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$44141";
if (mini_table) return mini_table;
@ -720,7 +720,7 @@ const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__OneofOptions_msg_init() {
const upb_MiniTable* google__protobuf__OneofOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$P3e~G";
if (mini_table) return mini_table;
@ -752,7 +752,7 @@ const upb_MiniTable* google__protobuf__OneofOptions_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__EnumOptions_msg_init() {
const upb_MiniTable* google__protobuf__EnumOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$Pa//b/3_~G";
if (mini_table) return mini_table;
@ -784,7 +784,7 @@ const upb_MiniTable* google__protobuf__EnumOptions_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init() {
const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$P/3/3b~G";
if (mini_table) return mini_table;
@ -824,7 +824,7 @@ const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__ServiceOptions_msg_init() {
const upb_MiniTable* google__protobuf__ServiceOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$P``/3d}G";
if (mini_table) return mini_table;
@ -856,7 +856,7 @@ const upb_MiniTable* google__protobuf__ServiceOptions_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__MethodOptions_msg_init() {
const upb_MiniTable* google__protobuf__MethodOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$P``/43c}G";
if (mini_table) return mini_table;
@ -896,7 +896,7 @@ const upb_MiniTable* google__protobuf__MethodOptions_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init() {
const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$aG1,+ 01";
if (mini_table) return mini_table;
@ -920,7 +920,7 @@ const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init() {
const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$1N/N";
if (mini_table) return mini_table;
@ -936,7 +936,7 @@ const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init()
return mini_table;
}
const upb_MiniTable* google__protobuf__FeatureSet_msg_init() {
const upb_MiniTable* google__protobuf__FeatureSet_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$P444444444";
if (mini_table) return mini_table;
@ -1024,7 +1024,7 @@ const upb_MiniTable* google__protobuf__FeatureSet_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__FeatureSet__VisibilityFeature_msg_init() {
const upb_MiniTable* google__protobuf__FeatureSet__VisibilityFeature_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$";
if (mini_table) return mini_table;
@ -1040,7 +1040,7 @@ const upb_MiniTable* google__protobuf__FeatureSet__VisibilityFeature_msg_init()
return mini_table;
}
const upb_MiniTable* google__protobuf__FeatureSet__ProtoLimitsFeature_msg_init() {
const upb_MiniTable* google__protobuf__FeatureSet__ProtoLimitsFeature_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$";
if (mini_table) return mini_table;
@ -1056,7 +1056,7 @@ const upb_MiniTable* google__protobuf__FeatureSet__ProtoLimitsFeature_msg_init()
return mini_table;
}
const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init() {
const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$Gb44";
if (mini_table) return mini_table;
@ -1096,7 +1096,7 @@ const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init() {
const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$b433";
if (mini_table) return mini_table;
@ -1136,7 +1136,7 @@ const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefa
return mini_table;
}
const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init() {
const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$PG";
if (mini_table) return mini_table;
@ -1160,7 +1160,7 @@ const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init() {
const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$N<<11aE";
if (mini_table) return mini_table;
@ -1176,7 +1176,7 @@ const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init() {
const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$G";
if (mini_table) return mini_table;
@ -1200,7 +1200,7 @@ const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init() {
const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$N<1((4";
if (mini_table) return mini_table;
@ -1224,7 +1224,7 @@ const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init()
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__Edition_enum_init() {
const upb_MiniTableEnum* google__protobuf__Edition_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)~z!|aAcxg!h{va)|i}{~~`!";
if (mini_table) return mini_table;
@ -1234,7 +1234,7 @@ const upb_MiniTableEnum* google__protobuf__Edition_enum_init() {
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__ExtensionRangeOptions__VerificationState_enum_init() {
const upb_MiniTableEnum* google__protobuf__ExtensionRangeOptions__VerificationState_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!$";
if (mini_table) return mini_table;
@ -1244,7 +1244,7 @@ const upb_MiniTableEnum* google__protobuf__ExtensionRangeOptions__VerificationSt
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FeatureSet__EnforceNamingStyle_enum_init() {
const upb_MiniTableEnum* google__protobuf__FeatureSet__EnforceNamingStyle_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!1";
if (mini_table) return mini_table;
@ -1254,7 +1254,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__EnforceNamingStyle_enum_i
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FeatureSet__EnumType_enum_init() {
const upb_MiniTableEnum* google__protobuf__FeatureSet__EnumType_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1264,7 +1264,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__EnumType_enum_init() {
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FeatureSet__FieldPresence_enum_init() {
const upb_MiniTableEnum* google__protobuf__FeatureSet__FieldPresence_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!1";
if (mini_table) return mini_table;
@ -1274,7 +1274,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__FieldPresence_enum_init()
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FeatureSet__JsonFormat_enum_init() {
const upb_MiniTableEnum* google__protobuf__FeatureSet__JsonFormat_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1284,7 +1284,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__JsonFormat_enum_init() {
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FeatureSet__MessageEncoding_enum_init() {
const upb_MiniTableEnum* google__protobuf__FeatureSet__MessageEncoding_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1294,7 +1294,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__MessageEncoding_enum_init
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FeatureSet__ProtoLimitsFeature__EnforceProtoLimits_enum_init() {
const upb_MiniTableEnum* google__protobuf__FeatureSet__ProtoLimitsFeature__EnforceProtoLimits_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1304,7 +1304,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__ProtoLimitsFeature__Enfor
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init() {
const upb_MiniTableEnum* google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1314,7 +1314,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__RepeatedFieldEncoding_enu
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FeatureSet__Utf8Validation_enum_init() {
const upb_MiniTableEnum* google__protobuf__FeatureSet__Utf8Validation_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!/";
if (mini_table) return mini_table;
@ -1324,7 +1324,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__Utf8Validation_enum_init(
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FeatureSet__VisibilityFeature__DefaultSymbolVisibility_enum_init() {
const upb_MiniTableEnum* google__protobuf__FeatureSet__VisibilityFeature__DefaultSymbolVisibility_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!A";
if (mini_table) return mini_table;
@ -1334,7 +1334,7 @@ const upb_MiniTableEnum* google__protobuf__FeatureSet__VisibilityFeature__Defaul
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Label_enum_init() {
const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Label_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!0";
if (mini_table) return mini_table;
@ -1344,7 +1344,7 @@ const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Label_enum_init
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Type_enum_init() {
const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Type_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!@AA1";
if (mini_table) return mini_table;
@ -1354,7 +1354,7 @@ const upb_MiniTableEnum* google__protobuf__FieldDescriptorProto__Type_enum_init(
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FieldOptions__CType_enum_init() {
const upb_MiniTableEnum* google__protobuf__FieldOptions__CType_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1364,7 +1364,7 @@ const upb_MiniTableEnum* google__protobuf__FieldOptions__CType_enum_init() {
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FieldOptions__JSType_enum_init() {
const upb_MiniTableEnum* google__protobuf__FieldOptions__JSType_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1374,7 +1374,7 @@ const upb_MiniTableEnum* google__protobuf__FieldOptions__JSType_enum_init() {
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionRetention_enum_init() {
const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionRetention_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1384,7 +1384,7 @@ const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionRetention_enum_in
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionTargetType_enum_init() {
const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionTargetType_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!AA";
if (mini_table) return mini_table;
@ -1394,7 +1394,7 @@ const upb_MiniTableEnum* google__protobuf__FieldOptions__OptionTargetType_enum_i
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__FileOptions__OptimizeMode_enum_init() {
const upb_MiniTableEnum* google__protobuf__FileOptions__OptimizeMode_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!0";
if (mini_table) return mini_table;
@ -1404,7 +1404,7 @@ const upb_MiniTableEnum* google__protobuf__FileOptions__OptimizeMode_enum_init()
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init() {
const upb_MiniTableEnum* google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1414,7 +1414,7 @@ const upb_MiniTableEnum* google__protobuf__GeneratedCodeInfo__Annotation__Semant
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__MethodOptions__IdempotencyLevel_enum_init() {
const upb_MiniTableEnum* google__protobuf__MethodOptions__IdempotencyLevel_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;
@ -1424,7 +1424,7 @@ const upb_MiniTableEnum* google__protobuf__MethodOptions__IdempotencyLevel_enum_
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__SymbolVisibility_enum_init() {
const upb_MiniTableEnum* google__protobuf__SymbolVisibility_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;

View file

@ -0,0 +1,27 @@
#include <stddef.h>
#include "upb/generated_code_support.h"
#include "upb/reflection/json_enumvalue_options_bootstrap.h"
#include "upb/reflection/descriptor_bootstrap.h"
static upb_Arena* upb_BootstrapArena(void) {
static upb_Arena* arena = NULL;
if (!arena) arena = upb_Arena_New();
return arena;
}
const upb_MiniTable* pb__enumvalue__JsonEnumValueOptions_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$M1";
if (mini_table) return mini_table;
upb_Status status;
mini_table =
upb_MiniTable_Build(mini_descriptor, strlen(mini_descriptor),
upb_BootstrapArena(), &status);
if (!mini_table) {
fprintf(stderr, "Failed to build mini_table for pb__enumvalue__JsonEnumValueOptions_msg_init: %s\n",
upb_Status_ErrorMessage(&status));
abort();
}
return mini_table;
}

View file

@ -0,0 +1,122 @@
/* This file was generated by upb_generator from the input file:
*
* google/protobuf/json_enumvalue_options.proto
*
* Do not edit -- your changes will be discarded when the file is
* regenerated.
* NO CHECKED-IN PROTOBUF GENCODE */
#ifndef GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_
#define GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_
#include "upb/generated_code_support.h"
// Must be last.
#include "upb/port/def.inc"
#ifdef __cplusplus
extern "C" {
#endif
extern const upb_MiniTable* pb__enumvalue__JsonEnumValueOptions_msg_init(void);
extern const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init(void);
typedef struct pb_enumvalue_JsonEnumValueOptions {
upb_Message UPB_PRIVATE(base);
} pb_enumvalue_JsonEnumValueOptions;
struct google_protobuf_EnumValueOptions;
/* pb.enumvalue.JsonEnumValueOptions */
UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_new(upb_Arena* arena) {
return (pb_enumvalue_JsonEnumValueOptions*)_upb_Message_New(pb__enumvalue__JsonEnumValueOptions_msg_init(), arena);
}
UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse(const char* buf, size_t size,
upb_Arena* arena) {
pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena);
if (!ret) return NULL;
if (upb_Decode(buf, size, UPB_UPCAST(ret), pb__enumvalue__JsonEnumValueOptions_msg_init(), NULL, 0,
arena) != kUpb_DecodeStatus_Ok) {
return NULL;
}
return ret;
}
UPB_INLINE pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_JsonEnumValueOptions_parse_ex(
const char* buf, size_t size, const upb_ExtensionRegistry* extreg,
int options, upb_Arena* arena) {
pb_enumvalue_JsonEnumValueOptions* ret = pb_enumvalue_JsonEnumValueOptions_new(arena);
if (!ret) return NULL;
if (upb_Decode(buf, size, UPB_UPCAST(ret), pb__enumvalue__JsonEnumValueOptions_msg_init(), extreg,
options, arena) != kUpb_DecodeStatus_Ok) {
return NULL;
}
return ret;
}
UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize(const pb_enumvalue_JsonEnumValueOptions* msg,
upb_Arena* arena, size_t* len) {
char* ptr;
(void)upb_Encode(UPB_UPCAST(msg), pb__enumvalue__JsonEnumValueOptions_msg_init(), 0, arena, &ptr, len);
return ptr;
}
UPB_INLINE char* pb_enumvalue_JsonEnumValueOptions_serialize_ex(const pb_enumvalue_JsonEnumValueOptions* msg,
int options, upb_Arena* arena,
size_t* len) {
char* ptr;
(void)upb_Encode(UPB_UPCAST(msg), pb__enumvalue__JsonEnumValueOptions_msg_init(), options, arena, &ptr, len);
return ptr;
}
UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_clear_string(pb_enumvalue_JsonEnumValueOptions* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(pb__enumvalue__JsonEnumValueOptions_msg_init(), 1);
upb_Message_ClearBaseField(UPB_UPCAST(msg), &field);
}
UPB_INLINE upb_StringView pb_enumvalue_JsonEnumValueOptions_string(const pb_enumvalue_JsonEnumValueOptions* msg) {
upb_StringView default_val = upb_StringView_FromString("");
upb_StringView ret;
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(pb__enumvalue__JsonEnumValueOptions_msg_init(), 1);
_upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field,
&default_val, &ret);
return ret;
}
UPB_INLINE bool pb_enumvalue_JsonEnumValueOptions_has_string(const pb_enumvalue_JsonEnumValueOptions* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(pb__enumvalue__JsonEnumValueOptions_msg_init(), 1);
return upb_Message_HasBaseField(UPB_UPCAST(msg), &field);
}
UPB_INLINE void pb_enumvalue_JsonEnumValueOptions_set_string(pb_enumvalue_JsonEnumValueOptions* msg, upb_StringView value) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(pb__enumvalue__JsonEnumValueOptions_msg_init(), 1);
upb_Message_SetBaseField((upb_Message*)msg, &field, &value);
}
// In stage0 bootstrapping, extensions are not present.
UPB_INLINE bool pb_enumvalue_has_json(const struct google_protobuf_EnumValueOptions* msg) {
(void)msg;
return false;
}
UPB_INLINE void pb_enumvalue_clear_json(struct google_protobuf_EnumValueOptions* msg) { (void)msg; }
UPB_INLINE const pb_enumvalue_JsonEnumValueOptions*
pb_enumvalue_json(const struct google_protobuf_EnumValueOptions* msg) {
(void)msg;
return NULL;
}
UPB_INLINE void pb_enumvalue_set_json(struct google_protobuf_EnumValueOptions* msg,
const pb_enumvalue_JsonEnumValueOptions* val,
upb_Arena* arena) {
(void)msg;
(void)val;
(void)arena;
}
UPB_INLINE struct pb_enumvalue_JsonEnumValueOptions* pb_enumvalue_mutable_json(
struct google_protobuf_EnumValueOptions* msg, upb_Arena* arena) {
(void)msg;
(void)arena;
return NULL;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "upb/port/undef.inc"
#endif /* GOOGLE_PROTOBUF_JSON_ENUMVALUE_OPTIONS_PROTO_UPB_H__UPB_H_ */

View file

@ -2,6 +2,10 @@
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
load("@rules_cc//cc:defs.bzl", "cc_library")
load(
"//upb/bazel:copts.bzl",
"UPB_DEFAULT_COPTS",
)
load(
"//upb/bazel:upb_minitable_proto_library.bzl",
"upb_minitable_proto_library",
@ -15,6 +19,11 @@ load(
"staleness_test",
)
def _c_library_with_default_copts(**kwargs):
cc_kwargs = dict(kwargs)
cc_kwargs["copts"] = UPB_DEFAULT_COPTS + cc_kwargs.get("copts", [])
cc_library(**cc_kwargs)
_stages = ["_stage0", "_stage1", ""]
_protoc = "//src/google/protobuf/compiler/release:protoc_minimal"
@ -105,11 +114,11 @@ def _generated_hdrs_and_srcs(protos, stage, generator):
ret += _generated_files(protos, stage, generator, "c")
return ret
def _stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix):
def _stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix, third_party_dir = "3rd_party"):
native.genrule(
name = name + "_generate_bootstrap",
srcs = src_rules,
outs = ["bootstrap_generated_sources/" + f.replace("third_party", "3rd_party") for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb")],
outs = ["bootstrap_generated_sources/" + f.replace("third_party", third_party_dir) for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb")],
tools = [_protoc, _upbc("upb", 0)],
cmd =
"$(location " + _protoc + ") " +
@ -117,15 +126,18 @@ def _stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix):
"--plugin=protoc-gen-upb=$(location " + _upbc("upb", 0) + ") " +
"--upb_out=bootstrap_stage=0:$(@D)/bootstrap_generated_sources/stage0 " +
" ".join(src_files) +
"; rm -rf $(@D)/bootstrap_generated_sources/stage0/3rd_party" +
"; if [ -e $(@D)/bootstrap_generated_sources/stage0/third_party ]; then mv $(@D)/bootstrap_generated_sources/stage0/third_party $(@D)/bootstrap_generated_sources/stage0/3rd_party; fi",
"; rm -rf $(@D)/bootstrap_generated_sources/stage0/" + third_party_dir +
"; if [ -e $(@D)/bootstrap_generated_sources/stage0/third_party ]; then mv $(@D)/bootstrap_generated_sources/stage0/third_party $(@D)/bootstrap_generated_sources/stage0/" + third_party_dir + "; fi",
)
staleness_test(
name = name + "_stage0_staleness_test",
outs = [f.replace("third_party", "3rd_party") for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb")],
outs = [f.replace("third_party", third_party_dir) for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb")],
generated_pattern = "bootstrap_generated_sources/%s",
target_files = native.glob(["stage0/**"]),
target_files = [
f.replace("third_party", third_party_dir)
for f in _generated_hdrs_and_srcs(src_files, "stage0", "upb")
],
# To avoid skew problems for descriptor.proto/plugin.proto between
# GitHub repos. It's not critical that the checked-in protos are up to
# date for every change, they just needs to be complete enough to have
@ -194,6 +206,7 @@ def bootstrap_upb_proto_library(
proto_lib_deps,
deps = [],
strip_prefix = "",
third_party_dir = "3rd_party",
**kwargs):
"""A version of upb_proto_library() that is augmented to allow for bootstrapping the compiler.
@ -211,13 +224,15 @@ def bootstrap_upb_proto_library(
not bootstrapping.
deps: other bootstrap_upb_proto_library() rules that this one depends on.
strip_prefix: Prefix that should be stripped from file names.
third_party_dir: Subdirectory name to use instead of "third_party" for stage0 checked-in
files to comply with repository structure rules.
**kwargs: Other arguments that will be passed through to cc_library(), genrule(), and
upb_proto_library().
"""
_stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix)
_stage0_proto_staleness_test(name, src_files, src_rules, strip_prefix, third_party_dir)
# stage0 uses checked-in protos, and has no MiniTable.
cc_library(
_c_library_with_default_copts(
name = name + "_stage0",
srcs = _generated_hdrs_and_srcs(src_files, "stage0", "upb"),
hdrs = [bootstrap_hdr],
@ -233,7 +248,7 @@ def bootstrap_upb_proto_library(
# Generate stage1 protos (C API and MiniTables) using stage0 compiler.
_generate_stage1_proto(name, src_files, src_rules, "upb", kwargs)
_generate_stage1_proto(name, src_files, src_rules, "upb_minitable", kwargs)
cc_library(
_c_library_with_default_copts(
name = name + "_minitable_stage1",
srcs = _generated_files(src_files, "stage1", "upb_minitable", "c"),
hdrs = _generated_files(src_files, "stage1", "upb_minitable", "h"),
@ -244,7 +259,7 @@ def bootstrap_upb_proto_library(
] + [dep + "_minitable_stage1" for dep in deps],
**kwargs
)
cc_library(
_c_library_with_default_copts(
name = name + "_stage1",
srcs = _generated_files(src_files, "stage1", "upb", "h"),
hdrs = [bootstrap_hdr],
@ -263,7 +278,7 @@ def bootstrap_upb_proto_library(
deps = proto_lib_deps,
**kwargs
)
cc_library(
_c_library_with_default_copts(
name = name,
hdrs = [bootstrap_hdr],
deps = [name + "_upb_proto"],

View file

@ -313,6 +313,72 @@ std::string GetFieldRep(const DefPoolPair& pools, upb::FieldDefPtr field) {
}
void GenerateExtensionInHeader(Context& c, upb::FieldDefPtr ext) {
if (c.options().bootstrap_stage == 0) {
c.Emit(
{
{"ident_base", ExtensionIdentBase(ext)},
{"name", ext.name()},
{"ctype", MessageType(ext.containing_type())},
},
R"cc(
// In stage0 bootstrapping, extensions are not present.
UPB_INLINE bool $ident_base$_has_$name$(const struct $ctype$* msg) {
(void)msg;
return false;
}
UPB_INLINE void $ident_base$_clear_$name$(struct $ctype$* msg) { (void)msg; }
)cc");
if (ext.IsSequence()) {
// Repeated extensions are accessed via generic upb_Array and
// upb_Message_GetExtension APIs.
} else {
c.Emit(
{
{"ctype_const", CTypeConst(ext)},
{"ident_base", ExtensionIdentBase(ext)},
{"name", ext.name()},
{"ctype", MessageType(ext.containing_type())},
{"default", FieldDefault(ext)},
},
R"cc(
UPB_INLINE $ctype_const$
$ident_base$_$name$(const struct $ctype$* msg) {
(void)msg;
return $default$;
}
UPB_INLINE void $ident_base$_set_$name$(struct $ctype$* msg,
$ctype_const$ val,
upb_Arena* arena) {
(void)msg;
(void)val;
(void)arena;
}
)cc");
if (ext.IsSubMessage()) {
c.Emit(
{
{"sub_ctype", MessageType(ext.message_type())},
{"ident_base", ExtensionIdentBase(ext)},
{"name", ext.name()},
{"ctype", MessageType(ext.containing_type())},
},
R"cc(
UPB_INLINE struct $sub_ctype$* $ident_base$_mutable_$name$(
struct $ctype$* msg, upb_Arena* arena) {
(void)msg;
(void)arena;
return NULL;
}
)cc");
}
}
return;
}
c.Emit(
{
{"ident_base", ExtensionIdentBase(ext)},
@ -331,7 +397,8 @@ void GenerateExtensionInHeader(Context& c, upb::FieldDefPtr ext) {
)cc");
if (ext.IsSequence()) {
// TODO: We need generated accessors for repeated extensions.
// Repeated extensions are accessed via generic upb_Array and
// upb_Message_GetExtension APIs.
} else {
c.Emit(
{
@ -1206,7 +1273,7 @@ void WriteMessageMiniDescriptorInitializer(Context& c, upb::MessageDefPtr msg) {
{"mini_descriptor", msg.MiniDescriptorEncode()},
{"resolve_calls", [&] { WriteResolveCalls(c, msg); }}},
R"cc(
const upb_MiniTable* $name$() {
const upb_MiniTable* $name$(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$mini_descriptor$";
if (mini_table) return mini_table;
@ -1229,7 +1296,7 @@ void WriteEnumMiniDescriptorInitializer(Context& c, upb::EnumDefPtr enum_def) {
c.Emit({{"name", MiniTableEnumVarName(enum_def.full_name())},
{"mini_descriptor", enum_def.MiniDescriptorEncode()}},
R"cc(
const upb_MiniTableEnum* $name$() {
const upb_MiniTableEnum* $name$(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "$mini_descriptor$";
if (mini_table) return mini_table;
@ -1262,7 +1329,7 @@ void WriteMiniDescriptorSource(Context& c, upb::FileDefPtr file) {
c.Emit(
R"cc(
static upb_Arena* upb_BootstrapArena() {
static upb_Arena* upb_BootstrapArena(void) {
static upb_Arena* arena = NULL;
if (!arena) arena = upb_Arena_New();
return arena;

View file

@ -18,7 +18,14 @@ namespace generator {
std::string CApiHeaderFilename(absl::string_view proto_filename,
bool bootstrap) {
if (bootstrap) {
if (IsDescriptorProto(proto_filename)) {
if (proto_filename == "third_party/protobuf/json_enumvalue_options.proto" ||
proto_filename == "google/protobuf/json_enumvalue_options.proto" ||
proto_filename == "src/google/protobuf/json_enumvalue_options.proto") {
return "upb/reflection/"
"json_enumvalue_options_bootstrap.h";
} else if (proto_filename == "net/proto2/proto/descriptor.proto" ||
proto_filename == "google/protobuf/descriptor.proto" ||
proto_filename == "src/google/protobuf/descriptor.proto") {
return "upb/reflection/descriptor_bootstrap.h";
} else {
return "upb_generator/plugin_bootstrap.h";

View file

@ -31,9 +31,13 @@ std::string ToPreproc(absl::string_view str) {
} // namespace
bool IsDescriptorProto(absl::string_view filename) {
bool IsReflectionBootstrapProto(absl::string_view filename) {
return filename == "net/proto2/proto/descriptor.proto" ||
filename == "google/protobuf/descriptor.proto";
filename == "google/protobuf/descriptor.proto" ||
filename == "src/google/protobuf/descriptor.proto" ||
filename == "third_party/protobuf/json_enumvalue_options.proto" ||
filename == "google/protobuf/json_enumvalue_options.proto" ||
filename == "src/google/protobuf/json_enumvalue_options.proto";
}
std::string StripExtension(absl::string_view fname) {

View file

@ -18,7 +18,7 @@
namespace upb {
namespace generator {
bool IsDescriptorProto(absl::string_view filename);
bool IsReflectionBootstrapProto(absl::string_view filename);
std::string StripExtension(absl::string_view fname);
std::string IncludeGuard(absl::string_view filename);
std::string FileWarning(absl::string_view filename);

View file

@ -458,9 +458,15 @@ void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file,
}
}
std::string messages_layout =
absl::StrCat("messages_layout_", FileVarName(file));
std::string enums_layout = absl::StrCat("enums_layout_", FileVarName(file));
std::string extensions_layout =
absl::StrCat("extensions_layout_", FileVarName(file));
// Messages.
if (!messages.empty()) {
output("static const upb_MiniTable *$0[$1] = {\n", kMessagesInit,
output("static const upb_MiniTable *$0[$1] = {\n", messages_layout,
messages.size());
for (auto message : messages) {
output(" &$0,\n", MessageVarName(message));
@ -471,7 +477,7 @@ void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file,
// Enums.
if (!enums.empty()) {
output("static const upb_MiniTableEnum *$0[$1] = {\n", kEnumsInit,
output("static const upb_MiniTableEnum *$0[$1] = {\n", enums_layout,
enums.size());
for (const auto e : enums) {
output(" &$0,\n", EnumVarName(e));
@ -485,7 +491,7 @@ void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file,
output(
"\n"
"static const upb_MiniTableExtension *$0[$1] = {\n",
kExtensionsInit, extensions.size());
extensions_layout, extensions.size());
for (auto ext : extensions) {
output(" &$0_obj,\n", ExtensionVarName(ext));
@ -503,9 +509,9 @@ void WriteMiniTableSource(const DefPoolPair& pools, upb::FileDefPtr file,
}
output("const upb_MiniTableFile $0 = {\n", FileVarName(file));
output(" $0,\n", messages.empty() ? "NULL" : kMessagesInit);
output(" $0,\n", enums.empty() ? "NULL" : kEnumsInit);
output(" $0,\n", extensions.empty() ? "NULL" : kExtensionsInit);
output(" $0,\n", messages.empty() ? "NULL" : messages_layout);
output(" $0,\n", enums.empty() ? "NULL" : enums_layout);
output(" $0,\n", extensions.empty() ? "NULL" : extensions_layout);
output(" $0,\n", messages.size());
output(" $0,\n", enums.size());
output(" $0,\n", extensions.size());

View file

@ -28,7 +28,7 @@ std::string MiniTableHeaderFilename(absl::string_view proto_filename,
bool bootstrap) {
std::string base;
if (bootstrap) {
if (IsDescriptorProto(proto_filename)) {
if (IsReflectionBootstrapProto(proto_filename)) {
base = "upb/reflection/stage1/";
} else {
base = "upb_generator/stage1/";

View file

@ -89,13 +89,15 @@ void WriteDescriptor(upb::FileDefPtr file, Context& ctx) {
file_proto, arena.ptr(), &serialized_size);
absl::string_view file_data(serialized, serialized_size);
ctx.Emit({{"serialized_size", file_data.size()},
{"contents", [&] { WriteStringArray(file_data, ctx); }}},
R"cc(
static const char descriptor[$serialized_size$] = {
$contents$,
};
)cc");
ctx.Emit(
{{"serialized_size", file_data.size()},
{"defpool_init_name", ReflectionFileSymbol(file.name())},
{"contents", [&] { WriteStringArray(file_data, ctx); }}},
R"cc(
static const char descriptor_$defpool_init_name$[$serialized_size$] = {
$contents$,
};
)cc");
ctx.Emit("\n");
}
@ -112,9 +114,10 @@ void WriteDependencies(upb::FileDefPtr file, Context& ctx) {
};
ctx.Emit({{"dep_count", file.dependency_count() + 1},
{"defpool_init_name", ReflectionFileSymbol(file.name())},
{google::protobuf::io::Printer::Sub("deps", write_deps).WithSuffix(",")}},
R"cc(
static _upb_DefPool_Init *deps[$dep_count$] = {
static _upb_DefPool_Init* deps_$defpool_init_name$[$dep_count$] = {
$deps$,
NULL,
};
@ -131,10 +134,11 @@ void WriteDefPoolInitStruct(upb::FileDefPtr file, Context& ctx) {
},
R"cc(
_upb_DefPool_Init $defpool_init_name$ = {
deps,
deps_$defpool_init_name$,
&$mini_table_file_var_name$,
"$file_name$",
UPB_STRINGVIEW_INIT(descriptor, sizeof(descriptor)),
UPB_STRINGVIEW_INIT(descriptor_$defpool_init_name$,
sizeof(descriptor_$defpool_init_name$)),
};
)cc");
}

View file

@ -3,13 +3,13 @@
#include "upb_generator/plugin_bootstrap.h"
#include "upb/reflection/descriptor_bootstrap.h"
static upb_Arena* upb_BootstrapArena() {
static upb_Arena* upb_BootstrapArena(void) {
static upb_Arena* arena = NULL;
if (!arena) arena = upb_Arena_New();
return arena;
}
const upb_MiniTable* google__protobuf__compiler__Version_msg_init() {
const upb_MiniTable* google__protobuf__compiler__Version_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$(((1";
if (mini_table) return mini_table;
@ -25,7 +25,7 @@ const upb_MiniTable* google__protobuf__compiler__Version_msg_init() {
return mini_table;
}
const upb_MiniTable* google__protobuf__compiler__CodeGeneratorRequest_msg_init() {
const upb_MiniTable* google__protobuf__compiler__CodeGeneratorRequest_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$E13kGaG";
if (mini_table) return mini_table;
@ -65,7 +65,7 @@ const upb_MiniTable* google__protobuf__compiler__CodeGeneratorRequest_msg_init()
return mini_table;
}
const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse_msg_init() {
const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$1,((jG";
if (mini_table) return mini_table;
@ -89,7 +89,7 @@ const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse_msg_init(
return mini_table;
}
const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse__File_msg_init() {
const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse__File_msg_init(void) {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$11l13";
if (mini_table) return mini_table;
@ -113,7 +113,7 @@ const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse__File_msg
return mini_table;
}
const upb_MiniTableEnum* google__protobuf__compiler__CodeGeneratorResponse__Feature_enum_init() {
const upb_MiniTableEnum* google__protobuf__compiler__CodeGeneratorResponse__Feature_enum_init(void) {
static const upb_MiniTableEnum* mini_table = NULL;
static const char* mini_descriptor = "!)";
if (mini_table) return mini_table;