userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
common.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/dump/common.hpp
4
/// @brief Serialization and deserialization of integral, floating point,
5
/// string, `std::chrono`, `enum` and `uuid` types for dumps.
6
///
7
/// @ingroup userver_dump_read_write
8
9
#
include
<
chrono
>
10
#
include
<
concepts
>
11
#
include
<
cstdint
>
12
#
include
<
stdexcept
>
13
#
include
<
string
>
14
#
include
<
string_view
>
15
#
include
<
type_traits
>
16
17
#
include
<
userver
/
dump
/
operations
.
hpp
>
18
#
include
<
userver
/
dump
/
unsafe
.
hpp
>
19
#
include
<
userver
/
utils
/
meta_light
.
hpp
>
20
#
include
<
userver
/
utils
/
numeric_cast
.
hpp
>
21
22
namespace
boost::
uuids
{
23
struct
uuid;
24
}
25
26
USERVER_NAMESPACE_BEGIN
27
28
namespace
decimal64
{
29
template
<
int
Prec,
typename
RoundPolicy>
30
class
Decimal
;
31
}
// namespace decimal64
32
33
namespace
formats::
json
{
34
class
Value
;
35
}
// namespace formats::json
36
37
namespace
dump
{
38
39
/// @brief Reads the rest of the data from `reader`
40
std::string
ReadEntire
(
Reader
& reader);
41
42
namespace
impl {
43
44
/// @brief Helpers for serialization of trivially-copyable types
45
template
<
typename
T>
46
void
WriteTrivial(
Writer
& writer, T value) {
47
static_assert
(std::is_trivially_copyable_v<T>);
48
// TODO: endianness
49
WriteStringViewUnsafe
(
writer
,
std::string_view{
reinterpret_cast
<
const
char
*>(&value),
sizeof
(value)}
)
;
50
}
51
52
/// @brief Helpers for deserialization trivially-copyable types
53
template
<
typename
T>
54
T ReadTrivial(
Reader
& reader) {
55
static_assert
(std::is_trivially_copyable_v<T>);
56
T value{};
57
// TODO: endianness
58
ReadStringViewUnsafe
(
reader
,
sizeof
(T)
)
.copy(
reinterpret_cast
<
char
*>(&value),
sizeof
(T));
59
return
value;
60
}
61
62
void
WriteInteger(
Writer
& writer, std::uint64_t value);
63
64
std::uint64_t ReadInteger(
Reader
& reader);
65
66
template
<
typename
Duration>
67
concept
IsDumpedAsNanoseconds =
68
std::integral<
typename
Duration::rep> && (Duration::period::num == 1) &&
69
(Duration{1} <= std::chrono::milliseconds{1}) && (1'000'000'000 % Duration::period::den == 0);
70
71
}
// namespace impl
72
73
/// @brief Write-only `std::string_view` support
74
/// @see `ReadStringViewUnsafe`
75
void
Write
(
Writer
& writer, std::string_view value);
76
77
/// @brief `std::string` serialization support
78
void
Write
(
Writer
& writer,
const
std::string& value);
79
80
/// @brief `std::string` deserialization support
81
std::string
Read
(
Reader
& reader,
To
<std::string>);
82
83
/// @brief Allows writing string literals
84
void
Write
(
Writer
& writer,
const
char
* value);
85
86
/// @brief Integral types serialization support
87
template
<
meta
::kIsInteger T>
88
void
Write
(
Writer
& writer, T value) {
89
if
constexpr
(
sizeof
(T) == 1) {
90
impl::WriteTrivial(writer, value);
91
}
else
{
92
impl::WriteInteger(writer,
static_cast
<std::uint64_t>(value));
93
}
94
}
95
96
/// @brief Integral types deserialization support
97
template
<
meta
::kIsInteger T>
98
T
Read
(
Reader
& reader,
To
<T>) {
99
if
constexpr
(
sizeof
(T) == 1) {
100
return
impl::ReadTrivial<T>(reader);
101
}
102
103
const
auto
raw = impl::ReadInteger(reader);
104
105
if
constexpr
(std::is_signed_v<T>) {
106
return
utils
::numeric_cast<T>(
static_cast
<std::int64_t>(raw));
107
}
else
{
108
return
utils
::numeric_cast<T>(raw);
109
}
110
}
111
112
/// @brief Floating-point serialization support
113
template
<
std
::floating_point T>
114
void
Write
(
Writer
& writer, T value) {
115
impl::WriteTrivial(writer, value);
116
}
117
118
/// @brief Floating-point deserialization support
119
template
<
std
::floating_point T>
120
T
Read
(
Reader
& reader,
To
<T>) {
121
return
impl::ReadTrivial<T>(reader);
122
}
123
124
/// @brief bool serialization support
125
void
Write
(
Writer
& writer,
bool
value);
126
127
/// @brief bool deserialization support
128
bool
Read
(
Reader
& reader,
To
<
bool
>);
129
130
/// @brief enum serialization support
131
template
<
typename
T>
132
requires
std::is_enum_v<T>
133
void
Write
(
Writer
& writer, T value) {
134
writer.Write(
static_cast
<std::underlying_type_t<T>>(value));
135
}
136
137
/// @brief enum deserialization support
138
template
<
typename
T>
139
requires
std::is_enum_v<T>
140
T
Read
(
Reader
& reader,
To
<T>) {
141
return
static_cast
<T>(reader.Read<std::underlying_type_t<T>>());
142
}
143
144
/// @brief `std::chrono::duration` serialization support
145
template
<
typename
Rep,
typename
Period>
146
void
Write
(
Writer
& writer, std::chrono::duration<Rep, Period> value) {
147
using
std::chrono::duration, std::chrono::nanoseconds;
148
149
// Durations, which on some systems represent
150
// `std::chrono::*_clock::duration`, are serialized as `std::nanoseconds`
151
// to avoid system dependency
152
if
constexpr
(impl::IsDumpedAsNanoseconds<duration<Rep, Period>>) {
153
const
auto
count = std::chrono::duration_cast<nanoseconds>(value).count();
154
155
if
(nanoseconds{count} != value) {
156
throw
std::logic_error(
157
"Trying to serialize a huge duration, it does not fit into "
158
"std::chrono::nanoseconds type"
159
);
160
}
161
impl::WriteTrivial(writer, count);
162
}
else
{
163
impl::WriteTrivial(writer, value.count());
164
}
165
}
166
167
/// @brief `std::chrono::duration` deserialization support
168
template
<
typename
Rep,
typename
Period>
169
std::chrono::duration<Rep, Period>
Read
(
Reader
& reader,
To
<std::chrono::duration<Rep, Period>>) {
170
using
std::chrono::duration, std::chrono::nanoseconds;
171
172
if
constexpr
(impl::IsDumpedAsNanoseconds<duration<Rep, Period>>) {
173
const
auto
count = impl::ReadTrivial<nanoseconds::rep>(reader);
174
return
std::chrono::duration_cast<duration<Rep, Period>>(nanoseconds{count});
175
}
else
{
176
const
auto
count = impl::ReadTrivial<Rep>(reader);
177
return
duration<Rep, Period>{count};
178
}
179
}
180
181
/// @brief `std::chrono::time_point` serialization support
182
/// @note Only `system_clock` is supported, because `steady_clock` can only
183
/// be used within a single execution
184
template
<
typename
Duration>
185
void
Write
(
Writer
& writer, std::chrono::time_point<std::chrono::system_clock, Duration> value) {
186
writer.Write(value.time_since_epoch());
187
}
188
189
/// @brief `std::chrono::time_point` deserialization support
190
/// @note Only `system_clock` is supported, because `steady_clock` can only
191
/// be used within a single execution
192
template
<
typename
Duration>
193
auto
Read
(
Reader
& reader,
To
<std::chrono::time_point<std::chrono::system_clock, Duration>>) {
194
return
std::chrono::time_point<std::chrono::system_clock, Duration>{reader.Read<Duration>()};
195
}
196
197
/// @brief `boost::uuids::uuid` serialization support
198
void
Write
(
Writer
& writer,
const
boost::
uuids
::uuid& value);
199
200
/// @brief `boost::uuids::uuid` deserialization support
201
boost::
uuids
::uuid
Read
(
Reader
& reader,
To
<boost::
uuids
::uuid>);
202
203
/// @brief decimal64::Decimal serialization support
204
template
<
int
Prec,
typename
RoundPolicy>
205
inline
void
Write
(
Writer
& writer,
const
decimal64
::
Decimal
<Prec, RoundPolicy>& dec) {
206
writer.Write(dec.AsUnbiased());
207
}
208
209
/// @brief decimal64::Decimal deserialization support
210
template
<
int
Prec,
typename
RoundPolicy>
211
auto
Read
(
Reader
& reader,
dump
::
To
<
decimal64
::
Decimal
<Prec, RoundPolicy>>) {
212
return
decimal64
::
Decimal
<Prec, RoundPolicy>::FromUnbiased(reader
.
Read
<
int64_t
>
(
)
);
213
}
214
215
/// @brief formats::json::Value serialization support
216
void
Write
(
Writer
& writer,
const
formats::
json
::
Value
& value);
217
218
/// @brief formats::json::Value deserialization support
219
formats::
json
::
Value
Read
(
Reader
& reader,
To
<formats::
json
::
Value
>);
220
221
}
// namespace dump
222
223
USERVER_NAMESPACE_END
userver
dump
common.hpp
Generated on
for userver by
Doxygen
1.17.0