Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-28 10:10:19

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2008 Google Inc.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
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 // Must be included last.
0038 #include "google/protobuf/port_def.inc"
0039 
0040 // Traits for working with descriptor.proto and type.proto generically.
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 // Helper alias templates to avoid needing to write `typename` in function
0123 // signatures.
0124 template <typename Traits>
0125 using Field = typename Traits::Field;
0126 template <typename Traits>
0127 using Desc = typename Traits::Desc;
0128 
0129 // Traits for proto2-ish descriptors.
0130 struct Proto2Descriptor {
0131   // A descriptor for introspecting the fields of a message type.
0132   //
0133   // Desc<Traits> needs to be handled through a const Desc& in most (but not
0134   // all, in the case of ResolverTraits) cases, so we do not include the const*
0135   // annotation on this type.
0136   using Desc = Descriptor;
0137 
0138   // A field descriptor for introspecting a single field.
0139   //
0140   // Field<Traits> is always copyable, so this can be a pointer directly.
0141   using Field = const FieldDescriptor*;
0142 
0143   /// Functions for working with descriptors. ///
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   /// Functions for introspecting fields. ///
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   // Looks up the corresponding Desc for `f`'s type, if there is one, and
0287   // calls `body` with it.
0288   //
0289   // This needs to have this funny callback API since whether or not the
0290   // Descriptor equivalent is an owning type depends on the trait.
0291   template <typename F>
0292   static absl::Status WithFieldType(Field f, F body) {
0293     return body(*f->message_type());
0294   }
0295 
0296   // Like WithFieldType, but using dynamic lookup by type URL.
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 // Traits for proto3-ish deserialization.
0321 //
0322 // See Proto2Descriptor for API docs.
0323 struct Proto3Type {
0324   using Desc = ResolverPool::Message;
0325   using Field = const ResolverPool::Field*;
0326 
0327   /// Functions for working with descriptors. ///
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     // type.proto cannot represent extensions, so this function always
0369     // fails.
0370     return absl::nullopt;
0371   }
0372 
0373   /// Functions for introspecting fields. ///
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     // If there is no slash, `slash` is string_view::npos, which is guaranteed
0385     // to be -1.
0386     size_t slash = url.rfind('/');
0387     return url.substr(slash + 1);
0388   }
0389 
0390   static FieldDescriptor::Type FieldType(Field f) {
0391     // The descriptor.proto and type.proto field type enums are required to be
0392     // the same, so we leverage this.
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     // Implicit presence requires this weird check: in proto3 the following
0435     // cases support presence:
0436     // 1) Anything contained in a oneof (including things explicitly declared
0437     //    'optional' which are represented as as synthetic oneof in proto3).
0438     // 2) Fields that are a message type (but not map fields which are also
0439     //    TYPE_MESSAGE here).
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         // Two ifs to avoid doing operator== twice if the names are not equal.
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 }  // namespace json_internal
0508 }  // namespace protobuf
0509 }  // namespace google
0510 
0511 #include "google/protobuf/port_undef.inc"
0512 #endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_DESCRIPTOR_TRAITS_INTERNAL_H__