// 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_FIELD_LITE_H__
#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__

#include <type_traits>

#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/port.h"
#include "google/protobuf/map.h"
#include "google/protobuf/map_entry_lite.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 {

#ifndef NDEBUG
void MapFieldLiteNotDestructed(void* map_field_lite);
#endif

// This class provides access to map field using generated api. It is used for
// internal generated message implementation only. Users should never use this
// directly.
template <typename Derived, typename Key, typename T,
          WireFormatLite::FieldType key_wire_type,
          WireFormatLite::FieldType value_wire_type>
class MapFieldLite {
  // Define message type for internal repeated field.
  typedef Derived EntryType;

 public:
  typedef Map<Key, T> MapType;

  constexpr MapFieldLite() : map_() {}
  explicit MapFieldLite(Arena* arena) : map_(arena) {}
  MapFieldLite(ArenaInitialized, Arena* arena) : MapFieldLite(arena) {}

#ifdef NDEBUG
  void Destruct() { map_.~Map(); }
  ~MapFieldLite() {}
#else
  void Destruct() {
    // We want to destruct the map in such a way that we can verify
    // that we've done that, but also be sure that we've deallocated
    // everything (as opposed to leaving an allocation behind with no
    // data in it, as would happen if a vector was resize'd to zero.
    // Map::Swap with an empty map accomplishes that.
    decltype(map_) swapped_map(map_.arena());
    map_.InternalSwap(&swapped_map);
  }
  ~MapFieldLite() {
    if (map_.arena() == nullptr && !map_.empty()) {
      MapFieldLiteNotDestructed(this);
    }
  }
#endif
  // Accessors
  const Map<Key, T>& GetMap() const { return map_; }
  Map<Key, T>* MutableMap() { return &map_; }

  // Convenient methods for generated message implementation.
  int size() const { return static_cast<int>(map_.size()); }
  void Clear() { return map_.clear(); }
  void MergeFrom(const MapFieldLite& other) {
    for (typename Map<Key, T>::const_iterator it = other.map_.begin();
         it != other.map_.end(); ++it) {
      map_[it->first] = it->second;
    }
  }
  void Swap(MapFieldLite* other) { map_.swap(other->map_); }
  void InternalSwap(MapFieldLite* other) { map_.InternalSwap(&other->map_); }

  // Used in the implementation of parsing. Caller should take the ownership iff
  // arena_ is nullptr.
  EntryType* NewEntry() const {
    return Arena::CreateMessage<EntryType>(map_.arena());
  }

  const char* _InternalParse(const char* ptr, ParseContext* ctx) {
    typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this);
    return parser._InternalParse(ptr, ctx);
  }

  template <typename UnknownType>
  const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
                                      bool (*is_valid)(int), uint32_t field_num,
                                      InternalMetadata* metadata) {
    typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this);
    return parser.template ParseWithEnumValidation<UnknownType>(
        ptr, ctx, is_valid, field_num, metadata);
  }

 private:
  typedef void DestructorSkippable_;

  // map_ is inside an anonymous union so we can explicitly control its
  // destruction
  union {
    Map<Key, T> map_;
  };

  friend class ::PROTOBUF_NAMESPACE_ID::Arena;
};

template <typename UnknownType, typename T>
struct EnumParseWrapper {
  const char* _InternalParse(const char* ptr, ParseContext* ctx) {
    return map_field->template ParseWithEnumValidation<UnknownType>(
        ptr, ctx, is_valid, field_num, metadata);
  }
  T* map_field;
  bool (*is_valid)(int);
  uint32_t field_num;
  InternalMetadata* metadata;
};

// Helper function because the typenames of maps are horrendous to print. This
// leverages compiler type deduction, to keep all type data out of the
// generated code
template <typename UnknownType, typename T>
EnumParseWrapper<UnknownType, T> InitEnumParseWrapper(
    T* map_field, bool (*is_valid)(int), uint32_t field_num,
    InternalMetadata* metadata) {
  return EnumParseWrapper<UnknownType, T>{map_field, is_valid, field_num,
                                          metadata};
}

// True if IsInitialized() is true for value field in all elements of t. T is
// expected to be message.  It's useful to have this helper here to keep the
// protobuf compiler from ever having to emit loops in IsInitialized() methods.
// We want the C++ compiler to inline this or not as it sees fit.
template <typename Derived, typename Key, typename T,
          WireFormatLite::FieldType key_wire_type,
          WireFormatLite::FieldType value_wire_type>
bool AllAreInitialized(const MapFieldLite<Derived, Key, T, key_wire_type,
                                          value_wire_type>& field) {
  const auto& t = field.GetMap();
  for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
       ++it) {
    if (!it->second.IsInitialized()) return false;
  }
  return true;
}

template <typename MEntry>
struct MapEntryToMapField : MapEntryToMapField<typename MEntry::SuperType> {};

template <typename T, typename Key, typename Value,
          WireFormatLite::FieldType kKeyFieldType,
          WireFormatLite::FieldType kValueFieldType>
struct MapEntryToMapField<
    MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>> {
  typedef MapFieldLite<
      MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>, Key, Value,
      kKeyFieldType, kValueFieldType>
      MapFieldType;
};

#ifndef NDEBUG
inline PROTOBUF_NOINLINE void MapFieldLiteNotDestructed(void* map_field_lite) {
  bool proper_destruct = false;
  GOOGLE_CHECK(proper_destruct) << map_field_lite;
}
#endif

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

#include "google/protobuf/port_undef.inc"

#endif  // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
