#ifndef RFL_VALIDATOR_HPP_ #define RFL_VALIDATOR_HPP_ #include #include #include #include #include #include #include #include "AllOf.hpp" #include "Result.hpp" #include "internal/HasValidation.hpp" #include "internal/StringLiteral.hpp" namespace rfl { template requires internal::HasValidation, T> struct Validator { public: using ReflectionType = T; using ValidationType = std::conditional_t>; /// Exception-free validation. static Result> from_value(const T& _value) noexcept { try { return Validator(_value); } catch (std::exception& e) { return Error(e.what()); } } Validator() : value_(ValidationType::validate(T()).value()) {} Validator(Validator&& _other) noexcept = default; Validator(const Validator& _other) = default; Validator(T&& _value) : value_(ValidationType::validate(_value).value()) {} Validator(const T& _value) : value_(ValidationType::validate(_value).value()) {} template < class U, typename std::enable_if, bool>::type = true> Validator(U&& _value) : value_(ValidationType::validate(T(std::forward(_value))).value()) { } template < class U, typename std::enable_if, bool>::type = true> Validator(const U& _value) : value_(ValidationType::validate(T(_value)).value()) {} ~Validator() = default; /// Assigns the underlying object. auto& operator=(const T& _value) { value_ = ValidationType::validate(_value).value(); return *this; } /// Assigns the underlying object. auto& operator=(T&& _value) { value_ = ValidationType::validate(std::forward(_value)).value(); return *this; } /// Assigns the underlying object. Validator& operator=(const Validator& _other ) = default; /// Assigns the underlying object. Validator& operator=(Validator&& _other ) noexcept = default; /// Assigns the underlying object. template < class U, typename std::enable_if, bool>::type = true> auto& operator=(U&& _value) noexcept { value_ = ValidationType::validate(T(std::forward(_value))).value(); return *this; } /// Assigns the underlying object. template < class U, typename std::enable_if, bool>::type = true> auto& operator=(const U& _value) { value_ = ValidationType::validate(T(_value)).value(); return *this; } /// Equality operator other Validators. bool operator==(const Validator& _other) const { return value() == _other.value(); } /// Exposes the underlying value. T& value() { return value_; } /// Exposes the underlying value. const T& value() const { return value_; } /// Necessary for the serialization to work. const T& reflection() const { return value_; } private: /// The underlying value. T value_; }; template inline auto operator<=>( const Validator& _v1, const Validator& _v2 ) { return _v1.value() <=> _v2.value(); } template inline auto operator<=>(const Validator& _v, const T& _t) { return _v.value() <=> _t; } } // namespace rfl namespace std { template struct hash> { size_t operator()(const rfl::Validator& _v) const { return hash()(_v.value()); } }; } // namespace std #endif