16#include <boost/numeric/conversion/cast.hpp>
18#include <userver/dump/operations.hpp>
19#include <userver/dump/unsafe.hpp>
20#include <userver/utils/meta_light.hpp>
22namespace boost::uuids {
26USERVER_NAMESPACE_BEGIN
29template <
int Prec,
typename RoundPolicy>
33namespace formats::
json {
46void WriteTrivial(
Writer& writer, T value) {
47 static_assert(std::is_trivially_copyable_v<T>);
49 WriteStringViewUnsafe(
51 std::string_view{
reinterpret_cast<
const char*>(&value),
sizeof(value)});
56T ReadTrivial(
Reader& reader) {
57 static_assert(std::is_trivially_copyable_v<T>);
61 .copy(
reinterpret_cast<
char*>(&value),
sizeof(T));
65void WriteInteger(
Writer& writer, std::uint64_t value);
67std::uint64_t ReadInteger(
Reader& reader);
69template <
typename Duration>
70inline constexpr bool kIsDumpedAsNanoseconds =
71 std::is_integral_v<
typename Duration::rep> &&
72 (Duration::period::num == 1) &&
73 (Duration{1} <= std::chrono::milliseconds{1}) &&
74 (1'000'000'000 % Duration::period::den == 0);
94 if constexpr (
sizeof(T) == 1) {
95 impl::WriteTrivial(writer, value);
97 impl::WriteInteger(writer,
static_cast<std::uint64_t>(value));
104 if constexpr (
sizeof(T) == 1) {
105 return impl::ReadTrivial<T>(reader);
108 const auto raw = impl::ReadInteger(reader);
110 if constexpr (std::is_signed_v<T>) {
111 return boost::numeric_cast<T>(
static_cast<std::int64_t>(raw));
113 return boost::numeric_cast<T>(raw);
120 impl::WriteTrivial(writer, value);
126 return impl::ReadTrivial<T>(reader);
138 writer.Write(
static_cast<std::underlying_type_t<T>>(value));
144 return static_cast<T>(reader.Read<std::underlying_type_t<T>>());
148template <
typename Rep,
typename Period>
149void Write(
Writer& writer, std::chrono::duration<Rep, Period> value) {
150 using std::chrono::duration, std::chrono::nanoseconds;
155 if constexpr (impl::kIsDumpedAsNanoseconds<duration<Rep, Period>>) {
156 const auto count = std::chrono::duration_cast<nanoseconds>(value).count();
158 if (nanoseconds{count} != value) {
159 throw std::logic_error(
160 "Trying to serialize a huge duration, it does not fit into "
161 "std::chrono::nanoseconds type");
163 impl::WriteTrivial(writer, count);
165 impl::WriteTrivial(writer, value.count());
170template <
typename Rep,
typename Period>
171std::chrono::duration<Rep, Period>
Read(
172 Reader& reader, To<std::chrono::duration<Rep, Period>>) {
173 using std::chrono::duration, std::chrono::nanoseconds;
175 if constexpr (impl::kIsDumpedAsNanoseconds<duration<Rep, Period>>) {
176 const auto count = impl::ReadTrivial<nanoseconds::rep>(reader);
177 return std::chrono::duration_cast<duration<Rep, Period>>(
180 const auto count = impl::ReadTrivial<Rep>(reader);
181 return duration<Rep, Period>{count};
188template <
typename Duration>
190 std::chrono::time_point<std::chrono::system_clock, Duration> value) {
191 writer.Write(value.time_since_epoch());
197template <
typename Duration>
199 To<std::chrono::time_point<std::chrono::system_clock, Duration>>) {
200 return std::chrono::time_point<std::chrono::system_clock, Duration>{
201 reader.Read<Duration>()};
208boost::uuids::uuid
Read(
Reader& reader, To<boost::uuids::uuid>);
211template <
int Prec,
typename RoundPolicy>
214 writer.Write(dec.AsUnbiased());
218template <
int Prec,
typename RoundPolicy>
221 reader.Read<int64_t>());