inline void serialize()

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