23 if constexpr (std::is_arithmetic_v<T>) {
25 }
else if constexpr (std::is_enum_v<T>) {
26 static_assert(!std::is_convertible_v<T, std::underlying_type_t<T>>,
"Serializing unscoped enum");
33 template <
template <
typename>
class C,
typename T>
35 using type = std::decay_t<C<T>>;
37 std::is_same_v<std::vector<T>, type> ||
38 std::is_same_v<std::list<T>, type> ||
39 std::is_same_v<std::deque<T>, type> ||
40 std::is_same_v<std::set<T>, type>;
43 template <
typename R,
typename C>
45 template <
typename R,
typename C>
48 template <
typename... Args>
52 template <
std::size_t I,
typename Arg,
typename... Args>
54 std::memcpy(s.data()+I, &arg,
sizeof(Arg));
55 if constexpr (std::is_integral_v<std::decay_t<Arg>> ||
57 std::reverse(s.data()+I, s.data()+I+
sizeof(Arg));
59 if constexpr (
sizeof...(Args) > 0) {
60 return const_pack_helper<I+sizeof(Arg)>(s, std::forward<Args>(args)...);
65 template <
typename... Args>
68 s.resize(total_bytes_size<Args...>());
69 const_pack_helper<0>(s, std::forward<Args>(args)...);
97template <
typename T,
typename S>
100template <
int I,
typename T,
typename S>
102 if constexpr (I < std::tuple_size_v<T>) {
103 to_key(std::get<I>(obj), stream);
104 to_key_tuple<I + 1>(obj, stream);
108template <
typename... Ts,
typename S>
110 to_key_tuple<0>(obj, stream);
113template <
typename T, std::
size_t N,
typename S>
115 for (
const T& elem : obj) {
to_key(elem, stream); }
118template <
typename T,
typename S>
129template <
typename T,
typename S>
131 if constexpr (detail::has_bitwise_serialization<T>() &&
sizeof(T) == 1) {
133 stream.
write(
"\0", 2);
138 stream.
write(buf[0]);
152template <
typename T,
typename U,
typename S>
154 to_key(obj.first, stream);
155 to_key(obj.second, stream);
158template <
typename T,
typename S>
161 to_key_optional((std::add_pointer_t<
decltype(*std::begin(obj))>)
nullptr, stream);
164template <
typename T,
typename S>
165auto to_key(
const T& obj,
datastream<S>& stream) -> std::enable_if_t<is_ranged_type(std::declval<T>()),
void> {
169template <
typename T,
typename U,
typename S>
174template <
typename T,
typename S>
193 }
else if (obj < 0x4000u) {
195 }
else if (obj < 0x200000u) {
197 }
else if (obj < 0x10000000u) {
204 static_cast<char>(~(0xFFu >> (num_bytes - 1)) | (num_bytes == 5 ? 0 : (obj >> ((num_bytes - 1) * 8)))));
205 for (
int i = num_bytes - 2; i >= 0; --i) { stream.
write(
static_cast<char>((obj >> i * 8) & 0xFFu)); }
227 static_assert(std::is_same_v<S, void>,
"to_key for varint32 has been temporarily disabled");
229 bool sign = (obj < 0);
230 if (obj < 0x40 && obj >= -0x40) {
232 }
else if (obj < 0x2000 && obj >= -0x2000) {
234 }
else if (obj < 0x100000 && obj >= -0x100000) {
236 }
else if (obj < 0x08000000 && obj >= -0x08000000) {
242 unsigned char width_field;
244 width_field = 0x80u >> num_bytes;
246 width_field = 0x80u | ~(0xFFu >> num_bytes);
249 unsigned char value_mask = (0xFFu >> (num_bytes + 1));
250 unsigned char high_byte = (num_bytes == 5 ? (sign ? 0xFF : 0) : (uobj >> ((num_bytes - 1) * 8)));
251 stream.
write(width_field | (high_byte & value_mask));
252 for (
int i = num_bytes - 2; i >= 0; --i) { stream.
write(
static_cast<char>((uobj >> i * 8) & 0xFFu)); }
255template <
typename... Ts,
typename S>
258 std::visit([&](
const auto& item) {
to_key(item, stream); }, obj);
261template <std::
size_t N,
typename S>
263 to_key(std::string_view{str, N-1}, stream);
268 for (
char ch : obj) {
274 stream.
write(
"\0", 2);
279 to_key(std::string_view(obj), stream);
284 stream.
write(
static_cast<char>(obj ? 1 : 0));
287template <
typename UInt,
typename T>
289 static_assert(
sizeof(T) ==
sizeof(UInt),
"Expected unsigned int of the same size");
291 std::memcpy(&
result, &value,
sizeof(T));
292 UInt signbit = (
static_cast<UInt
>(1) << (std::numeric_limits<UInt>::digits - 1));
298 return result ^ (mask | signbit);
301template <
typename T,
typename S>
303 if constexpr (std::is_floating_point_v<T>) {
304 if constexpr (
sizeof(T) == 4) {
305 to_key(float_to_key<uint32_t>(obj), stream);
307 static_assert(
sizeof(T) == 8,
"Unknown floating point type");
308 to_key(float_to_key<uint64_t>(obj), stream);
310 }
else if constexpr (std::is_integral_v<T>) {
311 auto v =
static_cast<std::make_unsigned_t<T>
>(obj);
312 v -=
static_cast<std::make_unsigned_t<T>
>(std::numeric_limits<T>::min());
313 std::reverse(
reinterpret_cast<char*
>(&v),
reinterpret_cast<char*
>(&v + 1));
314 stream.
write(&v,
sizeof(v));
315 }
else if constexpr (std::is_enum_v<T>) {
316 static_assert(!std::is_convertible_v<T, std::underlying_type_t<T>>,
"Serializing unscoped enum");
317 to_key(
static_cast<std::underlying_type_t<T>
>(obj), stream);
319 using ts_meta = bluegrass::meta::meta_object<T>;
320 ts_meta::for_each_field(obj, [&](
const auto& member) {
330 auto orig_size = bin.size();
331 bin.resize(orig_size + ss.
tellp());