binary_serialization.ipp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. //
  2. // Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BHO_MYSQL_IMPL_INTERNAL_PROTOCOL_BINARY_SERIALIZATION_IPP
  8. #define BHO_MYSQL_IMPL_INTERNAL_PROTOCOL_BINARY_SERIALIZATION_IPP
  9. #pragma once
  10. #include <asio2/bho/mysql/days.hpp>
  11. #include <asio2/bho/mysql/detail/config.hpp>
  12. #include <asio2/bho/mysql/impl/internal/protocol/binary_serialization.hpp>
  13. #include <asio2/bho/mysql/impl/internal/protocol/constants.hpp>
  14. #include <asio2/bho/mysql/impl/internal/protocol/serialization.hpp>
  15. #include <chrono>
  16. namespace bho {
  17. namespace mysql {
  18. namespace detail {
  19. // Binary serialization
  20. template <class T>
  21. BHO_MYSQL_STATIC_OR_INLINE void serialize_binary_float(serialization_context& ctx, T input)
  22. {
  23. bho::endian::endian_store<T, sizeof(T), bho::endian::order::little>(ctx.first(), input);
  24. ctx.advance(sizeof(T));
  25. }
  26. BHO_MYSQL_STATIC_OR_INLINE
  27. void serialize_binary_date(serialization_context& ctx, const date& input)
  28. {
  29. using namespace binc;
  30. serialize(ctx, static_cast<std::uint8_t>(date_sz), input.year(), input.month(), input.day());
  31. }
  32. BHO_MYSQL_STATIC_OR_INLINE
  33. void serialize_binary_datetime(serialization_context& ctx, const datetime& input)
  34. {
  35. using namespace binc;
  36. // Serialize
  37. serialize(
  38. ctx,
  39. static_cast<std::uint8_t>(datetime_dhmsu_sz),
  40. input.year(),
  41. input.month(),
  42. input.day(),
  43. input.hour(),
  44. input.minute(),
  45. input.second(),
  46. input.microsecond()
  47. );
  48. }
  49. BHO_MYSQL_STATIC_OR_INLINE
  50. void serialize_binary_time(serialization_context& ctx, const bho::mysql::time& input)
  51. {
  52. using namespace binc;
  53. using bho::mysql::days;
  54. using std::chrono::duration_cast;
  55. using std::chrono::hours;
  56. using std::chrono::microseconds;
  57. using std::chrono::minutes;
  58. using std::chrono::seconds;
  59. // Break time
  60. auto num_micros = duration_cast<microseconds>(input % seconds(1));
  61. auto num_secs = duration_cast<seconds>(input % minutes(1) - num_micros);
  62. auto num_mins = duration_cast<minutes>(input % hours(1) - num_secs);
  63. auto num_hours = duration_cast<hours>(input % days(1) - num_mins);
  64. auto num_days = duration_cast<days>(input - num_hours);
  65. std::uint8_t is_negative = (input.count() < 0) ? 1 : 0;
  66. // Serialize
  67. serialize(
  68. ctx,
  69. static_cast<std::uint8_t>(time_dhmsu_sz),
  70. is_negative,
  71. static_cast<std::uint32_t>(std::abs(num_days.count())),
  72. static_cast<std::uint8_t>(std::abs(num_hours.count())),
  73. static_cast<std::uint8_t>(std::abs(num_mins.count())),
  74. static_cast<std::uint8_t>(std::abs(num_secs.count())),
  75. static_cast<std::uint32_t>(std::abs(num_micros.count()))
  76. );
  77. }
  78. } // namespace detail
  79. } // namespace mysql
  80. } // namespace bho
  81. std::size_t bho::mysql::detail::get_size(field_view input) noexcept
  82. {
  83. switch (input.kind())
  84. {
  85. case field_kind::null: return 0;
  86. case field_kind::int64: return 8;
  87. case field_kind::uint64: return 8;
  88. case field_kind::string: return get_size(string_lenenc{input.get_string()});
  89. case field_kind::blob: return get_size(string_lenenc{to_string(input.get_blob())});
  90. case field_kind::float_: return 4;
  91. case field_kind::double_: return 8;
  92. case field_kind::date: return binc::date_sz + binc::length_sz;
  93. case field_kind::datetime: return binc::datetime_dhmsu_sz + binc::length_sz;
  94. case field_kind::time: return binc::time_dhmsu_sz + binc::length_sz;
  95. default: BHO_ASSERT(false); return 0;
  96. }
  97. }
  98. void bho::mysql::detail::serialize(serialization_context& ctx, field_view input) noexcept
  99. {
  100. switch (input.kind())
  101. {
  102. case field_kind::null: break;
  103. case field_kind::int64: serialize(ctx, input.get_int64()); break;
  104. case field_kind::uint64: serialize(ctx, input.get_uint64()); break;
  105. case field_kind::string: serialize(ctx, string_lenenc{input.get_string()}); break;
  106. case field_kind::blob: serialize(ctx, string_lenenc{to_string(input.get_blob())}); break;
  107. case field_kind::float_: serialize_binary_float(ctx, input.get_float()); break;
  108. case field_kind::double_: serialize_binary_float(ctx, input.get_double()); break;
  109. case field_kind::date: serialize_binary_date(ctx, input.get_date()); break;
  110. case field_kind::datetime: serialize_binary_datetime(ctx, input.get_datetime()); break;
  111. case field_kind::time: serialize_binary_time(ctx, input.get_time()); break;
  112. default: BHO_ASSERT(false); break;
  113. }
  114. }
  115. #endif