#pragma once #include "fixed_string.hpp" #include #include #include #include #include namespace structive { struct Key_Category {}; struct Capability_Category {}; struct Unit_Category {}; struct Sensitive_Category {}; enum class Property_Capability { none, read, write, read_write }; template struct Key_Attribute { using attribute_category = Key_Category; static constexpr bool single_valued = true; static constexpr bool inheritable = false; static constexpr auto value = Value; }; template struct Property_Capability_Attribute { using attribute_category = Capability_Category; static constexpr bool single_valued = true; static constexpr bool inheritable = false; static constexpr auto value = Value; }; template struct Unit_Attribute { using attribute_category = Unit_Category; static constexpr bool single_valued = true; static constexpr bool inheritable = false; static constexpr auto value = Value; }; template struct Sensitive_Attribute { using attribute_category = Sensitive_Category; static constexpr bool single_valued = true; static constexpr bool inheritable = true; static constexpr auto value = Value; }; template struct Min_Constraint { using property_constraint_tag = void; static constexpr bool inheritable = false; static constexpr auto code = Fixed_String{"min_value"}; template constexpr bool validate(const T& candidate) const requires requires { candidate >= Value; } { return candidate >= Value; } }; template struct Max_Constraint { using property_constraint_tag = void; static constexpr bool inheritable = false; static constexpr auto code = Fixed_String{"max_value"}; template constexpr bool validate(const T& candidate) const requires requires { candidate <= Value; } { return candidate <= Value; } }; struct Finite_Constraint { using property_constraint_tag = void; static constexpr bool inheritable = false; static constexpr auto code = Fixed_String{"finite"}; template bool validate(T candidate) const { return std::isfinite(candidate); } }; template struct Custom_Constraint { using property_constraint_tag = void; static constexpr bool inheritable = false; static constexpr auto code = Code; [[no_unique_address]] Function function; template constexpr bool validate(const T& candidate) const requires std::predicate { return static_cast(function(candidate)); } }; template inline constexpr Key_Attribute key{}; template inline constexpr Property_Capability_Attribute capability{}; inline constexpr auto read_only = capability; inline constexpr auto write_only = capability; inline constexpr auto read_write = capability; inline constexpr auto inaccessible = capability; template inline constexpr Unit_Attribute unit{}; template inline constexpr Sensitive_Attribute sensitive{}; template inline constexpr Min_Constraint min_value{}; template inline constexpr Max_Constraint max_value{}; inline constexpr Finite_Constraint finite{}; template constexpr auto constraint(Function&& function) { return Custom_Constraint>{std::forward(function)}; } template concept Property_Attribute = requires { typename Attribute::attribute_category; { Attribute::single_valued } -> std::convertible_to; { Attribute::inheritable } -> std::convertible_to; }; template concept Property_Constraint = requires { typename Attribute::property_constraint_tag; { Attribute::code.view() } -> std::convertible_to; }; template concept Property_Metadata = Property_Attribute || Property_Constraint; template concept Property_Constraint_For = Property_Constraint && requires(const Attribute& attribute, const Value& value) { { attribute.validate(value) } -> std::convertible_to; }; template concept Inheritable_Attribute = requires { { Attribute::inheritable } -> std::convertible_to; } && Attribute::inheritable; }