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>());