// 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_PARSER_TRAITS_H__
#define GOOGLE_PROTOBUF_JSON_INTERNAL_PARSER_TRAITS_H__

#include <cfloat>
#include <cmath>
#include <cstdint>
#include <limits>
#include <string>
#include <utility>

#include "google/protobuf/type.pb.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/dynamic_message.h"
#include "google/protobuf/message.h"
#include "google/protobuf/wire_format_lite.h"
#include "absl/base/attributes.h"
#include "absl/base/casts.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "google/protobuf/io/zero_copy_stream_impl_lite.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 {
using ::google::protobuf::internal::WireFormatLite;

// See the comment in json_util2_parser.cc for more information.
//
// The type traits in this file  describe how to parse to a protobuf
// representation used by the JSON API, either via proto reflection or by
// emitting wire format to an output stream.

// Helper alias templates to avoid needing to write `typename` in function
// signatures.
template <typename Traits>
using Msg = typename Traits::Msg;

struct ParseProto2Descriptor : Proto2Descriptor {
  // A message value that fields can be written to, but not read from.
  class Msg {
   public:
    explicit Msg(Message* msg) : msg_(msg) {}

   private:
    friend ParseProto2Descriptor;
    Message* msg_;
    // Because `msg` might already have oneofs set, we need to track which were
    // set *during* the parse separately.
    absl::flat_hash_set<int> parsed_oneofs_indices_;
    absl::flat_hash_set<int> parsed_fields_;
  };

  static bool HasParsed(Field f, const Msg& msg,
                        bool allow_repeated_non_oneof) {
    if (f->real_containing_oneof()) {
      return msg.parsed_oneofs_indices_.contains(
          f->real_containing_oneof()->index());
    }
    if (allow_repeated_non_oneof) {
      return false;
    }
    return msg.parsed_fields_.contains(f->number());
  }

  /// Functions for writing fields. ///

  // Marks a field as having been "seen". This will clear the field if it is
  // the first occurrence thereof.
  //
  // All setters call this function automatically, but it may also be called
  // eagerly to clear a pre-existing value that might not be overwritten, such
  // as when parsing a repeated field.
  static void RecordAsSeen(Field f, Msg& msg) {
    bool inserted = msg.parsed_fields_.insert(f->number()).second;
    if (inserted) {
      msg.msg_->GetReflection()->ClearField(msg.msg_, f);
    }

    if (f->real_containing_oneof() != nullptr) {
      msg.parsed_oneofs_indices_.insert(f->real_containing_oneof()->index());
    }
  }

  // Adds a new message and calls body on it.
  //
  // Body should have a signature `absl::Status(const Desc&, Msg&)`.
  template <typename F>
  static absl::Status NewMsg(Field f, Msg& msg, F body) {
    RecordAsSeen(f, msg);

    Message* new_msg;
    if (f->is_repeated()) {
      new_msg = msg.msg_->GetReflection()->AddMessage(msg.msg_, f);
    } else {
      new_msg = msg.msg_->GetReflection()->MutableMessage(msg.msg_, f);
    }
    Msg wrapper(new_msg);
    return body(*f->message_type(), wrapper);
  }

  // Adds a new dynamic message with the given type name and calls body on it.
  //
  // Body should have a signature `absl::Status(const Desc&, Msg&)`.
  template <typename F>
  static absl::Status NewDynamic(Field f, const std::string& type_url, Msg& msg,
                                 F body) {
    RecordAsSeen(f, msg);
    return WithDynamicType(
        *f->containing_type(), type_url, [&](const Desc& desc) -> absl::Status {
          DynamicMessageFactory factory;
          std::unique_ptr<Message> dynamic(factory.GetPrototype(&desc)->New());
          Msg wrapper(dynamic.get());
          RETURN_IF_ERROR(body(desc, wrapper));

          if (f->is_repeated()) {
            msg.msg_->GetReflection()->AddString(msg.msg_, f,
                                                 dynamic->SerializeAsString());
          } else {
            msg.msg_->GetReflection()->SetString(msg.msg_, f,
                                                 dynamic->SerializeAsString());
          }
          return absl::OkStatus();
        });
  }

  static void SetFloat(Field f, Msg& msg, float x) {
    RecordAsSeen(f, msg);
    if (f->is_repeated()) {
      msg.msg_->GetReflection()->AddFloat(msg.msg_, f, x);
    } else {
      msg.msg_->GetReflection()->SetFloat(msg.msg_, f, x);
    }
  }

  static void SetDouble(Field f, Msg& msg, double x) {
    if (f->is_repeated()) {
      msg.msg_->GetReflection()->AddDouble(msg.msg_, f, x);
    } else {
      msg.msg_->GetReflection()->SetDouble(msg.msg_, f, x);
    }
  }

  static void SetInt64(Field f, Msg& msg, int64_t x) {
    RecordAsSeen(f, msg);
    if (f->is_repeated()) {
      msg.msg_->GetReflection()->AddInt64(msg.msg_, f, x);
    } else {
      msg.msg_->GetReflection()->SetInt64(msg.msg_, f, x);
    }
  }

  static void SetUInt64(Field f, Msg& msg, uint64_t x) {
    RecordAsSeen(f, msg);
    if (f->is_repeated()) {
      msg.msg_->GetReflection()->AddUInt64(msg.msg_, f, x);
    } else {
      msg.msg_->GetReflection()->SetUInt64(msg.msg_, f, x);
    }
  }

  static void SetInt32(Field f, Msg& msg, int32 x) {
    RecordAsSeen(f, msg);
    if (f->is_repeated()) {
      msg.msg_->GetReflection()->AddInt32(msg.msg_, f, x);
    } else {
      msg.msg_->GetReflection()->SetInt32(msg.msg_, f, x);
    }
  }

  static void SetUInt32(Field f, Msg& msg, uint32 x) {
    RecordAsSeen(f, msg);
    if (f->is_repeated()) {
      msg.msg_->GetReflection()->AddUInt32(msg.msg_, f, x);
    } else {
      msg.msg_->GetReflection()->SetUInt32(msg.msg_, f, x);
    }
  }

  static void SetBool(Field f, Msg& msg, bool x) {
    RecordAsSeen(f, msg);
    if (f->is_repeated()) {
      msg.msg_->GetReflection()->AddBool(msg.msg_, f, x);
    } else {
      msg.msg_->GetReflection()->SetBool(msg.msg_, f, x);
    }
  }

  static void SetString(Field f, Msg& msg, absl::string_view x) {
    RecordAsSeen(f, msg);
    if (f->is_repeated()) {
      msg.msg_->GetReflection()->AddString(msg.msg_, f, std::string(x));
    } else {
      msg.msg_->GetReflection()->SetString(msg.msg_, f, std::string(x));
    }
  }

  static void SetEnum(Field f, Msg& msg, int32_t x) {
    RecordAsSeen(f, msg);
    if (f->is_repeated()) {
      msg.msg_->GetReflection()->AddEnumValue(msg.msg_, f, x);
    } else {
      msg.msg_->GetReflection()->SetEnumValue(msg.msg_, f, x);
    }
  }
};

// Traits for proto3-ish deserialization.
//
// This includes a rudimentary proto serializer, since message fields are
// written directly instead of being reflectively written to a proto field.
//
// See MessageTraits for API docs.
struct ParseProto3Type : Proto3Type {
  class Msg {
   public:
    explicit Msg(io::ZeroCopyOutputStream* stream) : stream_(stream) {}

   private:
    friend ParseProto3Type;
    io::CodedOutputStream stream_;
    absl::flat_hash_set<int32_t> parsed_oneofs_indices_;
    absl::flat_hash_set<int32_t> parsed_fields_;
  };

  static bool HasParsed(Field f, const Msg& msg,
                        bool allow_repeated_non_oneof) {
    if (f->proto().oneof_index() != 0) {
      return msg.parsed_oneofs_indices_.contains(f->proto().oneof_index());
    }
    if (allow_repeated_non_oneof) {
      return false;
    }
    return msg.parsed_fields_.contains(f->proto().number());
  }

  /// Functions for writing fields. ///

  static void RecordAsSeen(Field f, Msg& msg) {
    msg.parsed_fields_.insert(f->proto().number());
    if (f->proto().oneof_index() != 0) {
      msg.parsed_oneofs_indices_.insert(f->proto().oneof_index());
    }
  }

  template <typename F>
  static absl::Status NewMsg(Field f, Msg& msg, F body) {
    return NewDynamic(f, f->proto().type_url(), msg, body);
  }

  template <typename F>
  static absl::Status NewDynamic(Field f, const std::string& type_url, Msg& msg,
                                 F body) {
    RecordAsSeen(f, msg);
    return WithDynamicType(
        f->parent(), type_url, [&](const Desc& desc) -> absl::Status {
          if (f->proto().kind() == google::protobuf::Field::TYPE_GROUP) {
            msg.stream_.WriteTag(f->proto().number() << 3 |
                                 WireFormatLite::WIRETYPE_START_GROUP);
            RETURN_IF_ERROR(body(desc, msg));
            msg.stream_.WriteTag(f->proto().number() << 3 |
                                 WireFormatLite::WIRETYPE_END_GROUP);
            return absl::OkStatus();
          }

          std::string out;
          io::StringOutputStream stream(&out);
          Msg new_msg(&stream);
          RETURN_IF_ERROR(body(desc, new_msg));

          new_msg.stream_.Trim();  // Should probably be called "Flush()".
          absl::string_view written(
              out.data(), static_cast<size_t>(new_msg.stream_.ByteCount()));
          SetString(f, msg, written);
          return absl::OkStatus();
        });
  }

  static void SetFloat(Field f, Msg& msg, float x) {
    RecordAsSeen(f, msg);
    msg.stream_.WriteTag(f->proto().number() << 3 |
                         WireFormatLite::WIRETYPE_FIXED32);
    msg.stream_.WriteLittleEndian32(absl::bit_cast<uint32_t>(x));
  }

  static void SetDouble(Field f, Msg& msg, double x) {
    RecordAsSeen(f, msg);
    msg.stream_.WriteTag(f->proto().number() << 3 |
                         WireFormatLite::WIRETYPE_FIXED64);
    msg.stream_.WriteLittleEndian64(absl::bit_cast<uint64_t>(x));
  }

  static void SetInt64(Field f, Msg& msg, int64_t x) {
    SetInt<int64_t, google::protobuf::Field::TYPE_INT64,
           google::protobuf::Field::TYPE_SFIXED64,
           google::protobuf::Field::TYPE_SINT64>(f, msg, x);
  }

  static void SetUInt64(Field f, Msg& msg, uint64_t x) {
    SetInt<uint64_t, google::protobuf::Field::TYPE_UINT64,
           google::protobuf::Field::TYPE_FIXED64,
           google::protobuf::Field::TYPE_UNKNOWN>(f, msg, x);
  }

  static void SetInt32(Field f, Msg& msg, int32_t x) {
    SetInt<int32_t, google::protobuf::Field::TYPE_INT32,
           google::protobuf::Field::TYPE_SFIXED32,
           google::protobuf::Field::TYPE_SINT32>(f, msg, x);
  }

  static void SetUInt32(Field f, Msg& msg, uint32_t x) {
    SetInt<uint32_t, google::protobuf::Field::TYPE_UINT32,
           google::protobuf::Field::TYPE_FIXED32,
           google::protobuf::Field::TYPE_UNKNOWN>(f, msg, x);
  }

  static void SetBool(Field f, Msg& msg, bool x) {
    RecordAsSeen(f, msg);
    msg.stream_.WriteTag(f->proto().number() << 3);
    char b = x ? 0x01 : 0x00;
    msg.stream_.WriteRaw(&b, 1);
  }

  static void SetString(Field f, Msg& msg, absl::string_view x) {
    RecordAsSeen(f, msg);
    msg.stream_.WriteTag(f->proto().number() << 3 |
                         WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
    msg.stream_.WriteVarint64(static_cast<uint64_t>(x.size()));
    msg.stream_.WriteRaw(x.data(), x.size());
  }

  static void SetEnum(Field f, Msg& msg, int32_t x) {
    RecordAsSeen(f, msg);
    msg.stream_.WriteTag(f->proto().number() << 3);
    // Sign extension is deliberate here.
    msg.stream_.WriteVarint32(x);
  }

 private:
  using Kind = google::protobuf::Field::Kind;
  // Sets a field of *some* integer type, with the given kinds for the possible
  // encodings. This avoids quadruplicating this code in the helpers for the
  // four major integer types.
  template <typename Int, Kind varint, Kind fixed, Kind zigzag>
  static void SetInt(Field f, Msg& msg, Int x) {
    RecordAsSeen(f, msg);
    switch (f->proto().kind()) {
      case zigzag:
        // Regardless of the integer type, ZigZag64 will do the right thing,
        // because ZigZag is not dependent on the width of the integer: it is
        // always `2 * abs(n) + (n < 0)`.
        x = static_cast<Int>(
            internal::WireFormatLite::ZigZagEncode64(static_cast<int64_t>(x)));
        ABSL_FALLTHROUGH_INTENDED;
      case varint:
        msg.stream_.WriteTag(f->proto().number() << 3 |
                             WireFormatLite::WIRETYPE_VARINT);
        if (sizeof(Int) == 4) {
          msg.stream_.WriteVarint32(static_cast<uint32_t>(x));
        } else {
          msg.stream_.WriteVarint64(static_cast<uint64_t>(x));
        }
        break;
      case fixed: {
        if (sizeof(Int) == 4) {
          msg.stream_.WriteTag(f->proto().number() << 3 |
                               WireFormatLite::WIRETYPE_FIXED32);
          msg.stream_.WriteLittleEndian32(static_cast<uint32_t>(x));
        } else {
          msg.stream_.WriteTag(f->proto().number() << 3 |
                               WireFormatLite::WIRETYPE_FIXED64);
          msg.stream_.WriteLittleEndian64(static_cast<uint64_t>(x));
        }
        break;
      }
      default: {  // Unreachable.
      }
    }
  }
};
}  // namespace json_internal
}  // namespace protobuf
}  // namespace google

#include "google/protobuf/port_undef.inc"
#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_PARSER_TRAITS_H__
