#ifndef RFL_PARSING_PARSER_DURATION_HPP_ #define RFL_PARSING_PARSER_DURATION_HPP_ #include #include #include #include "../Literal.hpp" #include "../Variant.hpp" #include "../always_false.hpp" #include "Parent.hpp" #include "Parser_base.hpp" #include "schema/Type.hpp" namespace rfl ::parsing { template requires AreReaderAndWriter> struct Parser, ProcessorsType> { public: using InputVarType = typename R::InputVarType; using ParentType = Parent; using DurationType = std::chrono::duration; using Unit = Literal<"nanoseconds", "microseconds", "milliseconds", "seconds", "minutes", "hours", "days", "weeks", "months", "years">; using SupportedTypes = Variant; struct RType { int64_t count; Unit unit; }; static Result read(const R& _r, const InputVarType& _var) noexcept { return Parser::read(_r, _var) .and_then(to_duration) .transform([](auto&& _duration) { return _duration.visit([](auto&& _d) -> DurationType { return std::chrono::duration_cast(std::move(_d)); }); }); } template static void write(const W& _w, const DurationType& _d, const P& _parent) { const auto r = RType{.count = static_cast(_d.count()), .unit = make_unit()}; return Parser::write(_w, r, _parent); } static schema::Type to_schema( std::map* _definitions) { return Parser::to_schema(_definitions); } private: static Result to_duration(const RType& _r) { switch (_r.unit.value()) { case Unit::value_of<"nanoseconds">(): return SupportedTypes(std::chrono::nanoseconds(_r.count)); case Unit::value_of<"microseconds">(): return SupportedTypes(std::chrono::microseconds(_r.count)); case Unit::value_of<"milliseconds">(): return SupportedTypes(std::chrono::milliseconds(_r.count)); case Unit::value_of<"seconds">(): return SupportedTypes(std::chrono::seconds(_r.count)); case Unit::value_of<"minutes">(): return SupportedTypes(std::chrono::minutes(_r.count)); case Unit::value_of<"hours">(): return SupportedTypes(std::chrono::hours(_r.count)); case Unit::value_of<"days">(): return SupportedTypes(std::chrono::days(_r.count)); case Unit::value_of<"weeks">(): return SupportedTypes(std::chrono::weeks(_r.count)); case Unit::value_of<"months">(): return SupportedTypes(std::chrono::months(_r.count)); case Unit::value_of<"years">(): return SupportedTypes(std::chrono::years(_r.count)); default: return error("Unsupported unit."); } } static auto make_unit() noexcept { if constexpr (std::is_same_v) { return Unit::make<"nanoseconds">(); } else if constexpr (std::is_same_v) { return Unit::make<"microseconds">(); } else if constexpr (std::is_same_v) { return Unit::make<"milliseconds">(); } else if constexpr (std::is_same_v) { return Unit::make<"seconds">(); } else if constexpr (std::is_same_v) { return Unit::make<"minutes">(); } else if constexpr (std::is_same_v) { return Unit::make<"hours">(); } else if constexpr (std::is_same_v) { return Unit::make<"days">(); } else if constexpr (std::is_same_v) { return Unit::make<"weeks">(); } else if constexpr (std::is_same_v) { return Unit::make<"months">(); } else if constexpr (std::is_same_v) { return Unit::make<"years">(); } else { static_assert(always_false_v, "Unsupported type."); } }; }; } // namespace rfl::parsing #endif