// 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.

// This file defines the map container and its helpers to support protobuf maps.
//
// The Map and MapIterator types are provided by this header file.
// Please avoid using other types defined here, unless they are public
// types within Map or MapIterator, such as Map::value_type.

#ifndef GOOGLE_PROTOBUF_MAP_H__
#define GOOGLE_PROTOBUF_MAP_H__


#include <algorithm>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <limits>  // To support Visual Studio 2008
#include <map>
#include <string>
#include <type_traits>
#include <utility>

#if defined(__cpp_lib_string_view)
#include <string_view>
#endif  // defined(__cpp_lib_string_view)

#if !defined(GOOGLE_PROTOBUF_NO_RDTSC) && defined(__APPLE__)
#include <mach/mach_time.h>
#endif

#include "google/protobuf/stubs/common.h"
#include "google/protobuf/arena.h"
#include "google/protobuf/generated_enum_util.h"
#include "google/protobuf/map_type_handler.h"
#include "google/protobuf/port.h"


#ifdef SWIG
#error "You cannot SWIG proto headers"
#endif

// Must be included last.
#include "google/protobuf/port_def.inc"

namespace google {
namespace protobuf {

template <typename Key, typename T>
class Map;

class MapIterator;

template <typename Enum>
struct is_proto_enum;

namespace internal {
template <typename Derived, typename Key, typename T,
          WireFormatLite::FieldType key_wire_type,
          WireFormatLite::FieldType value_wire_type>
class MapFieldLite;

template <typename Derived, typename Key, typename T,
          WireFormatLite::FieldType key_wire_type,
          WireFormatLite::FieldType value_wire_type>
class MapField;

template <typename Key, typename T>
class TypeDefinedMapFieldBase;

class DynamicMapField;

class GeneratedMessageReflection;

// re-implement std::allocator to use arena allocator for memory allocation.
// Used for Map implementation. Users should not use this class
// directly.
template <typename U>
class MapAllocator {
 public:
  using value_type = U;
  using pointer = value_type*;
  using const_pointer = const value_type*;
  using reference = value_type&;
  using const_reference = const value_type&;
  using size_type = size_t;
  using difference_type = ptrdiff_t;

  constexpr MapAllocator() : arena_(nullptr) {}
  explicit constexpr MapAllocator(Arena* arena) : arena_(arena) {}
  template <typename X>
  MapAllocator(const MapAllocator<X>& allocator)  // NOLINT(runtime/explicit)
      : arena_(allocator.arena()) {}

  // MapAllocator does not support alignments beyond 8. Technically we should
  // support up to std::max_align_t, but this fails with ubsan and tcmalloc
  // debug allocation logic which assume 8 as default alignment.
  static_assert(alignof(value_type) <= 8, "");

  pointer allocate(size_type n, const void* /* hint */ = nullptr) {
    // If arena is not given, malloc needs to be called which doesn't
    // construct element object.
    if (arena_ == nullptr) {
      return static_cast<pointer>(::operator new(n * sizeof(value_type)));
    } else {
      return reinterpret_cast<pointer>(
          Arena::CreateArray<uint8_t>(arena_, n * sizeof(value_type)));
    }
  }

  void deallocate(pointer p, size_type n) {
    if (arena_ == nullptr) {
      internal::SizedDelete(p, n * sizeof(value_type));
    }
  }

#if !defined(GOOGLE_PROTOBUF_OS_APPLE) && !defined(GOOGLE_PROTOBUF_OS_NACL) && \
    !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN)
  template <class NodeType, class... Args>
  void construct(NodeType* p, Args&&... args) {
    // Clang 3.6 doesn't compile static casting to void* directly. (Issue
    // #1266) According C++ standard 5.2.9/1: "The static_cast operator shall
    // not cast away constness". So first the maybe const pointer is casted to
    // const void* and after the const void* is const casted.
    new (const_cast<void*>(static_cast<const void*>(p)))
        NodeType(std::forward<Args>(args)...);
  }

  template <class NodeType>
  void destroy(NodeType* p) {
    p->~NodeType();
  }
#else
  void construct(pointer p, const_reference t) { new (p) value_type(t); }

  void destroy(pointer p) { p->~value_type(); }
#endif

  template <typename X>
  struct rebind {
    using other = MapAllocator<X>;
  };

  template <typename X>
  bool operator==(const MapAllocator<X>& other) const {
    return arena_ == other.arena_;
  }

  template <typename X>
  bool operator!=(const MapAllocator<X>& other) const {
    return arena_ != other.arena_;
  }

  // To support Visual Studio 2008
  size_type max_size() const {
    // parentheses around (std::...:max) prevents macro warning of max()
    return (std::numeric_limits<size_type>::max)();
  }

  // To support gcc-4.4, which does not properly
  // support templated friend classes
  Arena* arena() const { return arena_; }

 private:
  using DestructorSkippable_ = void;
  Arena* arena_;
};

// To save on binary size and simplify generic uses of the map types we collapse
// signed/unsigned versions of the same sized integer to the unsigned version.
template <typename T, typename = void>
struct KeyForBaseImpl {
  using type = T;
};
template <typename T>
struct KeyForBaseImpl<T, std::enable_if_t<std::is_integral<T>::value &&
                                          std::is_signed<T>::value>> {
  using type = std::make_unsigned_t<T>;
};
template <typename T>
using KeyForBase = typename KeyForBaseImpl<T>::type;

// Default case: Not transparent.
// We use std::hash<key_type>/std::less<key_type> and all the lookup functions
// only accept `key_type`.
template <typename key_type>
struct TransparentSupport {
  using hash = std::hash<key_type>;
  using less = std::less<key_type>;

  static bool Equals(const key_type& a, const key_type& b) { return a == b; }

  template <typename K>
  using key_arg = key_type;
};

#if defined(__cpp_lib_string_view)
// If std::string_view is available, we add transparent support for std::string
// keys. We use std::hash<std::string_view> as it supports the input types we
// care about. The lookup functions accept arbitrary `K`. This will include any
// key type that is convertible to std::string_view.
template <>
struct TransparentSupport<std::string> {
  static std::string_view ImplicitConvert(std::string_view str) { return str; }
  // If the element is not convertible to std::string_view, try to convert to
  // std::string first.
  // The template makes this overload lose resolution when both have the same
  // rank otherwise.
  template <typename = void>
  static std::string_view ImplicitConvert(const std::string& str) {
    return str;
  }

  struct hash : private std::hash<std::string_view> {
    using is_transparent = void;

    template <typename T>
    size_t operator()(const T& str) const {
      return base()(ImplicitConvert(str));
    }

   private:
    const std::hash<std::string_view>& base() const { return *this; }
  };
  struct less {
    using is_transparent = void;

    template <typename T, typename U>
    bool operator()(const T& t, const U& u) const {
      return ImplicitConvert(t) < ImplicitConvert(u);
    }
  };

  template <typename T, typename U>
  static bool Equals(const T& t, const U& u) {
    return ImplicitConvert(t) == ImplicitConvert(u);
  }

  template <typename K>
  using key_arg = K;
};
#endif  // defined(__cpp_lib_string_view)

struct NodeBase {
  // Align the node to allow KeyNode to predict the location of the key.
  // This way sizeof(NodeBase) contains any possible padding it was going to
  // have between NodeBase and the key.
  alignas(int64_t) alignas(double) alignas(void*) NodeBase* next;
};

inline NodeBase* EraseFromLinkedList(NodeBase* item, NodeBase* head) {
  if (head == item) {
    return head->next;
  } else {
    head->next = EraseFromLinkedList(item, head->next);
    return head;
  }
}

inline bool TableEntryIsTooLong(NodeBase* node) {
  const size_t kMaxLength = 8;
  size_t count = 0;
  do {
    ++count;
    node = node->next;
  } while (node != nullptr);
  // Invariant: no linked list ever is more than kMaxLength in length.
  GOOGLE_ABSL_DCHECK_LE(count, kMaxLength);
  return count >= kMaxLength;
}

template <typename T>
using KeyForTree = std::conditional_t<std::is_integral<T>::value, uint64_t,
                                      std::reference_wrapper<const T>>;

template <typename T>
using LessForTree = typename TransparentSupport<
    std::conditional_t<std::is_integral<T>::value, uint64_t, T>>::less;

template <typename Key>
using TreeForMap =
    std::map<KeyForTree<Key>, NodeBase*, LessForTree<Key>,
             MapAllocator<std::pair<const KeyForTree<Key>, NodeBase*>>>;

// Type safe tagged pointer.
// We convert to/from nodes and trees using the operations below.
// They ensure that the tags are used correctly.
// There are three states:
//  - x == 0: the entry is empty
//  - x != 0 && (x&1) == 0: the entry is a node list
//  - x != 0 && (x&1) == 1: the entry is a tree
enum class TableEntryPtr : uintptr_t;

inline bool TableEntryIsEmpty(TableEntryPtr entry) {
  return entry == TableEntryPtr{};
}
inline bool TableEntryIsTree(TableEntryPtr entry) {
  return (static_cast<uintptr_t>(entry) & 1) == 1;
}
inline bool TableEntryIsList(TableEntryPtr entry) {
  return !TableEntryIsTree(entry);
}
inline bool TableEntryIsNonEmptyList(TableEntryPtr entry) {
  return !TableEntryIsEmpty(entry) && TableEntryIsList(entry);
}
inline NodeBase* TableEntryToNode(TableEntryPtr entry) {
  GOOGLE_ABSL_DCHECK(TableEntryIsList(entry));
  return reinterpret_cast<NodeBase*>(static_cast<uintptr_t>(entry));
}
inline TableEntryPtr NodeToTableEntry(NodeBase* node) {
  GOOGLE_ABSL_DCHECK((reinterpret_cast<uintptr_t>(node) & 1) == 0);
  return static_cast<TableEntryPtr>(reinterpret_cast<uintptr_t>(node));
}
template <typename Tree>
Tree* TableEntryToTree(TableEntryPtr entry) {
  GOOGLE_ABSL_DCHECK(TableEntryIsTree(entry));
  return reinterpret_cast<Tree*>(static_cast<uintptr_t>(entry) - 1);
}
template <typename Tree>
TableEntryPtr TreeToTableEntry(Tree* node) {
  GOOGLE_ABSL_DCHECK((reinterpret_cast<uintptr_t>(node) & 1) == 0);
  return static_cast<TableEntryPtr>(reinterpret_cast<uintptr_t>(node) | 1);
}

// This captures all numeric types.
inline size_t MapValueSpaceUsedExcludingSelfLong(bool) { return 0; }
inline size_t MapValueSpaceUsedExcludingSelfLong(const std::string& str) {
  return StringSpaceUsedExcludingSelfLong(str);
}
template <typename T,
          typename = decltype(std::declval<const T&>().SpaceUsedLong())>
size_t MapValueSpaceUsedExcludingSelfLong(const T& message) {
  return message.SpaceUsedLong() - sizeof(T);
}

constexpr size_t kGlobalEmptyTableSize = 1;
PROTOBUF_EXPORT extern const TableEntryPtr
    kGlobalEmptyTable[kGlobalEmptyTableSize];

// Space used for the table, trees, and nodes.
// Does not include the indirect space used. Eg the data of a std::string.
template <typename Key>
PROTOBUF_NOINLINE size_t SpaceUsedInTable(TableEntryPtr* table,
                                          size_t num_buckets,
                                          size_t num_elements,
                                          size_t sizeof_node) {
  size_t size = 0;
  // The size of the table.
  size += sizeof(void*) * num_buckets;
  // All the nodes.
  size += sizeof_node * num_elements;
  // For each tree, count the overhead of the those nodes.
  // Two buckets at a time because we only care about trees.
  for (size_t b = 0; b < num_buckets; ++b) {
    if (internal::TableEntryIsTree(table[b])) {
      using Tree = TreeForMap<Key>;
      Tree* tree = TableEntryToTree<Tree>(table[b]);
      // Estimated cost of the red-black tree nodes, 3 pointers plus a
      // bool (plus alignment, so 4 pointers).
      size += tree->size() *
              (sizeof(typename Tree::value_type) + sizeof(void*) * 4);
    }
  }
  return size;
}

template <typename Map,
          typename = typename std::enable_if<
              !std::is_scalar<typename Map::key_type>::value ||
              !std::is_scalar<typename Map::mapped_type>::value>::type>
size_t SpaceUsedInValues(const Map* map) {
  size_t size = 0;
  for (const auto& v : *map) {
    size += internal::MapValueSpaceUsedExcludingSelfLong(v.first) +
            internal::MapValueSpaceUsedExcludingSelfLong(v.second);
  }
  return size;
}

inline size_t SpaceUsedInValues(const void*) { return 0; }

// The value might be of different signedness, so use memcpy to extract it.
template <typename T, std::enable_if_t<std::is_integral<T>::value, int> = 0>
T ReadKey(const void* ptr) {
  T out;
  memcpy(&out, ptr, sizeof(T));
  return out;
}

template <typename T, std::enable_if_t<!std::is_integral<T>::value, int> = 0>
const T& ReadKey(const void* ptr) {
  return *reinterpret_cast<const T*>(ptr);
}

template <typename Key>
class KeyMapBase {
  using Allocator = internal::MapAllocator<void*>;
  static_assert(!std::is_signed<Key>::value || !std::is_integral<Key>::value,
                "");

 public:
  using size_type = size_t;
  using hasher = typename TransparentSupport<Key>::hash;

  explicit constexpr KeyMapBase(Arena* arena)
      : num_elements_(0),
        num_buckets_(internal::kGlobalEmptyTableSize),
        seed_(0),
        index_of_first_non_null_(internal::kGlobalEmptyTableSize),
        table_(const_cast<TableEntryPtr*>(internal::kGlobalEmptyTable)),
        alloc_(arena) {}

  KeyMapBase(const KeyMapBase&) = delete;
  KeyMapBase& operator=(const KeyMapBase&) = delete;

 protected:
  enum { kMinTableSize = 8 };

  struct KeyNode : NodeBase {
    static constexpr size_t kOffset = sizeof(NodeBase);
    decltype(auto) key() const {
      return ReadKey<Key>(reinterpret_cast<const char*>(this) + kOffset);
    }
  };

  // Trees. The payload type is a copy of Key, so that we can query the tree
  // with Keys that are not in any particular data structure.
  // The value is a void* pointing to Node. We use void* instead of Node* to
  // avoid code bloat. That way there is only one instantiation of the tree
  // class per key type.
  using Tree = internal::TreeForMap<Key>;
  using TreeIterator = typename Tree::iterator;

  class KeyIteratorBase {
   public:
    // Invariants:
    // node_ is always correct. This is handy because the most common
    // operations are operator* and operator-> and they only use node_.
    // When node_ is set to a non-null value, all the other non-const fields
    // are updated to be correct also, but those fields can become stale
    // if the underlying map is modified.  When those fields are needed they
    // are rechecked, and updated if necessary.
    KeyIteratorBase() : node_(nullptr), m_(nullptr), bucket_index_(0) {}

    explicit KeyIteratorBase(const KeyMapBase* m) : m_(m) {
      SearchFrom(m->index_of_first_non_null_);
    }

    KeyIteratorBase(KeyNode* n, const KeyMapBase* m, size_type index)
        : node_(n), m_(m), bucket_index_(index) {}

    KeyIteratorBase(TreeIterator tree_it, const KeyMapBase* m, size_type index)
        : node_(NodeFromTreeIterator(tree_it)), m_(m), bucket_index_(index) {}

    // Advance through buckets, looking for the first that isn't empty.
    // If nothing non-empty is found then leave node_ == nullptr.
    void SearchFrom(size_type start_bucket) {
      GOOGLE_ABSL_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ ||
                  !m_->TableEntryIsEmpty(m_->index_of_first_non_null_));
      for (size_type i = start_bucket; i < m_->num_buckets_; ++i) {
        TableEntryPtr entry = m_->table_[i];
        if (entry == TableEntryPtr{}) continue;
        bucket_index_ = i;
        if (PROTOBUF_PREDICT_TRUE(internal::TableEntryIsList(entry))) {
          node_ = static_cast<KeyNode*>(TableEntryToNode(entry));
        } else {
          Tree* tree = TableEntryToTree<Tree>(entry);
          GOOGLE_ABSL_DCHECK(!tree->empty());
          node_ = static_cast<KeyNode*>(tree->begin()->second);
        }
        return;
      }
      node_ = nullptr;
      bucket_index_ = 0;
    }

    friend bool operator==(const KeyIteratorBase& a, const KeyIteratorBase& b) {
      return a.node_ == b.node_;
    }
    friend bool operator!=(const KeyIteratorBase& a, const KeyIteratorBase& b) {
      return a.node_ != b.node_;
    }

    KeyIteratorBase& operator++() {
      if (node_->next == nullptr) {
        SearchFrom(bucket_index_ + 1);
      } else {
        node_ = static_cast<KeyNode*>(node_->next);
      }
      return *this;
    }

    KeyNode* node_;
    const KeyMapBase* m_;
    size_type bucket_index_;
  };

 public:
  Arena* arena() const { return this->alloc_.arena(); }

  void Swap(KeyMapBase* other) {
    std::swap(num_elements_, other->num_elements_);
    std::swap(num_buckets_, other->num_buckets_);
    std::swap(seed_, other->seed_);
    std::swap(index_of_first_non_null_, other->index_of_first_non_null_);
    std::swap(table_, other->table_);
    std::swap(alloc_, other->alloc_);
  }

  hasher hash_function() const { return {}; }

  static size_type max_size() {
    return static_cast<size_type>(1) << (sizeof(void**) >= 8 ? 60 : 28);
  }
  size_type size() const { return num_elements_; }
  bool empty() const { return size() == 0; }

 protected:
  PROTOBUF_NOINLINE void erase_no_destroy(size_type b, KeyNode* node) {
    TreeIterator tree_it;
    const bool is_list = revalidate_if_necessary(b, node, &tree_it);
    if (is_list) {
      GOOGLE_ABSL_DCHECK(TableEntryIsNonEmptyList(b));
      auto* head = TableEntryToNode(table_[b]);
      head = EraseFromLinkedList(node, head);
      table_[b] = NodeToTableEntry(head);
    } else {
      GOOGLE_ABSL_DCHECK(this->TableEntryIsTree(b));
      Tree* tree = internal::TableEntryToTree<Tree>(this->table_[b]);
      if (tree_it != tree->begin()) {
        auto* prev = std::prev(tree_it)->second;
        prev->next = prev->next->next;
      }
      tree->erase(tree_it);
      if (tree->empty()) {
        this->DestroyTree(tree);
        this->table_[b] = TableEntryPtr{};
      }
    }
    --num_elements_;
    if (PROTOBUF_PREDICT_FALSE(b == index_of_first_non_null_)) {
      while (index_of_first_non_null_ < num_buckets_ &&
             TableEntryIsEmpty(index_of_first_non_null_)) {
        ++index_of_first_non_null_;
      }
    }
  }

  struct NodeAndBucket {
    NodeBase* node;
    size_type bucket;
  };
  // TODO(sbenza): We can reduce duplication by coercing `K` to a common type.
  // Eg, for string keys we can coerce to string_view. Otherwise, we instantiate
  // this with all the different `char[N]` of the caller.
  template <typename K>
  NodeAndBucket FindHelper(const K& k, TreeIterator* it = nullptr) const {
    size_type b = BucketNumber(k);
    if (TableEntryIsNonEmptyList(b)) {
      auto* node = internal::TableEntryToNode(table_[b]);
      do {
        if (internal::TransparentSupport<Key>::Equals(
                static_cast<KeyNode*>(node)->key(), k)) {
          return {node, b};
        } else {
          node = node->next;
        }
      } while (node != nullptr);
    } else if (TableEntryIsTree(b)) {
      Tree* tree = internal::TableEntryToTree<Tree>(table_[b]);
      auto tree_it = tree->find(k);
      if (it != nullptr) *it = tree_it;
      if (tree_it != tree->end()) {
        return {tree_it->second, b};
      }
    }
    return {nullptr, b};
  }

  // Insert the given Node in bucket b.  If that would make bucket b too big,
  // and bucket b is not a tree, create a tree for buckets b.
  // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct
  // bucket.  num_elements_ is not modified.
  void InsertUnique(size_type b, KeyNode* node) {
    GOOGLE_ABSL_DCHECK(index_of_first_non_null_ == num_buckets_ ||
                !TableEntryIsEmpty(index_of_first_non_null_));
    // In practice, the code that led to this point may have already
    // determined whether we are inserting into an empty list, a short list,
    // or whatever.  But it's probably cheap enough to recompute that here;
    // it's likely that we're inserting into an empty or short list.
    GOOGLE_ABSL_DCHECK(FindHelper(node->key()).node == nullptr);
    if (TableEntryIsEmpty(b)) {
      InsertUniqueInList(b, node);
      index_of_first_non_null_ = (std::min)(index_of_first_non_null_, b);
    } else if (TableEntryIsNonEmptyList(b) && !TableEntryIsTooLong(b)) {
      InsertUniqueInList(b, node);
    } else {
      if (TableEntryIsNonEmptyList(b)) {
        TreeConvert(b);
      }
      GOOGLE_ABSL_DCHECK(TableEntryIsTree(b))
          << (void*)table_[b] << " " << (uintptr_t)table_[b];
      InsertUniqueInTree(b, node);
      index_of_first_non_null_ = (std::min)(index_of_first_non_null_, b);
    }
  }

  // Returns whether we should insert after the head of the list. For
  // non-optimized builds, we randomly decide whether to insert right at the
  // head of the list or just after the head. This helps add a little bit of
  // non-determinism to the map ordering.
  bool ShouldInsertAfterHead(void* node) {
#ifdef NDEBUG
    (void)node;
    return false;
#else
    // Doing modulo with a prime mixes the bits more.
    return (reinterpret_cast<uintptr_t>(node) ^ seed_) % 13 > 6;
#endif
  }

  // Helper for InsertUnique.  Handles the case where bucket b is a
  // not-too-long linked list.
  void InsertUniqueInList(size_type b, KeyNode* node) {
    if (!TableEntryIsEmpty(b) && ShouldInsertAfterHead(node)) {
      auto* first = TableEntryToNode(table_[b]);
      node->next = first->next;
      first->next = node;
    } else {
      node->next = TableEntryToNode(table_[b]);
      table_[b] = NodeToTableEntry(node);
    }
  }

  // Helper for InsertUnique.  Handles the case where bucket b points to a
  // Tree.
  void InsertUniqueInTree(size_type b, KeyNode* node) {
    auto* tree = TableEntryToTree<Tree>(table_[b]);
    auto it = tree->insert({node->key(), node}).first;
    // Maintain the linked list of the nodes in the tree.
    // For simplicity, they are in the same order as the tree iteration.
    if (it != tree->begin()) {
      auto* prev = std::prev(it)->second;
      prev->next = node;
    }
    auto next = std::next(it);
    node->next = next != tree->end() ? next->second : nullptr;
  }

  // Returns whether it did resize.  Currently this is only used when
  // num_elements_ increases, though it could be used in other situations.
  // It checks for load too low as well as load too high: because any number
  // of erases can occur between inserts, the load could be as low as 0 here.
  // Resizing to a lower size is not always helpful, but failing to do so can
  // destroy the expected big-O bounds for some operations. By having the
  // policy that sometimes we resize down as well as up, clients can easily
  // keep O(size()) = O(number of buckets) if they want that.
  bool ResizeIfLoadIsOutOfRange(size_type new_size) {
    const size_type kMaxMapLoadTimes16 = 12;  // controls RAM vs CPU tradeoff
    const size_type hi_cutoff = num_buckets_ * kMaxMapLoadTimes16 / 16;
    const size_type lo_cutoff = hi_cutoff / 4;
    // We don't care how many elements are in trees.  If a lot are,
    // we may resize even though there are many empty buckets.  In
    // practice, this seems fine.
    if (PROTOBUF_PREDICT_FALSE(new_size >= hi_cutoff)) {
      if (num_buckets_ <= max_size() / 2) {
        Resize(num_buckets_ * 2);
        return true;
      }
    } else if (PROTOBUF_PREDICT_FALSE(new_size <= lo_cutoff &&
                                      num_buckets_ > kMinTableSize)) {
      size_type lg2_of_size_reduction_factor = 1;
      // It's possible we want to shrink a lot here... size() could even be 0.
      // So, estimate how much to shrink by making sure we don't shrink so
      // much that we would need to grow the table after a few inserts.
      const size_type hypothetical_size = new_size * 5 / 4 + 1;
      while ((hypothetical_size << lg2_of_size_reduction_factor) < hi_cutoff) {
        ++lg2_of_size_reduction_factor;
      }
      size_type new_num_buckets = std::max<size_type>(
          kMinTableSize, num_buckets_ >> lg2_of_size_reduction_factor);
      if (new_num_buckets != num_buckets_) {
        Resize(new_num_buckets);
        return true;
      }
    }
    return false;
  }

  // Resize to the given number of buckets.
  void Resize(size_t new_num_buckets) {
    if (num_buckets_ == kGlobalEmptyTableSize) {
      // This is the global empty array.
      // Just overwrite with a new one. No need to transfer or free anything.
      num_buckets_ = index_of_first_non_null_ = kMinTableSize;
      table_ = CreateEmptyTable(num_buckets_);
      seed_ = Seed();
      return;
    }

    GOOGLE_ABSL_DCHECK_GE(new_num_buckets, kMinTableSize);
    const auto old_table = table_;
    const size_type old_table_size = num_buckets_;
    num_buckets_ = new_num_buckets;
    table_ = CreateEmptyTable(num_buckets_);
    const size_type start = index_of_first_non_null_;
    index_of_first_non_null_ = num_buckets_;
    for (size_type i = start; i < old_table_size; ++i) {
      if (internal::TableEntryIsNonEmptyList(old_table[i])) {
        TransferList(static_cast<KeyNode*>(TableEntryToNode(old_table[i])));
      } else if (internal::TableEntryIsTree(old_table[i])) {
        TransferTree(TableEntryToTree<Tree>(old_table[i]));
      }
    }
    Dealloc<TableEntryPtr>(old_table, old_table_size);
  }

  // Transfer all nodes in the list `node` into `this`.
  void TransferList(KeyNode* node) {
    do {
      auto* next = static_cast<KeyNode*>(node->next);
      InsertUnique(BucketNumber(node->key()), node);
      node = next;
    } while (node != nullptr);
  }

  // Transfer all nodes in the tree `tree` into `this` and destroy the tree.
  void TransferTree(Tree* tree) {
    auto* node = tree->begin()->second;
    DestroyTree(tree);
    TransferList(static_cast<KeyNode*>(node));
  }

  bool TableEntryIsEmpty(size_type b) const {
    return internal::TableEntryIsEmpty(table_[b]);
  }
  bool TableEntryIsNonEmptyList(size_type b) const {
    return internal::TableEntryIsNonEmptyList(table_[b]);
  }
  bool TableEntryIsTree(size_type b) const {
    return internal::TableEntryIsTree(table_[b]);
  }
  bool TableEntryIsList(size_type b) const {
    return internal::TableEntryIsList(table_[b]);
  }

  void TreeConvert(size_type b) {
    GOOGLE_ABSL_DCHECK(!TableEntryIsTree(b));
    Tree* tree =
        Arena::Create<Tree>(alloc_.arena(), typename Tree::key_compare(),
                            typename Tree::allocator_type(alloc_));
    size_type count = CopyListToTree(b, tree);
    GOOGLE_ABSL_DCHECK_EQ(count, tree->size());
    table_[b] = TreeToTableEntry(tree);
    // Relink the nodes.
    NodeBase* next = nullptr;
    auto it = tree->end();
    do {
      auto* node = (--it)->second;
      node->next = next;
      next = node;
    } while (it != tree->begin());
  }

  // Copy a linked list in the given bucket to a tree.
  // Returns the number of things it copied.
  size_type CopyListToTree(size_type b, Tree* tree) {
    size_type count = 0;
    auto* node = TableEntryToNode(table_[b]);
    while (node != nullptr) {
      tree->insert({static_cast<KeyNode*>(node)->key(), node});
      ++count;
      auto* next = node->next;
      node->next = nullptr;
      node = next;
    }
    return count;
  }

  // Return whether table_[b] is a linked list that seems awfully long.
  // Requires table_[b] to point to a non-empty linked list.
  bool TableEntryIsTooLong(size_type b) {
    return internal::TableEntryIsTooLong(TableEntryToNode(table_[b]));
  }

  template <typename K>
  size_type BucketNumber(const K& k) const {
    // We xor the hash value against the random seed so that we effectively
    // have a random hash function.
    uint64_t h = hash_function()(k) ^ seed_;

    // We use the multiplication method to determine the bucket number from
    // the hash value. The constant kPhi (suggested by Knuth) is roughly
    // (sqrt(5) - 1) / 2 * 2^64.
    constexpr uint64_t kPhi = uint64_t{0x9e3779b97f4a7c15};
    return ((kPhi * h) >> 32) & (num_buckets_ - 1);
  }

  // Return a power of two no less than max(kMinTableSize, n).
  // Assumes either n < kMinTableSize or n is a power of two.
  size_type TableSize(size_type n) {
    return n < static_cast<size_type>(kMinTableSize)
               ? static_cast<size_type>(kMinTableSize)
               : n;
  }

  // Use alloc_ to allocate an array of n objects of type U.
  template <typename U>
  U* Alloc(size_type n) {
    using alloc_type = typename Allocator::template rebind<U>::other;
    return alloc_type(alloc_).allocate(n);
  }

  // Use alloc_ to deallocate an array of n objects of type U.
  template <typename U>
  void Dealloc(U* t, size_type n) {
    using alloc_type = typename Allocator::template rebind<U>::other;
    alloc_type(alloc_).deallocate(t, n);
  }

  void DestroyTree(Tree* tree) {
    if (alloc_.arena() == nullptr) {
      delete tree;
    }
  }

  TableEntryPtr* CreateEmptyTable(size_type n) {
    GOOGLE_ABSL_DCHECK(n >= kMinTableSize);
    GOOGLE_ABSL_DCHECK_EQ(n & (n - 1), 0u);
    TableEntryPtr* result = Alloc<TableEntryPtr>(n);
    memset(result, 0, n * sizeof(result[0]));
    return result;
  }

  // Return a randomish value.
  size_type Seed() const {
    // We get a little bit of randomness from the address of the map. The
    // lower bits are not very random, due to alignment, so we discard them
    // and shift the higher bits into their place.
    size_type s = reinterpret_cast<uintptr_t>(this) >> 4;
#if !defined(GOOGLE_PROTOBUF_NO_RDTSC)
#if defined(__APPLE__)
    // Use a commpage-based fast time function on Apple environments (MacOS,
    // iOS, tvOS, watchOS, etc).
    s += mach_absolute_time();
#elif defined(__x86_64__) && defined(__GNUC__)
    uint32_t hi, lo;
    asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
    s += ((static_cast<uint64_t>(hi) << 32) | lo);
#elif defined(__aarch64__) && defined(__GNUC__)
    // There is no rdtsc on ARMv8. CNTVCT_EL0 is the virtual counter of the
    // system timer. It runs at a different frequency than the CPU's, but is
    // the best source of time-based entropy we get.
    uint64_t virtual_timer_value;
    asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
    s += virtual_timer_value;
#endif
#endif  // !defined(GOOGLE_PROTOBUF_NO_RDTSC)
    return s;
  }

  // Assumes node_ and m_ are correct and non-null, but other fields may be
  // stale.  Fix them as needed.  Then return true iff node_ points to a
  // Node in a list.  If false is returned then *it is modified to be
  // a valid iterator for node_.
  bool revalidate_if_necessary(size_t& bucket_index, KeyNode* node,
                               TreeIterator* it) const {
    // Force bucket_index to be in range.
    bucket_index &= (num_buckets_ - 1);
    // Common case: the bucket we think is relevant points to `node`.
    if (table_[bucket_index] == NodeToTableEntry(node)) return true;
    // Less common: the bucket is a linked list with node_ somewhere in it,
    // but not at the head.
    if (TableEntryIsNonEmptyList(bucket_index)) {
      auto* l = TableEntryToNode(table_[bucket_index]);
      while ((l = l->next) != nullptr) {
        if (l == node) {
          return true;
        }
      }
    }
    // Well, bucket_index_ still might be correct, but probably
    // not.  Revalidate just to be sure.  This case is rare enough that we
    // don't worry about potential optimizations, such as having a custom
    // find-like method that compares Node* instead of the key.
    auto res = FindHelper(node->key(), it);
    bucket_index = res.bucket;
    return TableEntryIsList(bucket_index);
  }

  size_type num_elements_;
  size_type num_buckets_;
  size_type seed_;
  size_type index_of_first_non_null_;
  TableEntryPtr* table_;  // an array with num_buckets_ entries
  Allocator alloc_;
};

}  // namespace internal

#ifdef PROTOBUF_FUTURE_MAP_PAIR_UPGRADE
// This is the class for Map's internal value_type.
template <typename Key, typename T>
using MapPair = std::pair<const Key, T>;
#else
// This is the class for Map's internal value_type. Instead of using
// std::pair as value_type, we use this class which provides us more control of
// its process of construction and destruction.
template <typename Key, typename T>
struct PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG MapPair {
  using first_type = const Key;
  using second_type = T;

  MapPair(const Key& other_first, const T& other_second)
      : first(other_first), second(other_second) {}
  explicit MapPair(const Key& other_first) : first(other_first), second() {}
  explicit MapPair(Key&& other_first)
      : first(std::move(other_first)), second() {}
  MapPair(const MapPair& other) : first(other.first), second(other.second) {}

  ~MapPair() {}

  // Implicitly convertible to std::pair of compatible types.
  template <typename T1, typename T2>
  operator std::pair<T1, T2>() const {  // NOLINT(runtime/explicit)
    return std::pair<T1, T2>(first, second);
  }

  const Key first;
  T second;

 private:
  friend class Arena;
  friend class Map<Key, T>;
};
#endif

// Map is an associative container type used to store protobuf map
// fields.  Each Map instance may or may not use a different hash function, a
// different iteration order, and so on.  E.g., please don't examine
// implementation details to decide if the following would work:
//  Map<int, int> m0, m1;
//  m0[0] = m1[0] = m0[1] = m1[1] = 0;
//  assert(m0.begin()->first == m1.begin()->first);  // Bug!
//
// Map's interface is similar to std::unordered_map, except that Map is not
// designed to play well with exceptions.
template <typename Key, typename T>
class Map {
 public:
  using key_type = Key;
  using mapped_type = T;
  using init_type = std::pair<Key, T>;
  using value_type = MapPair<Key, T>;

  using pointer = value_type*;
  using const_pointer = const value_type*;
  using reference = value_type&;
  using const_reference = const value_type&;

  using size_type = size_t;
  using hasher = typename internal::TransparentSupport<Key>::hash;

  constexpr Map() : elements_(nullptr) {}
  explicit Map(Arena* arena) : elements_(arena) {}

  Map(const Map& other) : Map() { insert(other.begin(), other.end()); }

  Map(Map&& other) noexcept : Map() {
    if (other.arena() != nullptr) {
      *this = other;
    } else {
      swap(other);
    }
  }

  Map& operator=(Map&& other) noexcept {
    if (this != &other) {
      if (arena() != other.arena()) {
        *this = other;
      } else {
        swap(other);
      }
    }
    return *this;
  }

  template <class InputIt>
  Map(const InputIt& first, const InputIt& last) : Map() {
    insert(first, last);
  }

  ~Map() {}

 private:
  template <typename P>
  struct SameAsElementReference
      : std::is_same<typename std::remove_cv<
                         typename std::remove_reference<reference>::type>::type,
                     typename std::remove_cv<
                         typename std::remove_reference<P>::type>::type> {};

  template <class P>
  using RequiresInsertable =
      typename std::enable_if<std::is_convertible<P, init_type>::value ||
                                  SameAsElementReference<P>::value,
                              int>::type;
  template <class P>
  using RequiresNotInit =
      typename std::enable_if<!std::is_same<P, init_type>::value, int>::type;

  using Allocator = internal::MapAllocator<void*>;

  // InnerMap is a generic hash-based map.  It doesn't contain any
  // protocol-buffer-specific logic.  It is a chaining hash map with the
  // additional feature that some buckets can be converted to use an ordered
  // container.  This ensures O(lg n) bounds on find, insert, and erase, while
  // avoiding the overheads of ordered containers most of the time.
  //
  // The implementation doesn't need the full generality of unordered_map,
  // and it doesn't have it.  More bells and whistles can be added as needed.
  // Some implementation details:
  // 1. The hash function has type hasher and the equality function
  //    equal_to<Key>.  We inherit from hasher to save space
  //    (empty-base-class optimization).
  // 2. The number of buckets is a power of two.
  // 3. Buckets are converted to trees in pairs: if we convert bucket b then
  //    buckets b and b^1 will share a tree.  Invariant: buckets b and b^1 have
  //    the same non-null value iff they are sharing a tree.  (An alternative
  //    implementation strategy would be to have a tag bit per bucket.)
  // 4. As is typical for hash_map and such, the Keys and Values are always
  //    stored in linked list nodes.  Pointers to elements are never invalidated
  //    until the element is deleted.
  // 5. The trees' payload type is pointer to linked-list node.  Tree-converting
  //    a bucket doesn't copy Key-Value pairs.
  // 6. Once we've tree-converted a bucket, it is never converted back. However,
  //    the items a tree contains may wind up assigned to trees or lists upon a
  //    rehash.
  // 7. The code requires no C++ features from C++14 or later.
  // 8. Mutations to a map do not invalidate the map's iterators, pointers to
  //    elements, or references to elements.
  // 9. Except for erase(iterator), any non-const method can reorder iterators.
  // 10. InnerMap uses KeyForTree<Key> when using the Tree representation, which
  //    is either `Key`, if Key is a scalar, or `reference_wrapper<const Key>`
  //    otherwise. This avoids unnecessary copies of string keys, for example.
  class InnerMap : public internal::KeyMapBase<internal::KeyForBase<Key>> {
   public:
    explicit constexpr InnerMap(Arena* arena) : InnerMap::KeyMapBase(arena) {}

    InnerMap(const InnerMap&) = delete;
    InnerMap& operator=(const InnerMap&) = delete;

    ~InnerMap() {
      if (this->alloc_.arena() == nullptr &&
          this->num_buckets_ != internal::kGlobalEmptyTableSize) {
        clear();
        this->template Dealloc<TableEntryPtr>(this->table_, this->num_buckets_);
      }
    }

   private:
    // Linked-list nodes, as one would expect for a chaining hash table.
    struct Node : InnerMap::KeyMapBase::KeyNode {
      value_type kv;
    };

    using Tree = internal::TreeForMap<Key>;
    using TreeIterator = typename Tree::iterator;

    static Node* NodeFromTreeIterator(TreeIterator it) {
      static_assert(PROTOBUF_FIELD_OFFSET(Node, kv.first) ==
                        InnerMap::KeyMapBase::KeyNode::kOffset,
                    "");
      return static_cast<Node*>(it->second);
    }

    using TableEntryPtr = internal::TableEntryPtr;

    // iterator and const_iterator are instantiations of iterator_base.
    template <typename KeyValueType>
    class iterator_base : public InnerMap::KeyMapBase::KeyIteratorBase {
      using Base = typename InnerMap::KeyMapBase::KeyIteratorBase;

     public:
      using reference = KeyValueType&;
      using pointer = KeyValueType*;

      using Base::Base;
      iterator_base() = default;
      // Any iterator_base can convert to any other.  This is overkill, and we
      // rely on the enclosing class to use it wisely.  The standard "iterator
      // can convert to const_iterator" is OK but the reverse direction is not.
      iterator_base(const Base& base) : Base(base) {}  // NOLINT

      reference operator*() const {
        return static_cast<Node*>(this->node_)->kv;
      }
      pointer operator->() const { return &(operator*()); }
    };

   public:
    using iterator = iterator_base<value_type>;
    using const_iterator = iterator_base<const value_type>;

    iterator begin() { return iterator(this); }
    iterator end() { return iterator(); }
    const_iterator begin() const { return const_iterator(this); }
    const_iterator end() const { return const_iterator(); }

    void clear() {
      for (size_type b = 0; b < this->num_buckets_; b++) {
        internal::NodeBase* node;
        if (this->TableEntryIsNonEmptyList(b)) {
          node = internal::TableEntryToNode(this->table_[b]);
          this->table_[b] = TableEntryPtr{};
        } else if (this->TableEntryIsTree(b)) {
          Tree* tree = internal::TableEntryToTree<Tree>(this->table_[b]);
          this->table_[b] = TableEntryPtr{};
          node = NodeFromTreeIterator(tree->begin());
          this->DestroyTree(tree);
        } else {
          continue;
        }
        do {
          auto* next = node->next;
          DestroyNode(static_cast<Node*>(node));
          node = next;
        } while (node != nullptr);
      }
      this->num_elements_ = 0;
      this->index_of_first_non_null_ = this->num_buckets_;
    }

    template <typename K>
    iterator find(const K& k) {
      auto res = this->FindHelper(k);
      return iterator(static_cast<Node*>(res.node), this, res.bucket);
    }

    template <typename K>
    const_iterator find(const K& k) const {
      auto res = this->FindHelper(k);
      return const_iterator(static_cast<Node*>(res.node), this, res.bucket);
    }

    // Inserts a new element into the container if there is no element with the
    // key in the container.
    // The new element is:
    //  (1) Constructed in-place with the given args, if mapped_type is not
    //      arena constructible.
    //  (2) Constructed in-place with the arena and then assigned with a
    //      mapped_type temporary constructed with the given args, otherwise.
    template <typename K, typename... Args>
    std::pair<iterator, bool> try_emplace(K&& k, Args&&... args) {
      return ArenaAwareTryEmplace(Arena::is_arena_constructable<mapped_type>(),
                                  std::forward<K>(k),
                                  std::forward<Args>(args)...);
    }

    // Inserts the key into the map, if not present. In that case, the value
    // will be value initialized.
    template <typename K>
    std::pair<iterator, bool> insert(K&& k) {
      return try_emplace(std::forward<K>(k));
    }

    template <typename K>
    value_type& operator[](K&& k) {
      return *try_emplace(std::forward<K>(k)).first;
    }

    void erase(iterator it) {
      GOOGLE_ABSL_DCHECK_EQ(it.m_, this);
      auto* node = static_cast<Node*>(it.node_);
      this->erase_no_destroy(it.bucket_index_, node);
      DestroyNode(node);
    }

    size_t SpaceUsedInternal() const {
      return internal::SpaceUsedInTable<Key>(this->table_, this->num_buckets_,
                                             this->num_elements_, sizeof(Node));
    }

   private:
    template <typename K, typename... Args>
    std::pair<iterator, bool> TryEmplaceInternal(K&& k, Args&&... args) {
      auto p = this->FindHelper(k);
      // Case 1: key was already present.
      if (p.node != nullptr)
        return std::make_pair(
            iterator(static_cast<Node*>(p.node), this, p.bucket), false);
      // Case 2: insert.
      if (this->ResizeIfLoadIsOutOfRange(this->num_elements_ + 1)) {
        p = this->FindHelper(k);
      }
      const size_type b = p.bucket;  // bucket number
      // If K is not key_type, make the conversion to key_type explicit.
      using TypeToInit = typename std::conditional<
          std::is_same<typename std::decay<K>::type, key_type>::value, K&&,
          key_type>::type;
      Node* node = this->template Alloc<Node>(1);
      // Even when arena is nullptr, CreateInArenaStorage is still used to
      // ensure the arena of submessage will be consistent.
      Arena::CreateInArenaStorage(const_cast<Key*>(&node->kv.first),
                                  this->alloc_.arena(),
                                  static_cast<TypeToInit>(std::forward<K>(k)));
      // Note: if `T` is arena constructible, `Args` needs to be empty.
      Arena::CreateInArenaStorage(&node->kv.second, this->alloc_.arena(),
                                  std::forward<Args>(args)...);

      this->InsertUnique(b, node);
      ++this->num_elements_;
      return std::make_pair(iterator(node, this, b), true);
    }

    // A helper function to perform an assignment of `mapped_type`.
    // If the first argument is true, then it is a regular assignment.
    // Otherwise, we first create a temporary and then perform an assignment.
    template <typename V>
    static void AssignMapped(std::true_type, mapped_type& mapped, V&& v) {
      mapped = std::forward<V>(v);
    }
    template <typename... Args>
    static void AssignMapped(std::false_type, mapped_type& mapped,
                             Args&&... args) {
      mapped = mapped_type(std::forward<Args>(args)...);
    }

    // Case 1: `mapped_type` is arena constructible. A temporary object is
    // created and then (if `Args` are not empty) assigned to a mapped value
    // that was created with the arena.
    template <typename K>
    std::pair<iterator, bool> ArenaAwareTryEmplace(std::true_type, K&& k) {
      // case 1.1: "default" constructed (e.g. from arena only).
      return TryEmplaceInternal(std::forward<K>(k));
    }
    template <typename K, typename... Args>
    std::pair<iterator, bool> ArenaAwareTryEmplace(std::true_type, K&& k,
                                                   Args&&... args) {
      // case 1.2: "default" constructed + copy/move assignment
      auto p = TryEmplaceInternal(std::forward<K>(k));
      if (p.second) {
        AssignMapped(std::is_same<void(typename std::decay<Args>::type...),
                                  void(mapped_type)>(),
                     p.first->second, std::forward<Args>(args)...);
      }
      return p;
    }
    // Case 2: `mapped_type` is not arena constructible. Using in-place
    // construction.
    template <typename... Args>
    std::pair<iterator, bool> ArenaAwareTryEmplace(std::false_type,
                                                   Args&&... args) {
      return TryEmplaceInternal(std::forward<Args>(args)...);
    }

    void DestroyNode(Node* node) {
      if (this->alloc_.arena() == nullptr) {
        node->kv.first.~key_type();
        node->kv.second.~mapped_type();
        this->Dealloc(node, 1);
      }
    }

    friend class Arena;
    using InternalArenaConstructable_ = void;
    using DestructorSkippable_ = void;
  };  // end of class InnerMap

  template <typename LookupKey>
  using key_arg = typename internal::TransparentSupport<
      key_type>::template key_arg<LookupKey>;

 public:
  // Iterators
  class const_iterator {
    using InnerIt = typename InnerMap::const_iterator;

   public:
    using iterator_category = std::forward_iterator_tag;
    using value_type = typename Map::value_type;
    using difference_type = ptrdiff_t;
    using pointer = const value_type*;
    using reference = const value_type&;

    const_iterator() {}
    explicit const_iterator(const InnerIt& it) : it_(it) {}

    const_reference operator*() const { return *it_; }
    const_pointer operator->() const { return &(operator*()); }

    const_iterator& operator++() {
      ++it_;
      return *this;
    }
    const_iterator operator++(int) {
      auto copy = *this;
      ++*this;
      return copy;
    }

    friend bool operator==(const const_iterator& a, const const_iterator& b) {
      return a.it_ == b.it_;
    }
    friend bool operator!=(const const_iterator& a, const const_iterator& b) {
      return !(a == b);
    }

   private:
    InnerIt it_;
  };

  class iterator {
    using InnerIt = typename InnerMap::iterator;

   public:
    using iterator_category = std::forward_iterator_tag;
    using value_type = typename Map::value_type;
    using difference_type = ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;

    iterator() {}
    explicit iterator(const InnerIt& it) : it_(it) {}

    reference operator*() const { return *it_; }
    pointer operator->() const { return &(operator*()); }

    iterator& operator++() {
      ++it_;
      return *this;
    }
    iterator operator++(int) {
      auto copy = *this;
      ++*this;
      return copy;
    }

    // Allow implicit conversion to const_iterator.
    operator const_iterator() const {  // NOLINT(runtime/explicit)
      return const_iterator(typename InnerMap::const_iterator(it_));
    }

    friend bool operator==(const iterator& a, const iterator& b) {
      return a.it_ == b.it_;
    }
    friend bool operator!=(const iterator& a, const iterator& b) {
      return !(a == b);
    }

   private:
    friend class Map;

    InnerIt it_;
  };

  iterator begin() { return iterator(elements_.begin()); }
  iterator end() { return iterator(elements_.end()); }
  const_iterator begin() const { return const_iterator(elements_.begin()); }
  const_iterator end() const { return const_iterator(elements_.end()); }
  const_iterator cbegin() const { return begin(); }
  const_iterator cend() const { return end(); }

  size_type size() const { return elements_.size(); }
  bool empty() const { return size() == 0; }

  // Element access
  template <typename K = key_type>
  T& operator[](const key_arg<K>& key) {
    return elements_[key].second;
  }
  template <
      typename K = key_type,
      // Disable for integral types to reduce code bloat.
      typename = typename std::enable_if<!std::is_integral<K>::value>::type>
  T& operator[](key_arg<K>&& key) {
    return elements_[std::forward<K>(key)].second;
  }

  template <typename K = key_type>
  const T& at(const key_arg<K>& key) const {
    const_iterator it = find(key);
    GOOGLE_ABSL_CHECK(it != end()) << "key not found: " << static_cast<Key>(key);
    return it->second;
  }

  template <typename K = key_type>
  T& at(const key_arg<K>& key) {
    iterator it = find(key);
    GOOGLE_ABSL_CHECK(it != end()) << "key not found: " << static_cast<Key>(key);
    return it->second;
  }

  // Lookup
  template <typename K = key_type>
  size_type count(const key_arg<K>& key) const {
    return find(key) == end() ? 0 : 1;
  }

  template <typename K = key_type>
  const_iterator find(const key_arg<K>& key) const {
    return const_iterator(elements_.find(key));
  }
  template <typename K = key_type>
  iterator find(const key_arg<K>& key) {
    return iterator(elements_.find(key));
  }

  template <typename K = key_type>
  bool contains(const key_arg<K>& key) const {
    return find(key) != end();
  }

  template <typename K = key_type>
  std::pair<const_iterator, const_iterator> equal_range(
      const key_arg<K>& key) const {
    const_iterator it = find(key);
    if (it == end()) {
      return std::pair<const_iterator, const_iterator>(it, it);
    } else {
      const_iterator begin = it++;
      return std::pair<const_iterator, const_iterator>(begin, it);
    }
  }

  template <typename K = key_type>
  std::pair<iterator, iterator> equal_range(const key_arg<K>& key) {
    iterator it = find(key);
    if (it == end()) {
      return std::pair<iterator, iterator>(it, it);
    } else {
      iterator begin = it++;
      return std::pair<iterator, iterator>(begin, it);
    }
  }

  // insert
  template <typename K, typename... Args>
  std::pair<iterator, bool> try_emplace(K&& k, Args&&... args) {
    auto p =
        elements_.try_emplace(std::forward<K>(k), std::forward<Args>(args)...);
    return std::pair<iterator, bool>(iterator(p.first), p.second);
  }
  std::pair<iterator, bool> insert(init_type&& value) {
    return try_emplace(std::move(value.first), std::move(value.second));
  }
  template <typename P, RequiresInsertable<P> = 0>
  std::pair<iterator, bool> insert(P&& value) {
    return try_emplace(std::forward<P>(value).first,
                       std::forward<P>(value).second);
  }
  template <typename... Args>
  std::pair<iterator, bool> emplace(Args&&... args) {
    return EmplaceInternal(Rank0{}, std::forward<Args>(args)...);
  }
  template <class InputIt>
  void insert(InputIt first, InputIt last) {
    for (; first != last; ++first) {
      auto&& pair = *first;
      try_emplace(pair.first, pair.second);
    }
  }
  void insert(std::initializer_list<init_type> values) {
    insert(values.begin(), values.end());
  }
  template <typename P, RequiresNotInit<P> = 0,
            RequiresInsertable<const P&> = 0>
  void insert(std::initializer_list<P> values) {
    insert(values.begin(), values.end());
  }

  // Erase and clear
  template <typename K = key_type>
  size_type erase(const key_arg<K>& key) {
    iterator it = find(key);
    if (it == end()) {
      return 0;
    } else {
      erase(it);
      return 1;
    }
  }
  iterator erase(iterator pos) {
    iterator i = pos++;
    elements_.erase(i.it_);
    return pos;
  }
  void erase(iterator first, iterator last) {
    while (first != last) {
      first = erase(first);
    }
  }
  void clear() { elements_.clear(); }

  // Assign
  Map& operator=(const Map& other) {
    if (this != &other) {
      clear();
      insert(other.begin(), other.end());
    }
    return *this;
  }

  void swap(Map& other) {
    if (arena() == other.arena()) {
      InternalSwap(&other);
    } else {
      // TODO(zuguang): optimize this. The temporary copy can be allocated
      // in the same arena as the other message, and the "other = copy" can
      // be replaced with the fast-path swap above.
      Map copy = *this;
      *this = other;
      other = copy;
    }
  }

  void InternalSwap(Map* other) { elements_.Swap(&other->elements_); }

  hasher hash_function() const { return {}; }

  size_t SpaceUsedExcludingSelfLong() const {
    if (empty()) return 0;
    return elements_.SpaceUsedInternal() + internal::SpaceUsedInValues(this);
  }

 private:
  struct Rank1 {};
  struct Rank0 : Rank1 {};

  // We try to construct `init_type` from `Args` with a fall back to
  // `value_type`. The latter is less desired as it unconditionally makes a copy
  // of `value_type::first`.
  template <typename... Args>
  auto EmplaceInternal(Rank0, Args&&... args) ->
      typename std::enable_if<std::is_constructible<init_type, Args...>::value,
                              std::pair<iterator, bool>>::type {
    return insert(init_type(std::forward<Args>(args)...));
  }
  template <typename... Args>
  std::pair<iterator, bool> EmplaceInternal(Rank1, Args&&... args) {
    return insert(value_type(std::forward<Args>(args)...));
  }

  Arena* arena() const { return elements_.arena(); }
  InnerMap elements_;

  friend class Arena;
  using InternalArenaConstructable_ = void;
  using DestructorSkippable_ = void;
  template <typename Derived, typename K, typename V,
            internal::WireFormatLite::FieldType key_wire_type,
            internal::WireFormatLite::FieldType value_wire_type>
  friend class internal::MapFieldLite;
};

namespace internal {
template <typename... T>
PROTOBUF_NOINLINE void MapMergeFrom(Map<T...>& dest, const Map<T...>& src) {
  for (const auto& elem : src) {
    dest[elem.first] = elem.second;
  }
}
}  // namespace internal

}  // namespace protobuf
}  // namespace google

#include "google/protobuf/port_undef.inc"

#endif  // GOOGLE_PROTOBUF_MAP_H__
