#ifndef RFL_PARSING_FIELDVARIANTREADER_HPP_ #define RFL_PARSING_FIELDVARIANTREADER_HPP_ #include #include #include #include #include #include #include "../Result.hpp" #include "../internal/is_array.hpp" namespace rfl::parsing { template class FieldVariantReader { private: using InputVarType = typename R::InputVarType; using FieldVariantType = std::variant; using ResultType = Result; public: FieldVariantReader( const R* _r, std::optional>* _field_variant ) : r_(_r), field_variant_(_field_variant) {} ~FieldVariantReader() = default; template void read(const std::string_view& _disc_value, const InputVarType& _var) const noexcept { if constexpr (_i < sizeof...(FieldTypes)) { if constexpr (_i == 0) { if (*field_variant_) { *field_variant_ = Error( "Could not parse: Expected the object to have " "exactly one field, but found more than one." ); return; } } using FieldType = std::remove_cvref_t< typename std::tuple_element<_i, std::tuple>::type>; using ValueType = std::remove_cvref_t; constexpr auto key = FieldType::name_.string_view(); if (key == _disc_value) { const auto to_variant = [](ValueType&& _val) { return std::variant(FieldType(std::move(_val))); }; const auto embellish_error = [&](const Error& _e) { return Error( "Could not parse std::variant with field '" + std::string(_disc_value) + "': " + _e.what() ); }; *field_variant_ = Parser::read(*r_, _var) .transform(to_variant) .or_else(embellish_error); return; } else { read<_i + 1>(_disc_value, _var); } } else { *field_variant_ = Error( "Could not parse std::variant, could not match field named " "'" + std::string(_disc_value) + "'." ); } } private: /// The underlying reader. const R* r_; /// The underlying field variant. std::optional>* field_variant_; }; } // namespace rfl::parsing #endif