// 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_MAP_ENTRY_LITE_H__
#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__

#include <assert.h>

#include <algorithm>
#include <string>
#include <utility>

#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/port.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/map.h>
#include <google/protobuf/map_type_handler.h>
#include <google/protobuf/parse_context.h>
#include <google/protobuf/wire_format_lite.h>

// Must be included last.
#include <google/protobuf/port_def.inc>
#ifdef SWIG
#error "You cannot SWIG proto headers"
#endif

namespace google {
namespace protobuf {
namespace internal {
template <typename Derived, typename Key, typename Value,
          WireFormatLite::FieldType kKeyFieldType,
          WireFormatLite::FieldType kValueFieldType>
class MapEntry;
template <typename Derived, typename Key, typename Value,
          WireFormatLite::FieldType kKeyFieldType,
          WireFormatLite::FieldType kValueFieldType>
class MapFieldLite;
}  // namespace internal
}  // namespace protobuf
}  // namespace google

namespace google {
namespace protobuf {
namespace internal {

// MoveHelper::Move is used to set *dest.  It copies *src, or moves it (in
// the C++11 sense), or swaps it. *src is left in a sane state for
// subsequent destruction, but shouldn't be used for anything.
template <bool is_enum, bool is_message, bool is_stringlike, typename T>
struct MoveHelper {  // primitives
  static void Move(T* src, T* dest) { *dest = *src; }
};

template <bool is_message, bool is_stringlike, typename T>
struct MoveHelper<true, is_message, is_stringlike, T> {  // enums
  static void Move(T* src, T* dest) { *dest = *src; }
  // T is an enum here, so allow conversions to and from int.
  static void Move(T* src, int* dest) { *dest = static_cast<int>(*src); }
  static void Move(int* src, T* dest) { *dest = static_cast<T>(*src); }
};

template <bool is_stringlike, typename T>
struct MoveHelper<false, true, is_stringlike, T> {  // messages
  static void Move(T* src, T* dest) { dest->Swap(src); }
};

template <typename T>
struct MoveHelper<false, false, true, T> {  // strings and similar
  static void Move(T* src, T* dest) {
    *dest = std::move(*src);
  }
};

// MapEntryImpl is used to implement parsing and serialization of map entries.
// It uses Curious Recursive Template Pattern (CRTP) to provide the type of
// the eventual code to the template code.
template <typename Derived, typename Base, typename Key, typename Value,
          WireFormatLite::FieldType kKeyFieldType,
          WireFormatLite::FieldType kValueFieldType>
class MapEntryImpl : public Base {
 public:
  typedef MapEntryFuncs<Key, Value, kKeyFieldType, kValueFieldType> Funcs;

 protected:
  // Provide utilities to parse/serialize key/value.  Provide utilities to
  // manipulate internal stored type.
  typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
  typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;

  // Define internal memory layout. Strings and messages are stored as
  // pointers, while other types are stored as values.
  typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
  typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;

  // Enum type cannot be used for MapTypeHandler::Read. Define a type
  // which will replace Enum with int.
  typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
  typedef
      typename ValueTypeHandler::MapEntryAccessorType ValueMapEntryAccessorType;

  // Constants for field number.
  static const int kKeyFieldNumber = 1;
  static const int kValueFieldNumber = 2;

  // Constants for field tag.
  static const uint8_t kKeyTag =
      GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kKeyFieldNumber, KeyTypeHandler::kWireType);
  static const uint8_t kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
      kValueFieldNumber, ValueTypeHandler::kWireType);
  static const size_t kTagSize = 1;

 public:
  // Work-around for a compiler bug (see repeated_field.h).
  typedef void MapEntryHasMergeTypeTrait;
  typedef Derived EntryType;
  typedef Key EntryKeyType;
  typedef Value EntryValueType;
  static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType;
  static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType;

  constexpr MapEntryImpl()
      : key_(KeyTypeHandler::Constinit()),
        value_(ValueTypeHandler::Constinit()),
        _has_bits_{} {}

  explicit MapEntryImpl(Arena* arena)
      : Base(arena),
        key_(KeyTypeHandler::Constinit()),
        value_(ValueTypeHandler::Constinit()),
        _has_bits_{} {}

  ~MapEntryImpl() override {
    if (Base::GetArenaForAllocation() != nullptr) return;
    KeyTypeHandler::DeleteNoArena(key_);
    ValueTypeHandler::DeleteNoArena(value_);
  }

  // accessors ======================================================

  virtual inline const KeyMapEntryAccessorType& key() const {
    return KeyTypeHandler::GetExternalReference(key_);
  }
  virtual inline const ValueMapEntryAccessorType& value() const {
    return ValueTypeHandler::DefaultIfNotInitialized(value_);
  }
  inline KeyMapEntryAccessorType* mutable_key() {
    set_has_key();
    return KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
  }
  inline ValueMapEntryAccessorType* mutable_value() {
    set_has_value();
    return ValueTypeHandler::EnsureMutable(&value_,
                                           Base::GetArenaForAllocation());
  }

  // implements MessageLite =========================================

  // MapEntryImpl is for implementation only and this function isn't called
  // anywhere. Just provide a fake implementation here for MessageLite.
  std::string GetTypeName() const override { return ""; }

  void CheckTypeAndMergeFrom(const MessageLite& other) override {
    MergeFromInternal(*::google::protobuf::internal::DownCast<const Derived*>(&other));
  }

  const char* _InternalParse(const char* ptr, ParseContext* ctx) final {
    while (!ctx->Done(&ptr)) {
      uint32_t tag;
      ptr = ReadTag(ptr, &tag);
      GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
      if (tag == kKeyTag) {
        set_has_key();
        KeyMapEntryAccessorType* key = mutable_key();
        ptr = KeyTypeHandler::Read(ptr, ctx, key);
        if (!Derived::ValidateKey(key)) return nullptr;
      } else if (tag == kValueTag) {
        set_has_value();
        ValueMapEntryAccessorType* value = mutable_value();
        ptr = ValueTypeHandler::Read(ptr, ctx, value);
        if (!Derived::ValidateValue(value)) return nullptr;
      } else {
        if (tag == 0 || WireFormatLite::GetTagWireType(tag) ==
                            WireFormatLite::WIRETYPE_END_GROUP) {
          ctx->SetLastTag(tag);
          return ptr;
        }
        ptr = UnknownFieldParse(tag, static_cast<std::string*>(nullptr), ptr,
                                ctx);
      }
      GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    }
    return ptr;
  }

  size_t ByteSizeLong() const override {
    size_t size = 0;
    size += kTagSize + static_cast<size_t>(KeyTypeHandler::ByteSize(key()));
    size += kTagSize + static_cast<size_t>(ValueTypeHandler::ByteSize(value()));
    return size;
  }

  ::uint8_t* _InternalSerialize(
      ::uint8_t* ptr, io::EpsCopyOutputStream* stream) const override {
    ptr = KeyTypeHandler::Write(kKeyFieldNumber, key(), ptr, stream);
    return ValueTypeHandler::Write(kValueFieldNumber, value(), ptr, stream);
  }

  // Don't override SerializeWithCachedSizesToArray.  Use MessageLite's.

  int GetCachedSize() const override {
    int size = 0;
    size += has_key() ? static_cast<int>(kTagSize) +
                            KeyTypeHandler::GetCachedSize(key())
                      : 0;
    size += has_value() ? static_cast<int>(kTagSize) +
                              ValueTypeHandler::GetCachedSize(value())
                        : 0;
    return size;
  }

  bool IsInitialized() const override {
    return ValueTypeHandler::IsInitialized(value_);
  }

  Base* New(Arena* arena) const override {
    Derived* entry = Arena::CreateMessage<Derived>(arena);
    return entry;
  }

 protected:
  // We can't declare this function directly here as it would hide the other
  // overload (const Message&).
  void MergeFromInternal(const MapEntryImpl& from) {
    if (from._has_bits_[0]) {
      if (from.has_key()) {
        KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation());
        KeyTypeHandler::Merge(from.key(), &key_, Base::GetArenaForAllocation());
        set_has_key();
      }
      if (from.has_value()) {
        ValueTypeHandler::EnsureMutable(&value_, Base::GetArenaForAllocation());
        ValueTypeHandler::Merge(from.value(), &value_,
                                Base::GetArenaForAllocation());
        set_has_value();
      }
    }
  }

 public:
  void Clear() override {
    KeyTypeHandler::Clear(&key_, Base::GetArenaForAllocation());
    ValueTypeHandler::Clear(&value_, Base::GetArenaForAllocation());
    clear_has_key();
    clear_has_value();
  }

  // Parsing using MergePartialFromCodedStream, above, is not as
  // efficient as it could be.  This helper class provides a speedier way.
  template <typename MapField, typename Map>
  class Parser {
   public:
    explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {}
    ~Parser() {
      if (entry_ != nullptr && entry_->GetArenaForAllocation() == nullptr)
        delete entry_;
    }

    const char* _InternalParse(const char* ptr, ParseContext* ctx) {
      if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kKeyTag)) {
        ptr = KeyTypeHandler::Read(ptr + 1, ctx, &key_);
        if (PROTOBUF_PREDICT_FALSE(!ptr || !Derived::ValidateKey(&key_))) {
          return nullptr;
        }
        if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kValueTag)) {
          typename Map::size_type map_size = map_->size();
          value_ptr_ = &(*map_)[key_];
          if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) {
            using T =
                typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type;
            ptr = ValueTypeHandler::Read(ptr + 1, ctx,
                                         reinterpret_cast<T>(value_ptr_));
            if (PROTOBUF_PREDICT_FALSE(!ptr ||
                                       !Derived::ValidateValue(value_ptr_))) {
              map_->erase(key_);  // Failure! Undo insertion.
              return nullptr;
            }
            if (PROTOBUF_PREDICT_TRUE(ctx->Done(&ptr))) return ptr;
            if (!ptr) return nullptr;
            NewEntry();
            ValueMover::Move(value_ptr_, entry_->mutable_value());
            map_->erase(key_);
            goto move_key;
          }
        } else {
          if (!ptr) return nullptr;
        }
        NewEntry();
      move_key:
        KeyMover::Move(&key_, entry_->mutable_key());
      } else {
        if (!ptr) return nullptr;
        NewEntry();
      }
      ptr = entry_->_InternalParse(ptr, ctx);
      if (ptr) UseKeyAndValueFromEntry();
      return ptr;
    }

    template <typename UnknownType>
    const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
                                        bool (*is_valid)(int),
                                        uint32_t field_num,
                                        InternalMetadata* metadata) {
      auto entry = NewEntry();
      ptr = entry->_InternalParse(ptr, ctx);
      if (!ptr) return nullptr;
      if (is_valid(entry->value())) {
        UseKeyAndValueFromEntry();
      } else {
        WriteLengthDelimited(field_num, entry->SerializeAsString(),
                             metadata->mutable_unknown_fields<UnknownType>());
      }
      return ptr;
    }

    MapEntryImpl* NewEntry() { return entry_ = mf_->NewEntry(); }

    const Key& key() const { return key_; }
    const Value& value() const { return *value_ptr_; }

    const Key& entry_key() const { return entry_->key(); }
    const Value& entry_value() const { return entry_->value(); }

   private:
    void UseKeyAndValueFromEntry() {
      // Update key_ in case we need it later (because key() is called).
      // This is potentially inefficient, especially if the key is
      // expensive to copy (e.g., a long string), but this is a cold
      // path, so it's not a big deal.
      key_ = entry_->key();
      value_ptr_ = &(*map_)[key_];
      ValueMover::Move(entry_->mutable_value(), value_ptr_);
    }

    // After reading a key and value successfully, and inserting that data
    // into map_, we are not at the end of the input.  This is unusual, but
    // allowed by the spec.
    bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD {
      NewEntry();
      ValueMover::Move(value_ptr_, entry_->mutable_value());
      map_->erase(key_);
      KeyMover::Move(&key_, entry_->mutable_key());
      const bool result = entry_->MergePartialFromCodedStream(input);
      if (result) UseKeyAndValueFromEntry();
      return result;
    }

    typedef MoveHelper<KeyTypeHandler::kIsEnum, KeyTypeHandler::kIsMessage,
                       KeyTypeHandler::kWireType ==
                           WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
                       Key>
        KeyMover;
    typedef MoveHelper<ValueTypeHandler::kIsEnum, ValueTypeHandler::kIsMessage,
                       ValueTypeHandler::kWireType ==
                           WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
                       Value>
        ValueMover;

    MapField* const mf_;
    Map* const map_;
    Key key_;
    Value* value_ptr_;
    MapEntryImpl* entry_ = nullptr;
  };

 protected:
  void set_has_key() { _has_bits_[0] |= 0x00000001u; }
  bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
  void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
  void set_has_value() { _has_bits_[0] |= 0x00000002u; }
  bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
  void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }

 public:
  inline Arena* GetArena() const { return Base::GetArena(); }

 protected:  // Needed for constructing tables
  KeyOnMemory key_;
  ValueOnMemory value_;
  uint32_t _has_bits_[1];

 private:
  friend class ::PROTOBUF_NAMESPACE_ID::Arena;
  typedef void InternalArenaConstructable_;
  typedef void DestructorSkippable_;
  template <typename C, typename K, typename V, WireFormatLite::FieldType,
            WireFormatLite::FieldType>
  friend class internal::MapEntry;
  template <typename C, typename K, typename V, WireFormatLite::FieldType,
            WireFormatLite::FieldType>
  friend class internal::MapFieldLite;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl);
};

template <typename T, typename Key, typename Value,
          WireFormatLite::FieldType kKeyFieldType,
          WireFormatLite::FieldType kValueFieldType>
class MapEntryLite : public MapEntryImpl<T, MessageLite, Key, Value,
                                         kKeyFieldType, kValueFieldType> {
 public:
  typedef MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
                       kValueFieldType>
      SuperType;
  constexpr MapEntryLite() {}
  explicit MapEntryLite(Arena* arena) : SuperType(arena) {}
  ~MapEntryLite() override {
    MessageLite::_internal_metadata_.template Delete<std::string>();
  }
  void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); }

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
};

// Helpers for deterministic serialization =============================

// Iterator base for MapSorterFlat and MapSorterPtr.
template <typename storage_type>
struct MapSorterIt {
  storage_type* ptr;
  MapSorterIt(storage_type* ptr) : ptr(ptr) {}
  bool operator==(const MapSorterIt& other) const { return ptr == other.ptr; }
  bool operator!=(const MapSorterIt& other) const { return !(*this == other); }
  MapSorterIt& operator++() { ++ptr; return *this; }
  MapSorterIt operator++(int) { auto other = *this; ++ptr; return other; }
  MapSorterIt operator+(int v) { return MapSorterIt{ptr + v}; }
};

// MapSorterFlat stores keys inline with pointers to map entries, so that
// keys can be compared without indirection. This type is used for maps with
// keys that are not strings.
template <typename MapT>
class MapSorterFlat {
 public:
  using value_type = typename MapT::value_type;
  using storage_type = std::pair<typename MapT::key_type, const value_type*>;

  // This const_iterator dereferenes to the map entry stored in the sorting
  // array pairs. This is the same interface as the Map::const_iterator type,
  // and allows generated code to use the same loop body with either form:
  //   for (const auto& entry : map) { ... }
  //   for (const auto& entry : MapSorterFlat(map)) { ... }
  struct const_iterator : public MapSorterIt<storage_type> {
    using pointer = const typename MapT::value_type*;
    using reference = const typename MapT::value_type&;
    using MapSorterIt<storage_type>::MapSorterIt;

    pointer operator->() const { return this->ptr->second; }
    reference operator*() const { return *this->operator->(); }
  };

  explicit MapSorterFlat(const MapT& m)
      : size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
    if (!size_) return;
    storage_type* it = &items_[0];
    for (const auto& entry : m) {
      *it++ = {entry.first, &entry};
    }
    std::sort(&items_[0], &items_[size_],
              [](const storage_type& a, const storage_type& b) {
                return a.first < b.first;
              });
  }
  size_t size() const { return size_; }
  const_iterator begin() const { return {items_.get()}; }
  const_iterator end() const { return {items_.get() + size_}; }

 private:
  size_t size_;
  std::unique_ptr<storage_type[]> items_;
};

// MapSorterPtr stores and sorts pointers to map entries. This type is used for
// maps with keys that are strings.
template <typename MapT>
class MapSorterPtr {
 public:
  using value_type = typename MapT::value_type;
  using storage_type = const typename MapT::value_type*;

  // This const_iterator dereferenes the map entry pointer stored in the sorting
  // array. This is the same interface as the Map::const_iterator type, and
  // allows generated code to use the same loop body with either form:
  //   for (const auto& entry : map) { ... }
  //   for (const auto& entry : MapSorterPtr(map)) { ... }
  struct const_iterator : public MapSorterIt<storage_type> {
    using pointer = const typename MapT::value_type*;
    using reference = const typename MapT::value_type&;
    using MapSorterIt<storage_type>::MapSorterIt;

    pointer operator->() const { return *this->ptr; }
    reference operator*() const { return *this->operator->(); }
  };

  explicit MapSorterPtr(const MapT& m)
      : size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) {
    if (!size_) return;
    storage_type* it = &items_[0];
    for (const auto& entry : m) {
      *it++ = &entry;
    }
    std::sort(&items_[0], &items_[size_],
              [](const storage_type& a, const storage_type& b) {
                return a->first < b->first;
              });
  }
  size_t size() const { return size_; }
  const_iterator begin() const { return {items_.get()}; }
  const_iterator end() const { return {items_.get() + size_}; }

 private:
  size_t size_;
  std::unique_ptr<storage_type[]> items_;
};

}  // namespace internal
}  // namespace protobuf
}  // namespace google

#include <google/protobuf/port_undef.inc>

#endif  // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
