| // Protocol Buffers - Google's data interchange format |
| // Copyright 2008 Google Inc. All rights reserved. |
| // https://developers.google.com/protocol-buffers/ |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #ifndef GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_TRAITS_H__ |
| #define GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_TRAITS_H__ |
| |
| #include <algorithm> |
| #include <cfloat> |
| #include <cstdint> |
| #include <memory> |
| #include <sstream> |
| #include <string> |
| #include <type_traits> |
| #include <utility> |
| #include <vector> |
| |
| #include "google/protobuf/type.pb.h" |
| #include "google/protobuf/descriptor.h" |
| #include "google/protobuf/dynamic_message.h" |
| #include "google/protobuf/message.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/wire_format.h" |
| #include "google/protobuf/wire_format_lite.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 <typename Traits> |
| 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<Field>& 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<Field> 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<float> GetFloat(Field f) { |
| return f->default_value_float(); |
| } |
| |
| static absl::StatusOr<double> GetDouble(Field f) { |
| return f->default_value_double(); |
| } |
| |
| static absl::StatusOr<int32_t> GetInt32(Field f) { |
| return f->default_value_int32(); |
| } |
| |
| static absl::StatusOr<uint32_t> GetUInt32(Field f) { |
| return f->default_value_uint32(); |
| } |
| |
| static absl::StatusOr<int64_t> GetInt64(Field f) { |
| return f->default_value_int64(); |
| } |
| |
| static absl::StatusOr<uint64_t> GetUInt64(Field f) { |
| return f->default_value_uint64(); |
| } |
| |
| static absl::StatusOr<bool> GetBool(Field f) { |
| return f->default_value_bool(); |
| } |
| |
| static absl::StatusOr<int32_t> GetEnumValue(Field f) { |
| return f->default_value_enum()->number(); |
| } |
| |
| static absl::StatusOr<absl::string_view> GetString(Field f, |
| std::string& scratch) { |
| return f->default_value_string(); |
| } |
| |
| static absl::StatusOr<const Msg*> GetMessage(Field f) { |
| return absl::InternalError("message fields cannot have defaults"); |
| } |
| |
| static absl::StatusOr<float> GetFloat(Field f, const Msg& msg) { |
| return msg.GetReflection()->GetFloat(msg, f); |
| } |
| |
| static absl::StatusOr<double> GetDouble(Field f, const Msg& msg) { |
| return msg.GetReflection()->GetDouble(msg, f); |
| } |
| |
| static absl::StatusOr<int32_t> GetInt32(Field f, const Msg& msg) { |
| return msg.GetReflection()->GetInt32(msg, f); |
| } |
| |
| static absl::StatusOr<uint32_t> GetUInt32(Field f, const Msg& msg) { |
| return msg.GetReflection()->GetUInt32(msg, f); |
| } |
| |
| static absl::StatusOr<int64_t> GetInt64(Field f, const Msg& msg) { |
| return msg.GetReflection()->GetInt64(msg, f); |
| } |
| |
| static absl::StatusOr<uint64_t> GetUInt64(Field f, const Msg& msg) { |
| return msg.GetReflection()->GetUInt64(msg, f); |
| } |
| |
| static absl::StatusOr<bool> GetBool(Field f, const Msg& msg) { |
| return msg.GetReflection()->GetBool(msg, f); |
| } |
| |
| static absl::StatusOr<int32_t> GetEnumValue(Field f, const Msg& msg) { |
| return msg.GetReflection()->GetEnumValue(msg, f); |
| } |
| |
| static absl::StatusOr<absl::string_view> GetString(Field f, |
| std::string& scratch, |
| const Msg& msg) { |
| return msg.GetReflection()->GetStringReference(msg, f, &scratch); |
| } |
| |
| static absl::StatusOr<const Msg*> GetMessage(Field f, const Msg& msg) { |
| return &msg.GetReflection()->GetMessage(msg, f); |
| } |
| |
| static absl::StatusOr<float> GetFloat(Field f, const Msg& msg, size_t idx) { |
| return msg.GetReflection()->GetRepeatedFloat(msg, f, idx); |
| } |
| |
| static absl::StatusOr<double> GetDouble(Field f, const Msg& msg, size_t idx) { |
| return msg.GetReflection()->GetRepeatedDouble(msg, f, idx); |
| } |
| |
| static absl::StatusOr<int32_t> GetInt32(Field f, const Msg& msg, size_t idx) { |
| return msg.GetReflection()->GetRepeatedInt32(msg, f, idx); |
| } |
| |
| static absl::StatusOr<uint32_t> GetUInt32(Field f, const Msg& msg, |
| size_t idx) { |
| return msg.GetReflection()->GetRepeatedUInt32(msg, f, idx); |
| } |
| |
| static absl::StatusOr<int64_t> GetInt64(Field f, const Msg& msg, size_t idx) { |
| return msg.GetReflection()->GetRepeatedInt64(msg, f, idx); |
| } |
| |
| static absl::StatusOr<uint64_t> GetUInt64(Field f, const Msg& msg, |
| size_t idx) { |
| return msg.GetReflection()->GetRepeatedUInt64(msg, f, idx); |
| } |
| |
| static absl::StatusOr<bool> GetBool(Field f, const Msg& msg, size_t idx) { |
| return msg.GetReflection()->GetRepeatedBool(msg, f, idx); |
| } |
| |
| static absl::StatusOr<int32_t> GetEnumValue(Field f, const Msg& msg, |
| size_t idx) { |
| return msg.GetReflection()->GetRepeatedEnumValue(msg, f, idx); |
| } |
| |
| static absl::StatusOr<absl::string_view> GetString(Field f, |
| std::string& scratch, |
| const Msg& msg, |
| size_t idx) { |
| return msg.GetReflection()->GetRepeatedStringReference(msg, f, idx, |
| &scratch); |
| } |
| |
| static absl::StatusOr<const Msg*> GetMessage(Field f, const Msg& msg, |
| size_t idx) { |
| return &msg.GetReflection()->GetRepeatedMessage(msg, f, idx); |
| } |
| |
| template <typename F> |
| static absl::Status WithDecodedMessage(const Desc& desc, |
| absl::string_view data, F body) { |
| DynamicMessageFactory factory; |
| std::unique_ptr<Message> unerased(factory.GetPrototype(&desc)->New()); |
| unerased->ParseFromString(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<Field>&) { |
| // type.proto does not support extensions. |
| } |
| |
| static size_t GetSize(Field f, const Msg& msg) { |
| return msg.Count(f->proto().number()); |
| } |
| |
| static absl::StatusOr<float> 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<double> 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<int32_t> 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<uint32_t> 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<int64_t> 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<uint64_t> 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<bool> 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<int32_t> 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<absl::string_view> GetString(Field f, |
| std::string& scratch) { |
| absl::CUnescape(f->proto().default_value(), &scratch); |
| return scratch; |
| } |
| |
| static absl::StatusOr<const Msg*> GetMessage(Field f) { |
| return absl::InternalError("message fields cannot have defaults"); |
| } |
| |
| static absl::StatusOr<float> GetFloat(Field f, const Msg& msg, |
| size_t idx = 0) { |
| return msg.Get<float>(f->proto().number())[idx]; |
| } |
| |
| static absl::StatusOr<double> GetDouble(Field f, const Msg& msg, |
| size_t idx = 0) { |
| return msg.Get<double>(f->proto().number())[idx]; |
| } |
| |
| static absl::StatusOr<int32_t> GetInt32(Field f, const Msg& msg, |
| size_t idx = 0) { |
| return msg.Get<int32_t>(f->proto().number())[idx]; |
| } |
| |
| static absl::StatusOr<uint32_t> GetUInt32(Field f, const Msg& msg, |
| size_t idx = 0) { |
| return msg.Get<uint32_t>(f->proto().number())[idx]; |
| } |
| |
| static absl::StatusOr<int64_t> GetInt64(Field f, const Msg& msg, |
| size_t idx = 0) { |
| return msg.Get<int64_t>(f->proto().number())[idx]; |
| } |
| |
| static absl::StatusOr<uint64_t> GetUInt64(Field f, const Msg& msg, |
| size_t idx = 0) { |
| return msg.Get<uint64_t>(f->proto().number())[idx]; |
| } |
| |
| static absl::StatusOr<bool> GetBool(Field f, const Msg& msg, size_t idx = 0) { |
| return msg.Get<Msg::Bool>(f->proto().number())[idx] == Msg::kTrue; |
| } |
| |
| static absl::StatusOr<int32_t> GetEnumValue(Field f, const Msg& msg, |
| size_t idx = 0) { |
| return msg.Get<int32_t>(f->proto().number())[idx]; |
| } |
| |
| static absl::StatusOr<absl::string_view> GetString(Field f, |
| std::string& scratch, |
| const Msg& msg, |
| size_t idx = 0) { |
| return msg.Get<std::string>(f->proto().number())[idx]; |
| } |
| |
| static absl::StatusOr<const Msg*> GetMessage(Field f, const Msg& msg, |
| size_t idx = 0) { |
| return &msg.Get<Msg>(f->proto().number())[idx]; |
| } |
| |
| template <typename F> |
| static absl::Status WithDecodedMessage(const Desc& desc, |
| absl::string_view data, F body) { |
| io::CodedInputStream stream(reinterpret_cast<const uint8_t*>(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__ |