#pragma once #include "fixed_string.hpp" #include #include #include #include #include namespace structive { struct Key_Category {}; struct Access_Category {}; struct Persistence_Category {}; struct Unit_Category {}; struct Sensitive_Category {}; enum class External_Access { none, read, write, read_write }; enum class Persistence_Access { none, load, store, load_store }; 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 External_Access_Attribute { using attribute_category = Access_Category; static constexpr bool single_valued = true; static constexpr bool inheritable = true; static constexpr auto value = Value; }; template struct Persistence_Access_Attribute { using attribute_category = Persistence_Category; static constexpr bool single_valued = true; static constexpr bool inheritable = true; 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 External_Access_Attribute external_access{}; template inline constexpr Persistence_Access_Attribute persistence_access{}; 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_Constraint = requires { typename Attribute::property_constraint_tag; { Attribute::code.view() } -> std::convertible_to; }; 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; }