in src/common/serde/Serde.h [267:378]
inline void serialize(auto &&o, Out<O> &out) {
using T = std::decay_t<decltype(o)>;
constexpr bool isBinaryOut = requires { typename Out<O>::is_binary_out; };
if constexpr (requires { o.serdeToReadable(); } && !isBinaryOut) {
serialize(o.serdeToReadable(), out);
} else if constexpr (requires { SerdeMethod<T>::serializeReadable(o, out); } && !isBinaryOut) {
SerdeMethod<T>::serializeReadable(o, out);
} else if constexpr (requires { SerdeMethod<T>::serdeToReadable(o); } && !isBinaryOut) {
serialize(SerdeMethod<T>::serdeToReadable(o), out);
} else if constexpr (requires { SerdeMethod<T>::serialize(o, out); }) {
static_assert(requires(T t, In<std::string_view> in) { Result<Void>{SerdeMethod<T>::deserialize(t, in)}; });
SerdeMethod<T>::serialize(o, out);
} else if constexpr (requires { SerdeMethod<T>::serdeTo(o); }) {
static_assert(requires { SerdeMethod<T>::serdeFrom(SerdeMethod<T>::serdeTo(o)); });
serialize(SerdeMethod<T>::serdeTo(o), out);
} else if constexpr (SerdeType<T>) {
auto start = out.tableBegin(false);
if constexpr (isBinaryOut) {
refl::Helper::iterate<T, true>([&](auto type) { serialize(o.*type.getter, out); },
[&] { out.tableEnd(start), start = out.tableBegin(false); });
} else {
refl::Helper::iterate<T>([&](auto type) { out.key(type.name), serialize(o.*type.getter, out); });
}
out.tableEnd(start);
} else if constexpr (std::is_same_v<T, std::string>) {
out.value(o);
} else if constexpr (std::is_convertible_v<T, std::string_view>) {
out.value(std::string_view(o));
} else if constexpr (is_optional_v<T>) {
if (o.has_value()) {
serialize(o.value(), out);
out.value(Optional::HasValue);
} else {
out.value(Optional::NullOpt);
}
} else if constexpr (is_unique_ptr_v<T> || is_shared_ptr_v<T>) {
if (o) {
serialize(*o, out);
out.value(Optional::HasValue);
} else {
out.value(Optional::NullOpt);
}
} else if constexpr (is_variant_v<T> && isBinaryOut) {
static_assert(std::variant_size_v<T> <= std::numeric_limits<uint8_t>::max());
std::visit(
[&out](auto &&v) {
serialize(v, out);
serialize(type_name_v<std::decay_t<decltype(v)>>, out);
},
o);
} else if constexpr (is_variant_v<T>) {
static_assert(std::variant_size_v<T> <= std::numeric_limits<uint8_t>::max());
auto start = out.tableBegin(true);
out.key("type");
std::visit(
[&out](auto &&v) {
serialize(type_name_v<std::decay_t<decltype(v)>>, out);
out.key("value");
serialize(v, out);
},
o);
out.tableEnd(start);
} else if constexpr (is_generic_pair_v<T> && isBinaryOut) {
serialize(o.second, out);
serialize(o.first, out);
} else if constexpr (Container<T> && isBinaryOut) {
out.arrayBegin();
if constexpr (requires { o.rbegin(); }) {
for (auto it = o.rbegin(); it != o.rend(); ++it) {
serialize(*it, out);
}
} else {
for (auto &item : o) {
serialize(item, out);
}
}
out.arrayEnd(o.size());
} else if constexpr (is_vector_v<T> && std::is_arithmetic_v<T> && isBinaryOut) {
out.value(o);
} else if constexpr (is_vector_v<T> || is_set_v<T>) {
out.arrayBegin();
for (const auto &item : o) {
serialize(item, out);
}
out.arrayEnd(o.size());
} else if constexpr (is_map_v<T>) {
auto start = out.tableBegin(true);
for (const auto &pair : o) {
if constexpr (requires { out.key(pair.first); }) {
out.key(pair.first);
} else if constexpr (requires { pair.first.toUnderType(); }) {
out.key(fmt::format("{}", pair.first.toUnderType()));
} else {
out.key(fmt::format("{}", pair.first));
}
serialize(pair.second, out);
}
out.tableEnd(start);
} else if constexpr (isBinaryOut && SerdeCopyable<T>) {
out.value(o);
} else if constexpr (std::is_same_v<T, bool>) {
out.value(o);
} else if constexpr (std::is_integral_v<T>) {
out.value(int64_t(o));
} else if constexpr (std::is_floating_point_v<T>) {
out.value(double(o));
} else if constexpr (std::is_enum_v<T>) {
out.value(magic_enum::enum_name(o));
} else {
return notSupportToSerialize(o);
}
}