Files
Structive/core/include/structive/property/attributes.hpp
T
2026-08-07 17:50:04 +08:00

122 lines
4.3 KiB
C++

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