#ifndef RFL_PARSING_TUPLEPARSER_HPP_ #define RFL_PARSING_TUPLEPARSER_HPP_ #include #include #include #include "../Result.hpp" #include "../always_false.hpp" #include "Parent.hpp" #include "TupleReader.hpp" #include "schema/Type.hpp" namespace rfl::parsing { template requires AreReaderAndWriter> struct TupleParser { public: using InputArrayType = typename R::InputArrayType; using InputVarType = typename R::InputVarType; using OutputArrayType = typename W::OutputArrayType; using OutputVarType = typename W::OutputVarType; using ParentType = Parent; static Result> read(const R& _r, const InputVarType& _var) noexcept { const auto parse = [&](const InputArrayType& _arr) -> Result> { alignas(std::tuple) unsigned char buf[sizeof(std::tuple)]; auto ptr = reinterpret_cast*>(buf); const auto tuple_reader = TupleReader, _ignore_empty_containers, _all_required, ProcessorsType>(&_r, ptr); auto err = _r.read_array(tuple_reader, _arr); if (err) { tuple_reader.call_destructors_where_necessary(); return *err; } err = tuple_reader.handle_missing_fields(); if (err) { tuple_reader.call_destructors_where_necessary(); return *err; } return std::move(*ptr); }; return _r.to_array(_var).and_then(parse); } template static void write(const W& _w, const std::tuple& _tup, const P& _parent) noexcept { auto arr = ParentType::add_array(_w, sizeof...(Ts), _parent); const auto new_parent = typename ParentType::Array {&arr}; to_array<0>(_w, _tup, new_parent); _w.end_array(&arr); } template static schema::Type to_schema( std::map* _definitions, std::vector _types = {}) { using Type = schema::Type; constexpr size_t size = sizeof...(Ts); if constexpr (_i == size) { return Type {Type::Tuple {.types_ = _types}}; } else { using U = std::remove_cvref_t>>; _types.push_back( Parser::to_schema(_definitions)); return to_schema<_i + 1>(_definitions, std::move(_types)); } } private: template static void to_array(const W& _w, const std::tuple& _tup, const P& _parent) noexcept { if constexpr (_i < sizeof...(Ts)) { using NewFieldType = std::remove_cvref_t< typename std::tuple_element_t<_i, std::tuple>>; Parser::write( _w, std::get<_i>(_tup), _parent); to_array<_i + 1>(_w, _tup, _parent); } } }; } // namespace rfl::parsing #endif