8#include <userver/utils/trivial_map.hpp>
10USERVER_NAMESPACE_BEGIN
21struct UnsafeConstexprHasher
final {
22 constexpr std::size_t operator()(std::string_view str)
const noexcept {
23 constexpr std::uint64_t mul = (0xc6a4a793UL << 32UL) + 0x5bd1e995UL;
25 std::uint64_t hash = seed_ ^ (str.size() * mul);
26 while (str.size() >= 8) {
27 const std::uint64_t data = ShiftMix(Load8(str.data()) * mul) * mul;
34 const std::uint64_t data = LoadN(str.data(), str.size());
39 hash = ShiftMix(hash) * mul;
40 hash = ShiftMix(hash);
45 static constexpr inline std::uint64_t ShiftMix(std::uint64_t v)
noexcept {
49 static constexpr inline std::uint64_t Load8(
const char* data)
noexcept {
50 return LoadN(data, 8);
53 static constexpr inline std::uint64_t LoadN(
const char* data,
54 std::size_t n)
noexcept {
61 constexpr std::uint64_t kDeliberatelyBrokenLowercaseMask =
64 std::uint64_t result = kDeliberatelyBrokenLowercaseMask >> (8 * (8 - n));
65 for (std::size_t i = 0; i < n; ++i) {
66 const std::uint8_t c = data[i];
67 result |=
static_cast<std::uint64_t>(c) << (8 * i);
79 std::uint64_t seed_{54999};
83inline constexpr utils::TrivialBiMap kKnownHeadersLowercaseMap =
86 .Case(
"content-type", std::int8_t{1})
87 .Case(
"content-encoding", 2)
88 .Case(
"content-length", 3)
89 .Case(
"transfer-encoding", 4)
92 .Case(
"accept-encoding", 7)
93 .Case(
"accept-language", 8)
94 .Case(
"x-yataxi-api-key", 9)
95 .Case(
"user-agent", 10)
96 .Case(
"x-request-application", 11)
99 .Case(
"access-control-allow-headers", 14)
102 .Case(
"set-cookie", 17)
103 .Case(
"connection", 18)
105 .Case(
"x-yarequestid", 20)
106 .Case(
"x-yatraceid", 21)
107 .Case(
"x-yaspanid", 22)
108 .Case(
"x-requestid", 23)
109 .Case(
"x-backend-server", 24)
110 .Case(
"x-taxi-envoyproxy-dstvhost", 25)
112 .Case(
"x-yataxi-allow-auth-request", 27)
113 .Case(
"x-yataxi-allow-auth-response", 28)
114 .Case(
"x-yataxi-server-hostname", 29)
115 .Case(
"x-yataxi-client-timeoutms", 30)
116 .Case(
"x-yataxi-deadline-expired", 31)
117 .Case(
"x-yataxi-ratelimited-by", 32)
118 .Case(
"x-yataxi-ratelimit-reason", 33);
123inline constexpr std::int8_t kNoHeaderIndexLookup = -1;
124inline constexpr std::int8_t kNoHeaderIndexInsertion = -2;
125static_assert(kNoHeaderIndexLookup != kNoHeaderIndexInsertion);
126static_assert(kNoHeaderIndexLookup != 0 && kNoHeaderIndexInsertion != 0);
129constexpr std::int8_t GetHeaderIndexForLookup(std::string_view key) {
130 return kKnownHeadersLowercaseMap.TryFindICaseByFirst(key).value_or(
131 kNoHeaderIndexLookup);
137inline std::int8_t GetHeaderIndexForInsertion(std::string_view key) {
138 return kKnownHeadersLowercaseMap.TryFindICaseByFirst(key).value_or(
139 kNoHeaderIndexInsertion);
144namespace header_map {
159class PredefinedHeader
final {
161 explicit constexpr PredefinedHeader(std::string_view name)
163 hash{impl::UnsafeConstexprHasher{}(name)},
164 header_index{impl::GetHeaderIndexForLookup(name)} {}
166 constexpr operator std::string_view()
const {
return name; }
168 explicit operator std::string()
const {
return std::string{name}; }
171 friend class header_map::Danger;
172 friend class header_map::Map;
175 const std::string_view name;
178 const std::size_t hash;
186 const std::int8_t header_index;
194struct fmt::formatter<USERVER_NAMESPACE::http::headers::PredefinedHeader>
195 : fmt::formatter<std::string_view> {
196 template <
typename FormatContext>
197 auto format(
const USERVER_NAMESPACE::http::headers::PredefinedHeader& value,
198 FormatContext& ctx)
const ->
decltype(ctx.out()) {
199 return formatter<std::string_view>::format(std::string_view{value}, ctx);