File indexing completed on 2025-02-28 10:10:19
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef GOOGLE_PROTOBUF_JSON_INTERNAL_DESCRIPTOR_TRAITS_H__
0009 #define GOOGLE_PROTOBUF_JSON_INTERNAL_DESCRIPTOR_TRAITS_H__
0010
0011 #include <array>
0012 #include <cfloat>
0013 #include <cmath>
0014 #include <cstdint>
0015 #include <cstring>
0016 #include <limits>
0017 #include <string>
0018 #include <utility>
0019
0020 #include "google/protobuf/type.pb.h"
0021 #include "absl/algorithm/container.h"
0022 #include "absl/log/absl_log.h"
0023 #include "absl/status/status.h"
0024 #include "absl/status/statusor.h"
0025 #include "absl/strings/match.h"
0026 #include "absl/strings/str_format.h"
0027 #include "absl/strings/string_view.h"
0028 #include "absl/types/optional.h"
0029 #include "google/protobuf/descriptor.h"
0030 #include "google/protobuf/dynamic_message.h"
0031 #include "google/protobuf/json/internal/lexer.h"
0032 #include "google/protobuf/json/internal/untyped_message.h"
0033 #include "google/protobuf/message.h"
0034 #include "google/protobuf/stubs/status_macros.h"
0035
0036
0037
0038 #include "google/protobuf/port_def.inc"
0039
0040
0041
0042 namespace google {
0043 namespace protobuf {
0044 namespace json_internal {
0045 enum class MessageType {
0046 kNotWellKnown,
0047 kAny,
0048 kWrapper,
0049 kStruct,
0050 kList,
0051 kValue,
0052 kNull,
0053 kTimestamp,
0054 kDuration,
0055 kFieldMask,
0056 };
0057
0058 inline MessageType ClassifyMessage(absl::string_view name) {
0059 constexpr absl::string_view kWellKnownPkg = "google.protobuf.";
0060 if (!absl::StartsWith(name, kWellKnownPkg)) {
0061 return MessageType::kNotWellKnown;
0062 }
0063 name = name.substr(kWellKnownPkg.size());
0064
0065 switch (name.size()) {
0066 case 3:
0067 if (name == "Any") {
0068 return MessageType::kAny;
0069 }
0070 break;
0071 case 5:
0072 if (name == "Value") {
0073 return MessageType::kValue;
0074 }
0075 break;
0076 case 6:
0077 if (name == "Struct") {
0078 return MessageType::kStruct;
0079 }
0080 break;
0081 case 8:
0082 if (name == "Duration") {
0083 return MessageType::kDuration;
0084 }
0085 break;
0086 case 9:
0087 if (name == "BoolValue") {
0088 return MessageType::kWrapper;
0089 }
0090 if (name == "NullValue") {
0091 return MessageType::kNull;
0092 }
0093 if (name == "ListValue") {
0094 return MessageType::kList;
0095 }
0096 if (name == "Timestamp") {
0097 return MessageType::kTimestamp;
0098 }
0099 if (name == "FieldMask") {
0100 return MessageType::kFieldMask;
0101 }
0102 break;
0103 case 10:
0104 if (name == "BytesValue" || name == "FloatValue" ||
0105 name == "Int32Value" || name == "Int64Value") {
0106 return MessageType::kWrapper;
0107 }
0108 break;
0109 case 11:
0110 if (name == "DoubleValue" || name == "StringValue" ||
0111 name == "UInt32Value" || name == "UInt64Value") {
0112 return MessageType::kWrapper;
0113 }
0114 break;
0115 default:
0116 break;
0117 }
0118
0119 return MessageType::kNotWellKnown;
0120 }
0121
0122
0123
0124 template <typename Traits>
0125 using Field = typename Traits::Field;
0126 template <typename Traits>
0127 using Desc = typename Traits::Desc;
0128
0129
0130 struct Proto2Descriptor {
0131
0132
0133
0134
0135
0136 using Desc = Descriptor;
0137
0138
0139
0140
0141 using Field = const FieldDescriptor*;
0142
0143
0144
0145 static absl::string_view TypeName(const Desc& d) { return d.full_name(); }
0146
0147 static absl::optional<Field> FieldByNumber(const Desc& d, int32_t number) {
0148 if (const auto* field = d.FindFieldByNumber(number)) {
0149 return field;
0150 }
0151 return absl::nullopt;
0152 }
0153
0154 static Field MustHaveField(const Desc& d, int32_t number,
0155 JsonLocation::SourceLocation loc =
0156 JsonLocation::SourceLocation::current()) {
0157 auto f = FieldByNumber(d, number);
0158 if (!f.has_value()) {
0159 ABSL_LOG(FATAL)
0160 << absl::StrFormat(
0161 "%s has, by definition, a field numbered %d, but it could not "
0162 "be "
0163 "looked up; this is a bug",
0164 TypeName(d), number);
0165 }
0166 return *f;
0167 }
0168
0169 static absl::optional<Field> FieldByName(const Desc& d,
0170 absl::string_view name) {
0171 if (const auto* field = d.FindFieldByCamelcaseName(name)) {
0172 return field;
0173 }
0174
0175 if (const auto* field = d.FindFieldByName(name)) {
0176 return field;
0177 }
0178
0179 for (int i = 0; i < d.field_count(); ++i) {
0180 const auto* field = d.field(i);
0181 if (field->has_json_name() && field->json_name() == name) {
0182 return field;
0183 }
0184 }
0185
0186 return absl::nullopt;
0187 }
0188
0189 static Field KeyField(const Desc& d) { return d.map_key(); }
0190
0191 static Field ValueField(const Desc& d) { return d.map_value(); }
0192
0193 static size_t FieldCount(const Desc& d) { return d.field_count(); }
0194
0195 static Field FieldByIndex(const Desc& d, size_t idx) { return d.field(idx); }
0196
0197 static absl::optional<Field> ExtensionByName(const Desc& d,
0198 absl::string_view name) {
0199 auto* field = d.file()->pool()->FindExtensionByName(name);
0200 if (field == nullptr) {
0201 return absl::nullopt;
0202 }
0203 return field;
0204 }
0205
0206
0207
0208 static absl::string_view FieldName(Field f) { return f->name(); }
0209 static absl::string_view FieldJsonName(Field f) {
0210 return f->has_json_name() ? f->json_name() : f->camelcase_name();
0211 }
0212 static absl::string_view FieldFullName(Field f) { return f->full_name(); }
0213
0214 static absl::string_view FieldTypeName(Field f) {
0215 if (f->type() == FieldDescriptor::TYPE_MESSAGE) {
0216 return f->message_type()->full_name();
0217 }
0218 if (f->type() == FieldDescriptor::TYPE_ENUM) {
0219 return f->enum_type()->full_name();
0220 }
0221 return "";
0222 }
0223
0224 static FieldDescriptor::Type FieldType(Field f) { return f->type(); }
0225
0226 static int32_t FieldNumber(Field f) { return f->number(); }
0227
0228 static bool Is32Bit(Field f) {
0229 switch (f->cpp_type()) {
0230 case FieldDescriptor::CPPTYPE_UINT32:
0231 case FieldDescriptor::CPPTYPE_INT32:
0232 case FieldDescriptor::CPPTYPE_ENUM:
0233 case FieldDescriptor::CPPTYPE_FLOAT:
0234 return true;
0235 default:
0236 return false;
0237 }
0238 }
0239
0240 static const Desc& ContainingType(Field f) { return *f->containing_type(); }
0241
0242 static bool IsMap(Field f) { return f->is_map(); }
0243
0244 static bool IsRepeated(Field f) { return f->is_repeated(); }
0245
0246 static bool IsExplicitPresence(Field f) { return f->has_presence(); }
0247
0248 static bool IsImplicitPresence(Field f) {
0249 return !f->is_repeated() && !f->has_presence();
0250 }
0251
0252 static bool IsExtension(Field f) { return f->is_extension(); }
0253
0254 static bool IsOneof(Field f) { return f->containing_oneof() != nullptr; }
0255
0256 static absl::StatusOr<int32_t> EnumNumberByName(Field f,
0257 absl::string_view name,
0258 bool case_insensitive) {
0259 if (case_insensitive) {
0260 for (int i = 0; i < f->enum_type()->value_count(); ++i) {
0261 const auto* ev = f->enum_type()->value(i);
0262 if (absl::EqualsIgnoreCase(name, ev->name())) {
0263 return ev->number();
0264 }
0265 }
0266 return absl::InvalidArgumentError(
0267 absl::StrFormat("unknown enum value: '%s'", name));
0268 }
0269
0270 if (const auto* ev = f->enum_type()->FindValueByName(name)) {
0271 return ev->number();
0272 }
0273
0274 return absl::InvalidArgumentError(
0275 absl::StrFormat("unknown enum value: '%s'", name));
0276 }
0277
0278 static absl::StatusOr<std::string> EnumNameByNumber(Field f, int32_t number) {
0279 if (const auto* ev = f->enum_type()->FindValueByNumber(number)) {
0280 return ev->name();
0281 }
0282 return absl::InvalidArgumentError(
0283 absl::StrFormat("unknown enum number: '%d'", number));
0284 }
0285
0286
0287
0288
0289
0290
0291 template <typename F>
0292 static absl::Status WithFieldType(Field f, F body) {
0293 return body(*f->message_type());
0294 }
0295
0296
0297 template <typename F>
0298 static absl::Status WithDynamicType(const Desc& desc,
0299 const std::string& type_url, F body) {
0300 size_t slash = type_url.rfind('/');
0301 if (slash == absl::string_view::npos || slash == 0) {
0302 return absl::InvalidArgumentError(absl::StrCat(
0303 "@type must contain at least one / and a nonempty host; got: ",
0304 type_url));
0305 }
0306 absl::string_view type_name(type_url);
0307 type_name = type_name.substr(slash + 1);
0308
0309 const Descriptor* dyn_desc =
0310 desc.file()->pool()->FindMessageTypeByName(type_name);
0311 if (dyn_desc == nullptr) {
0312 return absl::InvalidArgumentError(
0313 absl::StrFormat("could not find @type '%s'", type_url));
0314 }
0315
0316 return body(*dyn_desc);
0317 }
0318 };
0319
0320
0321
0322
0323 struct Proto3Type {
0324 using Desc = ResolverPool::Message;
0325 using Field = const ResolverPool::Field*;
0326
0327
0328 static absl::string_view TypeName(const Desc& d) { return d.proto().name(); }
0329
0330 static absl::optional<Field> FieldByNumber(const Desc& d, int32_t number) {
0331 const auto* f = d.FindField(number);
0332 return f == nullptr ? absl::nullopt : absl::make_optional(f);
0333 }
0334
0335 static Field MustHaveField(const Desc& d, int32_t number,
0336 JsonLocation::SourceLocation loc =
0337 JsonLocation::SourceLocation::current()) {
0338 auto f = FieldByNumber(d, number);
0339 if (!f.has_value()) {
0340 ABSL_LOG(FATAL)
0341 << absl::StrFormat(
0342 "%s has, by definition, a field numbered %d, but it could not "
0343 "be "
0344 "looked up; this is a bug",
0345 TypeName(d), number);
0346 }
0347 return *f;
0348 }
0349
0350 static absl::optional<Field> FieldByName(const Desc& d,
0351 absl::string_view name) {
0352 const auto* f = d.FindField(name);
0353 return f == nullptr ? absl::nullopt : absl::make_optional(f);
0354 }
0355
0356 static Field KeyField(const Desc& d) { return &d.FieldsByIndex()[0]; }
0357
0358 static Field ValueField(const Desc& d) { return &d.FieldsByIndex()[1]; }
0359
0360 static size_t FieldCount(const Desc& d) { return d.proto().fields_size(); }
0361
0362 static Field FieldByIndex(const Desc& d, size_t idx) {
0363 return &d.FieldsByIndex()[idx];
0364 }
0365
0366 static absl::optional<Field> ExtensionByName(const Desc& d,
0367 absl::string_view name) {
0368
0369
0370 return absl::nullopt;
0371 }
0372
0373
0374
0375 static absl::string_view FieldName(Field f) { return f->proto().name(); }
0376 static absl::string_view FieldJsonName(Field f) {
0377 return f->proto().json_name();
0378 }
0379 static absl::string_view FieldFullName(Field f) { return f->proto().name(); }
0380
0381 static absl::string_view FieldTypeName(Field f) {
0382 absl::string_view url = f->proto().type_url();
0383
0384
0385
0386 size_t slash = url.rfind('/');
0387 return url.substr(slash + 1);
0388 }
0389
0390 static FieldDescriptor::Type FieldType(Field f) {
0391
0392
0393 return static_cast<FieldDescriptor::Type>(f->proto().kind());
0394 }
0395
0396 static int32_t FieldNumber(Field f) { return f->proto().number(); }
0397
0398 static bool Is32Bit(Field f) {
0399 switch (f->proto().kind()) {
0400 case google::protobuf::Field::TYPE_INT32:
0401 case google::protobuf::Field::TYPE_SINT32:
0402 case google::protobuf::Field::TYPE_UINT32:
0403 case google::protobuf::Field::TYPE_FIXED32:
0404 case google::protobuf::Field::TYPE_SFIXED32:
0405 case google::protobuf::Field::TYPE_FLOAT:
0406 return true;
0407 default:
0408 return false;
0409 }
0410 }
0411
0412 static const Desc& ContainingType(Field f) { return f->parent(); }
0413 static bool IsMap(Field f) {
0414 if (f->proto().kind() != google::protobuf::Field::TYPE_MESSAGE) {
0415 return false;
0416 }
0417
0418 bool value = false;
0419 (void)WithFieldType(f, [&value](const Desc& desc) {
0420 value = absl::c_any_of(desc.proto().options(), [&](auto& option) {
0421 return option.name() == "map_entry";
0422 });
0423 return absl::OkStatus();
0424 });
0425 return value;
0426 }
0427
0428 static bool IsRepeated(Field f) {
0429 return f->proto().cardinality() ==
0430 google::protobuf::Field::CARDINALITY_REPEATED;
0431 }
0432
0433 static bool IsExplicitPresence(Field f) {
0434
0435
0436
0437
0438
0439
0440 if (f->parent().proto().syntax() == google::protobuf::SYNTAX_PROTO3) {
0441 return f->proto().oneof_index() != 0 ||
0442 (f->proto().kind() == google::protobuf::Field::TYPE_MESSAGE &&
0443 !IsRepeated(f));
0444 }
0445
0446 return f->proto().cardinality() ==
0447 google::protobuf::Field::CARDINALITY_OPTIONAL ||
0448 google::protobuf::Field::CARDINALITY_REQUIRED;
0449 }
0450
0451 static bool IsImplicitPresence(Field f) {
0452 return !IsRepeated(f) && !IsExplicitPresence(f);
0453 }
0454
0455 static bool IsExtension(Field f) { return false; }
0456
0457 static bool IsOneof(Field f) { return f->proto().oneof_index() != 0; }
0458
0459 static absl::StatusOr<int32_t> EnumNumberByName(Field f,
0460 absl::string_view name,
0461 bool case_insensitive) {
0462 auto e = f->EnumType();
0463 RETURN_IF_ERROR(e.status());
0464
0465 for (const auto& ev : (**e).proto().enumvalue()) {
0466 if (case_insensitive) {
0467
0468 if (absl::EqualsIgnoreCase(ev.name(), name)) {
0469 return ev.number();
0470 }
0471 } else if (ev.name() == name) {
0472 return ev.number();
0473 }
0474 }
0475 return absl::InvalidArgumentError(
0476 absl::StrFormat("unknown enum value: '%s'", name));
0477 }
0478
0479 static absl::StatusOr<std::string> EnumNameByNumber(Field f, int32_t number) {
0480 auto e = f->EnumType();
0481 RETURN_IF_ERROR(e.status());
0482
0483 for (const auto& ev : (**e).proto().enumvalue()) {
0484 if (ev.number() == number) {
0485 return ev.name();
0486 }
0487 }
0488 return absl::InvalidArgumentError(
0489 absl::StrFormat("unknown enum number: '%d'", number));
0490 }
0491
0492 template <typename F>
0493 static absl::Status WithFieldType(Field f, F body) {
0494 auto m = f->MessageType();
0495 RETURN_IF_ERROR(m.status());
0496 return body(**m);
0497 }
0498
0499 template <typename F>
0500 static absl::Status WithDynamicType(const Desc& desc,
0501 const std::string& type_url, F body) {
0502 auto dyn_desc = desc.pool()->FindMessage(type_url);
0503 RETURN_IF_ERROR(dyn_desc.status());
0504 return body(**dyn_desc);
0505 }
0506 };
0507 }
0508 }
0509 }
0510
0511 #include "google/protobuf/port_undef.inc"
0512 #endif