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_view, std::string_view>> headers);
67 template <
typename InputIt>
78 HeaderMap&
operator=(
const HeaderMap& other);
80 HeaderMap&
operator=(HeaderMap&& other)
noexcept;
83 void reserve(std::size_t capacity);
85 std::size_t
size()
const noexcept;
87 bool empty()
const noexcept;
93 std::size_t
count(std::string_view key)
const noexcept;
95 std::size_t
count(
const PredefinedHeader& key)
const noexcept;
97 template <std::size_t Size>
98 [[noreturn]] std::size_t count(
const char (&)[Size])
const noexcept {
103 bool contains(std::string_view key)
const noexcept;
105 bool contains(
const PredefinedHeader& key)
const noexcept;
107 template <std::size_t Size>
108 [[noreturn]]
bool contains(
const char (&)[Size])
const noexcept {
109 ReportMisuse<Size>();
117 std::string&
operator[](std::string&& key);
121 std::string&
operator[](std::string_view key);
123 std::string&
operator[](
const PredefinedHeader& key);
125 template <std::size_t Size>
126 [[noreturn]] std::string& operator[](
const char (&)[Size]) {
127 ReportMisuse<Size>();
132 Iterator
find(std::string_view key)
noexcept;
134 ConstIterator
find(std::string_view key)
const noexcept;
138 Iterator
find(
const PredefinedHeader& key)
noexcept;
140 ConstIterator
find(
const PredefinedHeader& key)
const noexcept;
142 template <std::size_t Size>
143 [[noreturn]] Iterator find(
const char (&)[Size])
noexcept;
145 template <std::size_t Size>
146 [[noreturn]] ConstIterator find(
const char (&)[Size])
const noexcept;
150 template <
typename... Args>
151 void emplace(std::string_view key, Args&&... args) {
152 Emplace(std::move(key), std::forward<Args>(args)...);
157 template <
typename... Args>
158 void emplace(std::string key, Args&&... args) {
159 Emplace(std::move(key), std::forward<Args>(args)...);
164 template <
typename... Args>
165 void try_emplace(std::string key, Args&&... args) {
166 Emplace(std::move(key), std::forward<Args>(args)...);
171 template <
typename InputIt>
172 void insert(InputIt first, InputIt last);
176 void insert(
const std::pair<std::string, std::string>& kvp);
179 void insert(std::pair<std::string, std::string>&& kvp);
191 void InsertOrAppend(
const PredefinedHeader& key, std::string value);
196 Iterator
erase(Iterator it);
200 Iterator
erase(ConstIterator it);
204 Iterator
erase(std::string_view key);
206 Iterator
erase(
const PredefinedHeader& key);
208 template <std::size_t Size>
209 [[noreturn]] Iterator erase(
const char (&)[Size]);
213 std::string&
at(std::string_view key);
215 std::string&
at(
const PredefinedHeader& key);
218 const std::string&
at(std::string_view key)
const;
220 const std::string&
at(
const PredefinedHeader& key)
const;
222 template <std::size_t Size>
223 [[noreturn]] std::string& at(
const char (&)[Size]) {
224 ReportMisuse<Size>();
226 template <std::size_t Size>
227 [[noreturn]]
const std::string& at(
const char (&)[Size])
const {
228 ReportMisuse<Size>();
232 Iterator
begin()
noexcept;
234 ConstIterator
begin()
const noexcept;
236 ConstIterator
cbegin()
const noexcept;
239 Iterator
end()
noexcept;
241 ConstIterator
end()
const noexcept;
243 ConstIterator
cend()
const noexcept;
247 bool operator==(
const HeaderMap& other)
const noexcept;
260 friend class TestsHelper;
262 template <
typename KeyType,
typename... Args>
263 void Emplace(KeyType&& key, Args&&... args);
265 template <std::size_t Size>
266 [[noreturn]]
static void ReportMisuse();
268 utils::FastPimpl<header_map::Map, 272, 8> impl_;
271template <
typename InputIt>
272HeaderMap::
HeaderMap(InputIt first, InputIt last) : HeaderMap{} {
276template <
typename InputIt>
277void HeaderMap::
insert(InputIt first, InputIt last) {
278 for (; first != last; ++first) {
283template <
typename KeyType,
typename... Args>
284void HeaderMap::Emplace(KeyType&& key, Args&&... args) {
285 static_assert(std::is_rvalue_reference_v<
decltype(key)>);
288 auto& value = operator[](std::move(key));
290 value = std::string{std::forward<Args>(args)...};
294template <std::size_t Size>
295void HeaderMap::ReportMisuse() {
298 "Please create a 'constexpr PredefinedHeader' and use that "
299 "instead of passing header name as a string literal."
303namespace header_map {
305class MapEntry
final {
310 MapEntry(std::string&& key, std::string&& value);
312 MapEntry(
const MapEntry& other);
313 MapEntry& operator=(
const MapEntry& other);
314 MapEntry(MapEntry&& other)
noexcept;
315 MapEntry& operator=(MapEntry&& other)
noexcept;
317 std::pair<
const std::string, std::string>& Get();
318 const std::pair<
const std::string, std::string>& Get()
const;
320 std::pair<std::string, std::string>& GetMutable();
322 bool operator==(
const MapEntry& other)
const;
336 std::pair<std::string, std::string> mutable_value;
337 std::pair<
const std::string, std::string> value;
345class HeaderMap::Iterator
final {
347 using iterator_category = std::forward_iterator_tag;
348 using difference_type = std::ptrdiff_t;
349 using value_type = std::pair<
const std::string, std::string>;
350 using reference = value_type&;
351 using const_reference =
const value_type&;
352 using pointer = value_type*;
353 using const_pointer =
const value_type*;
358 using UnderlyingIterator = std::vector<header_map::MapEntry>::reverse_iterator;
361 explicit Iterator(UnderlyingIterator it);
364 Iterator(
const Iterator& other);
365 Iterator(Iterator&& other)
noexcept;
366 Iterator& operator=(
const Iterator& other);
367 Iterator& operator=(Iterator&& other)
noexcept;
369 Iterator operator++(
int);
370 Iterator& operator++();
372 reference operator*();
373 const_reference operator*()
const;
374 pointer operator->();
375 const_pointer operator->()
const;
377 bool operator==(
const Iterator& other)
const;
378 bool operator!=(
const Iterator& other)
const;
380 bool operator==(
const ConstIterator& other)
const;
383 friend class HeaderMap::ConstIterator;
385 UnderlyingIterator it_{};
388class HeaderMap::ConstIterator
final {
390 using iterator_category = std::forward_iterator_tag;
391 using difference_type = std::ptrdiff_t;
392 using value_type = std::pair<
const std::string, std::string>;
393 using reference =
const value_type&;
394 using const_reference =
const value_type&;
395 using pointer =
const value_type*;
396 using const_pointer =
const value_type*;
401 using UnderlyingIterator = std::vector<header_map::MapEntry>::const_reverse_iterator;
404 explicit ConstIterator(UnderlyingIterator it);
407 ConstIterator(
const ConstIterator& other);
408 ConstIterator(ConstIterator&& other)
noexcept;
409 ConstIterator& operator=(
const ConstIterator& other);
410 ConstIterator& operator=(ConstIterator&& other)
noexcept;
412 ConstIterator operator++(
int);
413 ConstIterator& operator++();
415 reference operator*();
416 const_reference operator*()
const;
417 pointer operator->();
418 const_pointer operator->()
const;
420 bool operator==(
const ConstIterator& other)
const;
421 bool operator!=(
const ConstIterator& other)
const;
423 bool operator==(
const Iterator& other)
const;
426 friend class HeaderMap::Iterator;
428 UnderlyingIterator it_{};
431template <std::size_t Size>
432HeaderMap::Iterator HeaderMap::find(
const char (&)[Size])
noexcept {
433 ReportMisuse<Size>();
436template <std::size_t Size>
437HeaderMap::ConstIterator HeaderMap::find(
const char (&)[Size])
const noexcept {
438 ReportMisuse<Size>();
441template <std::size_t Size>
442HeaderMap::Iterator HeaderMap::erase(
const char (&)[Size]) {
443 ReportMisuse<Size>();