inline Result deserialize()

in src/common/serde/Serde.h [465:680]


inline Result<Void> deserialize(auto &o, auto &&in) requires is_specialization<std::decay_t<decltype(in)>, In> {
  using T = std::decay_t<decltype(o)>;
  using I = std::decay_t<decltype(in)>;
  constexpr bool isBinaryIn = requires { typename I::is_binary_in; };
  if constexpr (!isBinaryIn && requires { function_first_parameter_t<&T::serdeFromReadable>{}; }) {
    // 0. custom serde impl.
    function_first_parameter_t<&T::serdeFromReadable> from{};
    RETURN_AND_LOG_ON_ERROR(deserialize(from, in));
    auto result = T::serdeFromReadable(from);
    RETURN_AND_LOG_ON_ERROR(result);
    o = std::move(*result);
    return Void{};
  } else if constexpr (!isBinaryIn && requires { function_first_parameter_t<&SerdeMethod<T>::serdeFromReadable>{}; }) {
    function_first_parameter_t<&SerdeMethod<T>::serdeFromReadable> from{};
    RETURN_AND_LOG_ON_ERROR(deserialize(from, in));
    auto result = SerdeMethod<T>::serdeFromReadable(from);
    RETURN_AND_LOG_ON_ERROR(result);
    o = std::move(*result);
    return Void{};
  } else if constexpr (requires { function_first_parameter_t<&SerdeMethod<T>::serdeFrom>{}; }) {
    // 0. custom serde impl.
    function_first_parameter_t<&SerdeMethod<T>::serdeFrom> from{};
    RETURN_AND_LOG_ON_ERROR(deserialize(from, in));
    auto result = SerdeMethod<T>::serdeFrom(from);
    RETURN_AND_LOG_ON_ERROR(result);
    o = std::move(*result);
    return Void{};
  } else if constexpr (!isBinaryIn && requires { SerdeMethod<T>::deserializeReadable(o, in); }) {
    return SerdeMethod<T>::deserializeReadable(o, in);
  } else if constexpr (requires { SerdeMethod<T>::deserialize(o, in); }) {
    return SerdeMethod<T>::deserialize(o, in);
  } else if constexpr (SerdeType<T>) {
    auto table = in.parseTable();
    RETURN_AND_LOG_ON_ERROR(table);
    if constexpr (isBinaryIn) {
      return refl::Helper::iterate<T>(
          [&](auto type) -> Result<Void> {
            if (LIKELY(*table)) {
              return deserialize(o.*type.getter, *table);
            }
            // Missing fields at the end are acceptable.
            return Void{};
          },
          [&]() -> Result<Void> {
            table = in.parseTable();
            RETURN_AND_LOG_ON_ERROR(table);
            return Void{};
          });
    } else {
      return refl::Helper::iterate<T>([&](auto type) -> Result<Void> {
        auto value = table->parseKey(type.name);
        if (LIKELY(bool(value))) {
          return deserialize(o.*type.getter, *value);
        } else {
          using ItemType = std::decay_t<decltype(o.*type.getter)>;
          if constexpr (is_optional_v<ItemType>) {
            o.*type.getter = std::nullopt;
          } else if constexpr (is_unique_ptr_v<ItemType> || is_shared_ptr_v<ItemType>) {
            o.*type.getter = nullptr;
          }
        }
        return Void{};
      });
    }
  } else if constexpr (std::is_same_v<std::string, T> || std::is_same_v<std::string_view, T>) {
    auto result = in.parseString();
    RETURN_AND_LOG_ON_ERROR(result);
    o = *result;
    return Void{};
  } else if constexpr (is_optional_v<T>) {
    Optional optional;
    RETURN_AND_LOG_ON_ERROR(in.parseOptional(optional));
    if (optional == Optional::HasValue) {
      std::remove_cv_t<typename T::value_type> value;
      RETURN_AND_LOG_ON_ERROR(deserialize(value, in));
      o = std::move(value);
    } else {
      o = std::nullopt;
    }
    return Void{};
  } else if constexpr (is_unique_ptr_v<T> || is_shared_ptr_v<T>) {
    Optional optional;
    RETURN_AND_LOG_ON_ERROR(in.parseOptional(optional));
    if (optional == Optional::HasValue) {
      if constexpr (is_unique_ptr_v<T>) {
        o = std::make_unique<typename T::element_type>();
      } else {
        o = std::make_shared<typename T::element_type>();
      }
      RETURN_AND_LOG_ON_ERROR(deserialize(*o, in));
    } else {
      o = nullptr;
    }
    return Void{};
  } else if constexpr (is_variant_v<T>) {
    auto variant = in.parseVariant();
    RETURN_AND_LOG_ON_ERROR(variant);
    return callByIdx<type_list_t<T>>(
        [&](auto type) -> Result<Void> {
          if constexpr (std::is_same_v<decltype(type), std::nullptr_t>) {
            if constexpr (is_auto_fallback_variant_v<T>) {
              UnknownVariantType uvt;
              uvt.type = variant->first;
              o = std::move(uvt);
              return Void{};
            } else {
              return makeError(StatusCode::kSerdeVariantIndexExceeded);
            }
          } else {
            RETURN_AND_LOG_ON_ERROR(deserialize(type, variant->second));
            o = std::move(type);
            return Void{};
          }
        },
        variantTypeNameToIndex<T>(variant->first));
    return Void{};
  } else if constexpr (is_generic_pair_v<T> && isBinaryIn) {
    RETURN_AND_LOG_ON_ERROR(deserialize(o.first, in));
    RETURN_AND_LOG_ON_ERROR(deserialize(o.second, in));
    return Void{};
  } else if constexpr (Container<T> && isBinaryIn) {
    Varint64 size = 0;
    RETURN_AND_LOG_ON_ERROR(deserialize(size, in));
    o.clear();
    if constexpr (requires { o.reserve(size); }) {
      o.reserve(size);
    }
    auto inserter = std::inserter(o, o.end());
    for (uint32_t i = 0; i < size; ++i) {
      if constexpr (is_generic_pair_v<typename T::value_type>) {
        std::remove_cv_t<typename T::value_type::first_type> first;
        RETURN_AND_LOG_ON_ERROR(deserialize(first, in));
        std::remove_cv_t<typename T::value_type::second_type> second;
        RETURN_AND_LOG_ON_ERROR(deserialize(second, in));
        inserter++ = typename T::value_type{std::move(first), std::move(second)};
      } else {
        auto value = DefaultConstructor<std::remove_cv_t<typename T::value_type>>::construct();
        RETURN_AND_LOG_ON_ERROR(deserialize(value, in));
        inserter++ = std::move(value);
      }
    }
    return Void{};
  } else if constexpr (is_vector_v<T> || is_set_v<T> || is_map_v<T>) {
    auto containerResult = in.parseContainer();
    RETURN_AND_LOG_ON_ERROR(containerResult);
    auto size = containerResult->first;
    auto it = std::move(containerResult->second);
    o.clear();
    if constexpr (requires { o.reserve(size); }) {
      o.reserve(size);
    }
    auto inserter = std::inserter(o, o.end());
    for (uint32_t i = 0; i < size; ++i) {
      if constexpr (is_map_v<T>) {
        auto keyResult = in.fetchKey(it);
        RETURN_AND_LOG_ON_ERROR(keyResult);
        std::string_view key = *keyResult;
        using KeyType = std::remove_cv_t<typename T::value_type::first_type>;
        KeyType first;
        if constexpr (requires { first = KeyType{key}; }) {
          first = KeyType{key};
        } else if constexpr (requires { scn::scan(key, "{}", first); }) {
          auto result = scn::scan(key, "{}", first);
          if (!result) {
            return makeError(StatusCode::kInvalidArg);
          }
        } else if constexpr (requires { scn::scan(key, "{}", first.toUnderType()); }) {
          auto result = scn::scan(key, "{}", first.toUnderType());
          if (!result) {
            return makeError(StatusCode::kInvalidArg);
          }
        } else {
          return makeError(StatusCode::kInvalidArg);
        }
        std::remove_cv_t<typename T::value_type::second_type> second;
        RETURN_AND_LOG_ON_ERROR(deserialize(second, in.fetchValue(it)));
        inserter++ = typename T::value_type{std::move(first), std::move(second)};
        in.next(it);
      } else {
        std::remove_cv_t<typename T::value_type> value;
        RETURN_AND_LOG_ON_ERROR(deserialize(value, in.fetchAndNext(it)));
        inserter++ = std::move(value);
      }
    }
    return Void{};
  } else if constexpr (isBinaryIn && SerdeCopyable<T>) {
    return in.parseCopyable(o);
  } else if constexpr (std::is_same_v<T, bool>) {
    auto result = in.parseBoolean();
    RETURN_AND_LOG_ON_ERROR(result);
    o = *result;
    return Void{};
  } else if constexpr (std::is_integral_v<T>) {
    auto result = in.parseInteger();
    RETURN_AND_LOG_ON_ERROR(result);
    o = *result;
    return Void{};
  } else if constexpr (std::is_floating_point_v<T>) {
    auto result = in.parseFloat();
    RETURN_AND_LOG_ON_ERROR(result);
    o = *result;
    return Void{};
  } else if constexpr (std::is_enum_v<T>) {
    std::string_view str;
    RETURN_AND_LOG_ON_ERROR(deserialize(str, in));
    auto result = magic_enum::enum_cast<T>(str);
    if (result.has_value()) {
      o = *result;
      return Void{};
    }
    return makeError(StatusCode::kSerdeUnknownEnumValue,
                     fmt::format("unknown enum value {} for type {}", str, nameof::nameof_full_type<T>()));
  } else {
    return notSupportToDeserialize(o, in);
  }
}