8#include <unordered_map>
10#include <userver/storages/postgres/io/buffer_io.hpp>
11#include <userver/storages/postgres/io/buffer_io_base.hpp>
12#include <userver/storages/postgres/io/pg_types.hpp>
13#include <userver/storages/postgres/io/type_mapping.hpp>
14#include <userver/storages/postgres/io/user_types.hpp>
15#include <userver/utils/trivial_map_fwd.hpp>
17#include <userver/storages/postgres/detail/string_hash.hpp>
19USERVER_NAMESPACE_BEGIN
26template <
typename Enum>
29 std::string_view literal;
31 constexpr Enumerator(Enum en, std::string_view lit) : enumerator{en}, literal{lit} {}
38template <
typename Enum>
40 static_assert(std::is_enum<Enum>(),
"Type must be an enumeration");
47 using EnumType = Enum;
50 using Enumerator = detail::Enumerator<Enum>;
55 using EnumeratorList =
const std::initializer_list<Enumerator>;
74template <
typename Enum,
typename Enable = USERVER_NAMESPACE::
utils::void_t<>>
75struct AreEnumeratorsDefined : std::false_type {};
77template <
typename Enum>
78struct AreEnumeratorsDefined<Enum, USERVER_NAMESPACE::
utils::void_t<
decltype(CppToUserPg<Enum>::enumerators)*>>
81template <
typename Enum>
83 static_assert(std::is_enum<Enum>(),
"Type must be an enumeration");
85 AreEnumeratorsDefined<Enum>(),
86 "CppToUserPg for an enumeration must contain a static "
87 "`enumerators` member of `utils::TrivialBiMap` type or "
88 "`storages::postgres::io::detail::Enumerator[]`"
90 using Type =
decltype(CppToUserPg<Enum>::enumerators);
93template <
typename Enum,
typename =
typename Enumerators<Enum>::Type>
96template <
typename Enum,
typename T>
98 using StringType = std::string_view;
99 using EnumType = Enum;
100 using MappingType = CppToUserPg<EnumType>;
101 using EnumeratorType = Enumerator<EnumType>;
104 std::size_t operator()(EnumType v)
const {
105 using underlying_type = std::underlying_type_t<EnumType>;
106 using hasher = std::hash<underlying_type>;
107 return hasher{}(
static_cast<underlying_type>(v));
111 using EnumToString = std::unordered_map<EnumType, StringType, EnumHash>;
112 using StringToEnum = std::unordered_map<StringType, EnumType, utils::StringViewHash>;
113 using MapsPair = std::pair<EnumToString, StringToEnum>;
115 static MapsPair MapLiterals() {
117 for (
const auto& enumerator : enumerators) {
118 maps.first.insert(std::make_pair(enumerator.enumerator, enumerator.literal));
119 maps.second.insert(std::make_pair(enumerator.literal, enumerator.enumerator));
123 static const MapsPair& GetMaps() {
124 static auto maps_ = MapLiterals();
127 static const EnumToString& EnumeratorMap() {
return GetMaps().first; }
128 static const StringToEnum& LiteralMap() {
return GetMaps().second; }
131 static constexpr const auto& enumerators = MappingType::enumerators;
132 static constexpr std::size_t size = std::size(enumerators);
133 static EnumType GetEnumerator(StringType literal) {
134 static const auto& map = LiteralMap();
135 if (
auto f = map.find(literal); f != map.end()) {
140 static StringType GetLiteral(EnumType enumerator) {
141 static const auto& map = EnumeratorMap();
142 if (
auto f = map.find(enumerator); f != map.end()) {
149template <
typename Enum,
typename Func>
150class EnumerationMap<Enum,
const USERVER_NAMESPACE::
utils::TrivialBiMap<Func>> {
151 using StringType = std::string_view;
152 using EnumType = Enum;
153 using MappingType = CppToUserPg<EnumType>;
156 static constexpr const auto& enumerators = MappingType::enumerators;
157 static constexpr std::size_t size = enumerators.size();
158 static constexpr EnumType GetEnumerator(StringType literal) {
159 auto enumerator = enumerators.TryFind(literal);
160 if (enumerator.has_value())
return *enumerator;
163 static constexpr StringType GetLiteral(EnumType enumerator) {
164 auto literal = enumerators.TryFind(enumerator);
165 if (literal.has_value())
return *literal;
170template <
typename Enum>
171class EnumerationMap<Enum,
const Codegen> {
172 using EnumType = Enum;
173 using MappingType = CppToUserPg<EnumType>;
176 static EnumType GetEnumerator(std::string_view literal) {
return Parse(literal,
formats::
parse::
To<Enum>{}); }
177 static std::string GetLiteral(EnumType enumerator) {
return ToString(enumerator); }
180template <
typename Enum>
181struct EnumParser : BufferParserBase<Enum> {
182 using BaseType = BufferParserBase<Enum>;
183 using EnumMap = EnumerationMap<Enum>;
185 using BaseType::BaseType;
188 std::string_view literal;
190 this->value = EnumMap::GetEnumerator(literal);
194template <
typename Enum>
195struct EnumFormatter : BufferFormatterBase<Enum> {
196 using BaseType = BufferFormatterBase<Enum>;
197 using EnumMap = EnumerationMap<Enum>;
199 using BaseType::BaseType;
201 template <
typename Buffer>
202 void operator()(
const UserTypes& types, Buffer& buffer)
const {
203 auto literal = EnumMap::GetLiteral(
this->value);
204 io::WriteBuffer(types, buffer, literal);
213struct Input<T, std::enable_if_t<!detail::kCustomParserDefined<T> && std::is_enum<T>() &&
IsMappedToUserType<T>()>> {
214 using type = io::detail::EnumParser<T>;
224 std::enable_if_t<!detail::kCustomFormatterDefined<T> && std::is_enum<T>() &&
IsMappedToUserType<T>()>> {
225 using type = io::detail::EnumFormatter<T>;