3#include <initializer_list> 
    8#include <userver/formats/json_fwd.hpp> 
    9#include <userver/formats/parse/to.hpp> 
   10#include <userver/http/predefined_header.hpp> 
   11#include <userver/utils/fast_pimpl.hpp> 
   13USERVER_NAMESPACE_BEGIN
 
   38class HeaderMap 
final {
 
   45  using iterator = Iterator;
 
   46  using const_iterator = ConstIterator;
 
   48  using key_type = std::string;
 
   49  using mapped_type = std::string;
 
   52  class TooManyHeadersException 
final : 
public std::runtime_error {
 
   53    using std::runtime_error::runtime_error;
 
   60  HeaderMap(std::initializer_list<std::pair<std::string, std::string>> headers);
 
   64      std::initializer_list<std::pair<PredefinedHeader, std::string>> headers);
 
   71  template <
typename InputIt>
 
   82  HeaderMap& 
operator=(
const HeaderMap& other);
 
   84  HeaderMap& 
operator=(HeaderMap&& other) 
noexcept;
 
   87  void reserve(std::size_t capacity);
 
   89  std::size_t 
size() 
const noexcept;
 
   91  bool empty() 
const noexcept;
 
   97  std::size_t 
count(std::string_view key) 
const noexcept;
 
   99  std::size_t 
count(
const PredefinedHeader& key) 
const noexcept;
 
  101  template <std::size_t Size>
 
  102  [[noreturn]] std::size_t count(
const char (&)[Size]) 
const noexcept {
 
  103    ReportMisuse<Size>();
 
  107  bool contains(std::string_view key) 
const noexcept;
 
  109  bool contains(
const PredefinedHeader& key) 
const noexcept;
 
  111  template <std::size_t Size>
 
  112  [[noreturn]] 
bool contains(
const char (&)[Size]) 
const noexcept {
 
  113    ReportMisuse<Size>();
 
  121  std::string& 
operator[](std::string&& key);
 
  125  std::string& 
operator[](std::string_view key);
 
  127  std::string& 
operator[](
const PredefinedHeader& key);
 
  129  template <std::size_t Size>
 
  130  [[noreturn]] std::string& operator[](
const char (&)[Size]) {
 
  131    ReportMisuse<Size>();
 
  136  Iterator 
find(std::string_view key) 
noexcept;
 
  138  ConstIterator 
find(std::string_view key) 
const noexcept;
 
  142  Iterator 
find(
const PredefinedHeader& key) 
noexcept;
 
  144  ConstIterator 
find(
const PredefinedHeader& key) 
const noexcept;
 
  146  template <std::size_t Size>
 
  147  Iterator find(
const char (&)[Size]) 
noexcept;
 
  149  template <std::size_t Size>
 
  150  ConstIterator find(
const char (&)[Size]) 
const noexcept;
 
  154  template <
typename... Args>
 
  155  void emplace(std::string_view key, Args&&... args) {
 
  156    Emplace(std::move(key), std::forward<Args>(args)...);
 
  161  template <
typename... Args>
 
  162  void emplace(std::string key, Args&&... args) {
 
  163    Emplace(std::move(key), std::forward<Args>(args)...);
 
  168  template <
typename... Args>
 
  169  void try_emplace(std::string key, Args&&... args) {
 
  170    Emplace(std::move(key), std::forward<Args>(args)...);
 
  175  template <
typename InputIt>
 
  176  void insert(InputIt first, InputIt last);
 
  180  void insert(
const std::pair<std::string, std::string>& kvp);
 
  183  void insert(std::pair<std::string, std::string>&& kvp);
 
  195  void InsertOrAppend(
const PredefinedHeader& key, std::string value);
 
  200  Iterator 
erase(Iterator it);
 
  204  Iterator 
erase(ConstIterator it);
 
  208  Iterator 
erase(std::string_view key);
 
  210  Iterator 
erase(
const PredefinedHeader& key);
 
  212  template <std::size_t Size>
 
  213  Iterator erase(
const char (&)[Size]);
 
  217  std::string& 
at(std::string_view key);
 
  219  std::string& 
at(
const PredefinedHeader& key);
 
  222  const std::string& 
at(std::string_view key) 
const;
 
  224  const std::string& 
at(
const PredefinedHeader& key) 
const;
 
  226  template <std::size_t Size>
 
  227  [[noreturn]] std::string& at(
const char (&)[Size]) {
 
  228    ReportMisuse<Size>();
 
  230  template <std::size_t Size>
 
  231  [[noreturn]] 
const std::string& at(
const char (&)[Size]) 
const {
 
  232    ReportMisuse<Size>();
 
  236  Iterator 
begin() 
noexcept;
 
  238  ConstIterator 
begin() 
const noexcept;
 
  240  ConstIterator 
cbegin() 
const noexcept;
 
  243  Iterator 
end() 
noexcept;
 
  245  ConstIterator 
end() 
const noexcept;
 
  247  ConstIterator 
cend() 
const noexcept;
 
  251  bool operator==(
const HeaderMap& other) 
const noexcept;
 
  264  friend class TestsHelper;
 
  266  template <
typename KeyType, 
typename... Args>
 
  267  void Emplace(KeyType&& key, Args&&... args);
 
  269  template <std::size_t Size>
 
  270  [[noreturn]] 
static void ReportMisuse();
 
  272  utils::FastPimpl<header_map::Map, 272, 8> impl_;
 
  275template <
typename InputIt>
 
  276HeaderMap::
HeaderMap(InputIt first, InputIt last) : HeaderMap{} {
 
  280template <
typename InputIt>
 
  281void HeaderMap::
insert(InputIt first, InputIt last) {
 
  282  for (; first != last; ++first) {
 
  287template <
typename KeyType, 
typename... Args>
 
  288void HeaderMap::Emplace(KeyType&& key, Args&&... args) {
 
  289  static_assert(std::is_rvalue_reference_v<
decltype(key)>);
 
  292  auto& value = operator[](std::move(key));
 
  294    value = std::string{std::forward<Args>(args)...};
 
  298template <std::size_t Size>
 
  299void HeaderMap::ReportMisuse() {
 
  301                "Please create a 'constexpr PredefinedHeader' and use that " 
  302                "instead of passing header name as a string literal.");
 
  305namespace header_map {
 
  307class MapEntry 
final {
 
  312  MapEntry(std::string&& key, std::string&& value);
 
  314  MapEntry(
const MapEntry& other);
 
  315  MapEntry& operator=(
const MapEntry& other);
 
  316  MapEntry(MapEntry&& other) 
noexcept;
 
  317  MapEntry& operator=(MapEntry&& other) 
noexcept;
 
  319  std::pair<
const std::string, std::string>& Get();
 
  320  const std::pair<
const std::string, std::string>& Get() 
const;
 
  322  std::pair<std::string, std::string>& GetMutable();
 
  324  bool operator==(
const MapEntry& other) 
const;
 
  338    std::pair<std::string, std::string> mutable_value;
 
  339    std::pair<
const std::string, std::string> value;
 
  347class HeaderMap::Iterator 
final {
 
  349  using iterator_category = std::forward_iterator_tag;
 
  350  using difference_type = std::ptrdiff_t;
 
  351  using value_type = std::pair<
const std::string, std::string>;
 
  352  using reference = value_type&;
 
  353  using const_reference = 
const value_type&;
 
  354  using pointer = value_type*;
 
  355  using const_pointer = 
const value_type*;
 
  360  using UnderlyingIterator =
 
  361      std::vector<header_map::MapEntry>::reverse_iterator;
 
  364  explicit Iterator(UnderlyingIterator it);
 
  367  Iterator(
const Iterator& other);
 
  368  Iterator(Iterator&& other) 
noexcept;
 
  369  Iterator& operator=(
const Iterator& other);
 
  370  Iterator& operator=(Iterator&& other) 
noexcept;
 
  372  Iterator operator++(
int);
 
  373  Iterator& operator++();
 
  375  reference operator*();
 
  376  const_reference operator*() 
const;
 
  377  pointer operator->();
 
  378  const_pointer operator->() 
const;
 
  380  bool operator==(
const Iterator& other) 
const;
 
  381  bool operator!=(
const Iterator& other) 
const;
 
  383  bool operator==(
const ConstIterator& other) 
const;
 
  386  friend class HeaderMap::ConstIterator;
 
  388  UnderlyingIterator it_{};
 
  391class HeaderMap::ConstIterator 
final {
 
  393  using iterator_category = std::forward_iterator_tag;
 
  394  using difference_type = std::ptrdiff_t;
 
  395  using value_type = std::pair<
const std::string, std::string>;
 
  396  using reference = 
const value_type&;
 
  397  using const_reference = 
const value_type&;
 
  398  using pointer = 
const value_type*;
 
  399  using const_pointer = 
const value_type*;
 
  404  using UnderlyingIterator =
 
  405      std::vector<header_map::MapEntry>::const_reverse_iterator;
 
  408  explicit ConstIterator(UnderlyingIterator it);
 
  411  ConstIterator(
const ConstIterator& other);
 
  412  ConstIterator(ConstIterator&& other) 
noexcept;
 
  413  ConstIterator& operator=(
const ConstIterator& other);
 
  414  ConstIterator& operator=(ConstIterator&& other) 
noexcept;
 
  416  ConstIterator operator++(
int);
 
  417  ConstIterator& operator++();
 
  419  reference operator*();
 
  420  const_reference operator*() 
const;
 
  421  pointer operator->();
 
  422  const_pointer operator->() 
const;
 
  424  bool operator==(
const ConstIterator& other) 
const;
 
  425  bool operator!=(
const ConstIterator& other) 
const;
 
  427  bool operator==(
const Iterator& other) 
const;
 
  430  friend class HeaderMap::Iterator;
 
  432  UnderlyingIterator it_{};
 
  435template <std::size_t Size>
 
  436HeaderMap::Iterator HeaderMap::find(
const char (&)[Size]) 
noexcept {
 
  437  ReportMisuse<Size>();
 
  440template <std::size_t Size>
 
  441HeaderMap::ConstIterator HeaderMap::find(
const char (&)[Size]) 
const noexcept {
 
  442  ReportMisuse<Size>();
 
  445template <std::size_t Size>
 
  446HeaderMap::Iterator HeaderMap::erase(
const char (&)[Size]) {
 
  447  ReportMisuse<Size>();