16#include <userver/dump/operations.hpp>
17#include <userver/dump/unsafe.hpp>
18#include <userver/utils/meta_light.hpp>
19#include <userver/utils/numeric_cast.hpp>
21namespace boost::uuids {
25USERVER_NAMESPACE_BEGIN
28template <
int Prec,
typename RoundPolicy>
32namespace formats::
json {
45void WriteTrivial(
Writer& writer, T value) {
46 static_assert(std::is_trivially_copyable_v<T>);
48 WriteStringViewUnsafe(writer, std::string_view{
reinterpret_cast<
const char*>(&value),
sizeof(value)});
53T ReadTrivial(
Reader& reader) {
54 static_assert(std::is_trivially_copyable_v<T>);
61void WriteInteger(
Writer& writer, std::uint64_t value);
63std::uint64_t ReadInteger(
Reader& reader);
65template <
typename Duration>
66inline constexpr bool kIsDumpedAsNanoseconds =
67 std::is_integral_v<
typename Duration::rep> && (Duration::period::num == 1) &&
68 (Duration{1} <= std::chrono::milliseconds{1}) && (1'000'000'000 % Duration::period::den == 0);
88 if constexpr (
sizeof(T) == 1) {
89 impl::WriteTrivial(writer, value);
91 impl::WriteInteger(writer,
static_cast<std::uint64_t>(value));
98 if constexpr (
sizeof(T) == 1) {
99 return impl::ReadTrivial<T>(reader);
102 const auto raw = impl::ReadInteger(reader);
104 if constexpr (std::is_signed_v<T>) {
105 return utils::numeric_cast<T>(
static_cast<std::int64_t>(raw));
107 return utils::numeric_cast<T>(raw);
114 impl::WriteTrivial(writer, value);
120 return impl::ReadTrivial<T>(reader);
132 writer.Write(
static_cast<std::underlying_type_t<T>>(value));
138 return static_cast<T>(reader.Read<std::underlying_type_t<T>>());
142template <
typename Rep,
typename Period>
143void Write(
Writer& writer, std::chrono::duration<Rep, Period> value) {
144 using std::chrono::duration, std::chrono::nanoseconds;
149 if constexpr (impl::kIsDumpedAsNanoseconds<duration<Rep, Period>>) {
150 const auto count = std::chrono::duration_cast<nanoseconds>(value).count();
152 if (nanoseconds{count} != value) {
153 throw std::logic_error(
154 "Trying to serialize a huge duration, it does not fit into "
155 "std::chrono::nanoseconds type"
158 impl::WriteTrivial(writer, count);
160 impl::WriteTrivial(writer, value.count());
165template <
typename Rep,
typename Period>
166std::chrono::duration<Rep, Period>
Read(
Reader& reader, To<std::chrono::duration<Rep, Period>>) {
167 using std::chrono::duration, std::chrono::nanoseconds;
169 if constexpr (impl::kIsDumpedAsNanoseconds<duration<Rep, Period>>) {
170 const auto count = impl::ReadTrivial<nanoseconds::rep>(reader);
171 return std::chrono::duration_cast<duration<Rep, Period>>(nanoseconds{count});
173 const auto count = impl::ReadTrivial<Rep>(reader);
174 return duration<Rep, Period>{count};
181template <
typename Duration>
182void Write(
Writer& writer, std::chrono::time_point<std::chrono::system_clock, Duration> value) {
183 writer.Write(value.time_since_epoch());
189template <
typename Duration>
190auto Read(
Reader& reader, To<std::chrono::time_point<std::chrono::system_clock, Duration>>) {
191 return std::chrono::time_point<std::chrono::system_clock, Duration>{reader.Read<Duration>()};
198boost::uuids::uuid
Read(
Reader& reader, To<boost::uuids::uuid>);
201template <
int Prec,
typename RoundPolicy>
203 writer.Write(dec.AsUnbiased());
207template <
int Prec,
typename RoundPolicy>
209 return decimal64::Decimal<Prec, RoundPolicy>::FromUnbiased(reader.Read<int64_t>());