userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
traits.hpp
1
#
pragma
once
2
3
#
include
<
limits
>
4
#
include
<
string
>
5
#
include
<
type_traits
>
6
#
include
<
unordered_map
>
7
8
#
include
<
userver
/
storages
/
postgres
/
detail
/
is_decl_complete
.
hpp
>
9
#
include
<
userver
/
storages
/
postgres
/
io
/
pg_types
.
hpp
>
10
11
USERVER_NAMESPACE_BEGIN
12
13
namespace
storages::
postgres
{
14
15
class
UserTypes
;
16
17
namespace
io
{
18
19
/// Category of buffer contents.
20
///
21
/// Applied to binary parsers and deduced from field's data type.
22
enum
class
BufferCategory
{
23
kKeepCategory
= -1,
//!< kKeepCategory keep current buffer category
24
kNoParser
= 0,
//!< kNoParser the data type doesn't have a parser defined
25
kVoid
,
//!< kVoid there won't be a buffer for this field, but the category is
26
//!< required for correctly handling void results
27
kPlainBuffer
,
//!< kPlainBuffer the buffer is a single plain value
28
kArrayBuffer
,
//!< kArrayBuffer the buffer contains an array of values
29
kCompositeBuffer
,
//!< kCompositeBuffer the buffer contains a user-defined
30
//!< composite type
31
kRangeBuffer
//!< kRangeBuffer the buffer contains a range type
32
};
33
34
std::string_view ToString(
BufferCategory
);
35
36
template
<
BufferCategory
Category>
37
using
BufferCategoryConstant = std::integral_constant<
BufferCategory
, Category>;
38
39
using
TypeBufferCategory = std::unordered_map<
Oid
,
BufferCategory
>;
40
41
BufferCategory
GetTypeBufferCategory(
const
TypeBufferCategory&,
Oid
);
42
43
struct
BufferCategoryHash
{
44
using
IntegerType = std::underlying_type_t<
BufferCategory
>;
45
std::size_t operator()(
BufferCategory
val)
const
{
return
std::hash<IntegerType>{}(
static_cast
<IntegerType>(val)); }
46
};
47
48
inline
constexpr
int
kPgBinaryDataFormat = 1;
49
50
/// Fields that are null are denoted by specifying their length == -1
51
inline
constexpr
Integer
kPgNullBufferSize
= -1;
52
53
struct
FieldBuffer
{
54
static
constexpr
std::size_t npos = std::numeric_limits<std::size_t>::max();
55
56
bool
is_null =
false
;
57
BufferCategory
category =
BufferCategory
::
kPlainBuffer
;
58
std::size_t length = 0;
59
const
std::uint8_t* buffer =
nullptr
;
60
61
std::string ToString()
const
{
return
{
reinterpret_cast
<
const
char
*>(buffer), length}; }
62
constexpr
FieldBuffer
GetSubBuffer(
63
std::size_t offset,
64
std::size_t size = npos,
65
BufferCategory
cat =
BufferCategory
::
kKeepCategory
66
)
const
;
67
68
template
<
typename
T>
69
std::size_t Read(T&& value,
BufferCategory
cat =
BufferCategory
::
kKeepCategory
, std::size_t length =
sizeof
(T));
70
template
<
typename
T>
71
std::size_t Read(
72
T&& value,
73
const
TypeBufferCategory& categories,
74
std::size_t length =
sizeof
(T),
75
BufferCategory
cat =
BufferCategory
::
kKeepCategory
76
);
77
78
// Read 'raw' postgres buffer - first read the size, then read the value
79
template
<
typename
T>
80
std::size_t ReadRaw(
81
T&& value,
82
const
TypeBufferCategory& categories,
83
BufferCategory
cat =
BufferCategory
::
kKeepCategory
84
);
85
};
86
87
/// @brief Primary template for Postgre buffer parser.
88
/// Specialisations should provide call operators that parse FieldBuffer.
89
template
<
typename
T>
90
struct
BufferParser
;
91
92
/// @brief Primary template for Postgre buffer formatter
93
/// Specialisations should provide call operators that write to a buffer.
94
template
<
typename
T>
95
struct
BufferFormatter
;
96
97
namespace
traits
{
98
99
/// Customisation point for parsers
100
template
<
typename
T>
101
struct
Input
{
102
using
type =
BufferParser
<T>;
103
};
104
105
/// Customisation point for formatters
106
template
<
typename
T>
107
struct
Output
{
108
using
type =
BufferFormatter
<T>;
109
};
110
111
/// @brief A default deducer of parsers/formatters for a type/data format.
112
/// Can be specialised for a type/format pair providing custom
113
/// parsers/formatters.
114
template
<
typename
T>
115
struct
IO
{
116
using
ParserType =
typename
Input
<T>::type;
117
using
FormatterType =
typename
Output
<T>::type;
118
};
119
120
/// @brief Concept to detect if a type has a parser.
121
template
<
typename
T>
122
concept
HasParser
= utils::IsDeclComplete<
typename
IO
<T>::ParserType>::value;
123
124
/// @brief Concept to detect if a type has a formatter.
125
template
<
typename
T>
126
concept
HasFormatter
= utils::IsDeclComplete<
typename
IO
<T>::FormatterType>::value;
127
128
template
<
typename
T>
129
constexpr
bool
CheckParser() {
130
static_assert
(
131
HasParser
<T> || std::is_enum_v<T>,
132
"Type doesn't have a parser. Probably you forgot to include "
133
"file with parser or to define your own. Please see page "
134
"`uPg: Supported data types` for more information"
135
);
136
137
static_assert
(
138
HasParser
<T> || !std::is_enum_v<T>,
139
"Type doesn't have a parser. Probably you forgot to include "
140
"file with parser, to define your own or to specialize "
141
"`storages::postgres::io::traits::CanUseEnumAsStrongTypedef`. "
142
"See page `uPg: Supported data types` for more information"
143
);
144
145
return
true
;
146
}
147
148
template
<
typename
T>
149
constexpr
void
CheckFormatter() {
150
static_assert
(
151
HasFormatter
<T> || std::is_enum_v<T>,
152
"Type doesn't have a formatter. Probably you forgot to include "
153
"file with formatter or to define your own. Please see page "
154
"`uPg: Supported data types` for more information"
155
);
156
157
static_assert
(
158
HasFormatter
<T> || !std::is_enum_v<T>,
159
"Type doesn't have a formatter. Probably you forgot to include "
160
"file with formatter, to define your own or to specialize "
161
"`storages::postgres::io::traits::CanUseEnumAsStrongTypedef`. "
162
"See page `uPg: Supported data types` for more information"
163
);
164
}
165
166
/// Buffer category for parser
167
template
<
typename
T>
168
struct
ParserBufferCategory
: BufferCategoryConstant<
BufferCategory
::
kPlainBuffer
> {};
169
template
<
typename
T>
170
using
ParserBufferCategoryType =
typename
ParserBufferCategory
<T>::type;
171
template
<
typename
T>
172
inline
constexpr
BufferCategory kParserBufferCategory = ParserBufferCategory<T>::value;
173
174
//@{
175
/** @name Buffer category for a type */
176
namespace
detail {
177
template
<
typename
T>
178
constexpr
auto
DetectBufferCategory() {
179
if
constexpr
(
HasParser
<T>) {
180
return
ParserBufferCategoryType<
typename
IO
<T>::ParserType>{};
181
}
else
{
182
return
BufferCategoryConstant<
BufferCategory
::
kNoParser
>{};
183
}
184
}
185
}
// namespace detail
186
template
<
typename
T>
187
struct
TypeBufferCategory
:
decltype
(detail::DetectBufferCategory<T>()) {};
188
template
<
typename
T>
189
inline
constexpr
BufferCategory kTypeBufferCategory = TypeBufferCategory<T>::value;
190
//@}
191
192
namespace
detail {
193
194
template
<
typename
T>
195
concept
CustomParserDefined = utils::IsDeclComplete<
BufferParser
<T>>::value;
196
197
template
<
typename
T>
198
concept
CustomFormatterDefined = utils::IsDeclComplete<
BufferFormatter
<T>>::value;
199
200
}
// namespace detail
201
202
}
// namespace traits
203
204
}
// namespace io
205
}
// namespace storages::postgres
206
207
USERVER_NAMESPACE_END
userver
storages
postgres
io
traits.hpp
Generated on
for userver by
Doxygen
1.17.0