blob: cab762ba3325bfe89cd24d989055dab368ed9660 [file] [log] [blame]
// 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__