// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd #ifndef GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_TRAITS_H__ #define GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_TRAITS_H__ #include #include #include #include #include #include #include #include #include #include "google/protobuf/type.pb.h" #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/numbers.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "absl/types/variant.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/json/internal/descriptor_traits.h" #include "google/protobuf/stubs/status_macros.h" // Must be included last. #include "google/protobuf/port_def.inc" namespace google { namespace protobuf { namespace json_internal { // The type traits in this file provide describe how to read from protobuf // representation used by the JSON API, either via proto reflection or via // something ad-hoc for type.proto. // Helper alias templates to avoid needing to write `typename` in function // signatures. template using Msg = typename Traits::Msg; // Traits for proto2-ish deserialization. struct UnparseProto2Descriptor : Proto2Descriptor { // A message value that fields can be read from. using Msg = Message; static const Desc& GetDesc(const Msg& msg) { return *msg.GetDescriptor(); } // Appends extension fields to `fields`. static void FindAndAppendExtensions(const Msg& msg, std::vector& fields) { // Note that it is *not* correct to use ListFields for getting a list of // fields to write, because the way that JSON decides to print non-extension // fields is slightly subtle. That logic is handled elsewhere; we're only // here to get extensions. std::vector all_fields; msg.GetReflection()->ListFields(msg, &all_fields); for (Field field : all_fields) { if (field->is_extension()) { fields.push_back(field); } } } static size_t GetSize(Field f, const Msg& msg) { if (f->is_repeated()) { return msg.GetReflection()->FieldSize(msg, f); } else { return msg.GetReflection()->HasField(msg, f) ? 1 : 0; } } static absl::StatusOr GetFloat(Field f) { return f->default_value_float(); } static absl::StatusOr GetDouble(Field f) { return f->default_value_double(); } static absl::StatusOr GetInt32(Field f) { return f->default_value_int32(); } static absl::StatusOr GetUInt32(Field f) { return f->default_value_uint32(); } static absl::StatusOr GetInt64(Field f) { return f->default_value_int64(); } static absl::StatusOr GetUInt64(Field f) { return f->default_value_uint64(); } static absl::StatusOr GetBool(Field f) { return f->default_value_bool(); } static absl::StatusOr GetEnumValue(Field f) { return f->default_value_enum()->number(); } static absl::StatusOr GetString(Field f, std::string& scratch) { return f->default_value_string(); } static absl::StatusOr GetMessage(Field f) { return absl::InternalError("message fields cannot have defaults"); } static absl::StatusOr GetFloat(Field f, const Msg& msg) { return msg.GetReflection()->GetFloat(msg, f); } static absl::StatusOr GetDouble(Field f, const Msg& msg) { return msg.GetReflection()->GetDouble(msg, f); } static absl::StatusOr GetInt32(Field f, const Msg& msg) { return msg.GetReflection()->GetInt32(msg, f); } static absl::StatusOr GetUInt32(Field f, const Msg& msg) { return msg.GetReflection()->GetUInt32(msg, f); } static absl::StatusOr GetInt64(Field f, const Msg& msg) { return msg.GetReflection()->GetInt64(msg, f); } static absl::StatusOr GetUInt64(Field f, const Msg& msg) { return msg.GetReflection()->GetUInt64(msg, f); } static absl::StatusOr GetBool(Field f, const Msg& msg) { return msg.GetReflection()->GetBool(msg, f); } static absl::StatusOr GetEnumValue(Field f, const Msg& msg) { return msg.GetReflection()->GetEnumValue(msg, f); } static absl::StatusOr GetString(Field f, std::string& scratch, const Msg& msg) { return msg.GetReflection()->GetStringReference(msg, f, &scratch); } static absl::StatusOr GetMessage(Field f, const Msg& msg) { return &msg.GetReflection()->GetMessage(msg, f); } static absl::StatusOr GetFloat(Field f, const Msg& msg, size_t idx) { return msg.GetReflection()->GetRepeatedFloat(msg, f, idx); } static absl::StatusOr GetDouble(Field f, const Msg& msg, size_t idx) { return msg.GetReflection()->GetRepeatedDouble(msg, f, idx); } static absl::StatusOr GetInt32(Field f, const Msg& msg, size_t idx) { return msg.GetReflection()->GetRepeatedInt32(msg, f, idx); } static absl::StatusOr GetUInt32(Field f, const Msg& msg, size_t idx) { return msg.GetReflection()->GetRepeatedUInt32(msg, f, idx); } static absl::StatusOr GetInt64(Field f, const Msg& msg, size_t idx) { return msg.GetReflection()->GetRepeatedInt64(msg, f, idx); } static absl::StatusOr GetUInt64(Field f, const Msg& msg, size_t idx) { return msg.GetReflection()->GetRepeatedUInt64(msg, f, idx); } static absl::StatusOr GetBool(Field f, const Msg& msg, size_t idx) { return msg.GetReflection()->GetRepeatedBool(msg, f, idx); } static absl::StatusOr GetEnumValue(Field f, const Msg& msg, size_t idx) { return msg.GetReflection()->GetRepeatedEnumValue(msg, f, idx); } static absl::StatusOr GetString(Field f, std::string& scratch, const Msg& msg, size_t idx) { return msg.GetReflection()->GetRepeatedStringReference(msg, f, idx, &scratch); } static absl::StatusOr GetMessage(Field f, const Msg& msg, size_t idx) { return &msg.GetReflection()->GetRepeatedMessage(msg, f, idx); } template static absl::Status WithDecodedMessage(const Desc& desc, absl::string_view data, F body) { DynamicMessageFactory factory; std::unique_ptr unerased(factory.GetPrototype(&desc)->New()); unerased->ParsePartialFromString(data); // Explicitly create a const reference, so that we do not accidentally pass // a mutable reference to `body`. const Msg& ref = *unerased; return body(ref); } }; struct UnparseProto3Type : Proto3Type { using Msg = UntypedMessage; static const Desc& GetDesc(const Msg& msg) { return msg.desc(); } static void FindAndAppendExtensions(const Msg&, std::vector&) { // type.proto does not support extensions. } static size_t GetSize(Field f, const Msg& msg) { return msg.Count(f->proto().number()); } static absl::StatusOr GetFloat(Field f) { if (f->proto().default_value().empty()) { return 0.0; } float x; if (!absl::SimpleAtof(f->proto().default_value(), &x)) { return absl::InternalError(absl::StrCat( "bad default value in type.proto: ", f->parent().proto().name())); } return x; } static absl::StatusOr GetDouble(Field f) { if (f->proto().default_value().empty()) { return 0.0; } double x; if (!absl::SimpleAtod(f->proto().default_value(), &x)) { return absl::InternalError(absl::StrCat( "bad default value in type.proto: ", f->parent().proto().name())); } return x; } static absl::StatusOr GetInt32(Field f) { if (f->proto().default_value().empty()) { return 0; } int32_t x; if (!absl::SimpleAtoi(f->proto().default_value(), &x)) { return absl::InternalError(absl::StrCat( "bad default value in type.proto: ", f->parent().proto().name())); } return x; } static absl::StatusOr GetUInt32(Field f) { if (f->proto().default_value().empty()) { return 0; } uint32_t x; if (!absl::SimpleAtoi(f->proto().default_value(), &x)) { return absl::InternalError(absl::StrCat( "bad default value in type.proto: ", f->parent().proto().name())); } return x; } static absl::StatusOr GetInt64(Field f) { if (f->proto().default_value().empty()) { return 0; } int64_t x; if (!absl::SimpleAtoi(f->proto().default_value(), &x)) { return absl::InternalError(absl::StrCat( "bad default value in type.proto: ", f->parent().proto().name())); } return x; } static absl::StatusOr GetUInt64(Field f) { if (f->proto().default_value().empty()) { return 0; } uint64_t x; if (!absl::SimpleAtoi(f->proto().default_value(), &x)) { return absl::InternalError(absl::StrCat( "bad default value in type.proto: ", f->parent().proto().name())); } return x; } static absl::StatusOr GetBool(Field f) { if (f->proto().default_value().empty()) { return false; } else if (f->proto().default_value() == "false") { return false; } else if (f->proto().default_value() == "true") { return true; } else { return absl::InternalError(absl::StrCat( "bad default value in type.proto: ", f->parent().proto().name())); } } static absl::StatusOr GetEnumValue(Field f) { if (f->proto().default_value().empty()) { auto e = f->EnumType(); RETURN_IF_ERROR(e.status()); return (**e).proto().enumvalue(0).number(); } return EnumNumberByName(f, f->proto().default_value(), /*case_insensitive=*/false); } static absl::StatusOr GetString(Field f, std::string& scratch) { absl::CUnescape(f->proto().default_value(), &scratch); return scratch; } static absl::StatusOr GetMessage(Field f) { return absl::InternalError("message fields cannot have defaults"); } static absl::StatusOr GetFloat(Field f, const Msg& msg, size_t idx = 0) { return msg.Get(f->proto().number())[idx]; } static absl::StatusOr GetDouble(Field f, const Msg& msg, size_t idx = 0) { return msg.Get(f->proto().number())[idx]; } static absl::StatusOr GetInt32(Field f, const Msg& msg, size_t idx = 0) { return msg.Get(f->proto().number())[idx]; } static absl::StatusOr GetUInt32(Field f, const Msg& msg, size_t idx = 0) { return msg.Get(f->proto().number())[idx]; } static absl::StatusOr GetInt64(Field f, const Msg& msg, size_t idx = 0) { return msg.Get(f->proto().number())[idx]; } static absl::StatusOr GetUInt64(Field f, const Msg& msg, size_t idx = 0) { return msg.Get(f->proto().number())[idx]; } static absl::StatusOr GetBool(Field f, const Msg& msg, size_t idx = 0) { return msg.Get(f->proto().number())[idx] == Msg::kTrue; } static absl::StatusOr GetEnumValue(Field f, const Msg& msg, size_t idx = 0) { return msg.Get(f->proto().number())[idx]; } static absl::StatusOr GetString(Field f, std::string& scratch, const Msg& msg, size_t idx = 0) { return msg.Get(f->proto().number())[idx]; } static absl::StatusOr GetMessage(Field f, const Msg& msg, size_t idx = 0) { return &msg.Get(f->proto().number())[idx]; } template static absl::Status WithDecodedMessage(const Desc& desc, absl::string_view data, F body) { io::CodedInputStream stream(reinterpret_cast(data.data()), data.size()); auto unerased = Msg::ParseFromStream(&desc, stream); RETURN_IF_ERROR(unerased.status()); // Explicitly create a const reference, so that we do not accidentally pass // a mutable reference to `body`. const Msg& ref = *unerased; return body(ref); } }; } // namespace json_internal } // namespace protobuf } // namespace google #include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_TRAITS_H__