#pragma once #include "adminive/adapter.hpp" #include #include #include #include #include namespace adminive { template requires std::totally_ordered && (Minimum <= Maximum) class Range_Value { public: using value_type = T; static constexpr T minimum = Minimum; static constexpr T maximum = Maximum; constexpr explicit Range_Value(const T& value) : value_(checked(value)) {} constexpr Range_Value(const Range_Value&) = default; constexpr Range_Value(Range_Value&&) noexcept(std::is_nothrow_move_constructible_v) = default; constexpr Range_Value& operator=(const Range_Value&) = default; constexpr Range_Value& operator=(Range_Value&&) noexcept(std::is_nothrow_move_assignable_v) = default; constexpr Range_Value& operator=(const T& value) { value_ = checked(value); return *this; } constexpr const T& value() const noexcept { return value_; } constexpr operator const T&() const noexcept { return value_; } private: static constexpr T checked(const T& value) { if (value < Minimum || value > Maximum) { throw std::out_of_range("value is outside the declared range"); } return value; } T value_; }; template requires std::default_initializable && std::invocable class Validated_Value { public: using value_type = T; using validator_type = Validator; constexpr explicit Validated_Value(const T& value) : value_(checked(value)) {} constexpr Validated_Value(const Validated_Value&) = default; constexpr Validated_Value(Validated_Value&&) noexcept(std::is_nothrow_move_constructible_v) = default; constexpr Validated_Value& operator=(const Validated_Value&) = default; constexpr Validated_Value& operator=(Validated_Value&&) noexcept(std::is_nothrow_move_assignable_v) = default; constexpr Validated_Value& operator=(const T& value) { value_ = checked(value); return *this; } constexpr const T& value() const noexcept { return value_; } constexpr operator const T&() const noexcept { return value_; } private: static constexpr T checked(const T& value) { Validator{}(value); return value; } T value_; }; template struct Is_Range_Value : std::false_type {}; template struct Is_Range_Value> : std::true_type {}; template concept Range_Value_Type = Is_Range_Value>::value; template struct Is_Validated_Value : std::false_type {}; template struct Is_Validated_Value> : std::true_type {}; template concept Validated_Value_Type = Is_Validated_Value>::value; template struct Unwrapped_Value { using type = std::remove_cvref_t; }; template struct Unwrapped_Value> : Unwrapped_Value {}; template struct Unwrapped_Value> : Unwrapped_Value {}; template using Unwrapped_Value_Type = typename Unwrapped_Value>::type; template struct Value_Adapter, Json> { using value_type = T; static constexpr T minimum = Minimum; static constexpr T maximum = Maximum; static const T& read(const Range_Value& value) noexcept { return value.value(); } static void write(Range_Value& target, T value) { target = value; } }; template struct Validator_Multiple_Of_Metadata {}; template struct Validator_Multiple_Of_Metadata> { static constexpr auto multiple_of = Validator::multiple_of; }; template struct Validator_Message_Metadata {}; template struct Validator_Message_Metadata> { static constexpr std::string_view validation_message = Validator::message; }; template struct Value_Adapter, Json> : Validator_Multiple_Of_Metadata, Validator_Message_Metadata { using value_type = T; static const T& read(const Validated_Value& value) noexcept { return value.value(); } static void write(Validated_Value& target, T value) { target = value; } }; }