use alloc::rc::Rc;
use super::*;
pub trait DerivableTypeAttribute: AttributeRegistration {
fn create<V>(context: &Rc<Context>, value: V) -> UnsafeIntrusiveEntityRef<Self>
where
<Self as AttributeRegistration>::Value: From<V>;
}
impl<A> DerivableTypeAttribute for A
where
A: AttributeRegistration + MaybeInferAttributeType,
{
fn create<V>(context: &Rc<Context>, value: V) -> UnsafeIntrusiveEntityRef<Self>
where
<A as AttributeRegistration>::Value: From<V>,
{
let value = <<A as AttributeRegistration>::Value>::from(value);
let ty = <A as MaybeInferAttributeType>::maybe_infer_type_from_value(&value);
A::create::<<A as AttributeRegistration>::Value>(
context,
value,
ty.unwrap_or(Type::Unknown),
)
}
}
pub trait InferAttributeValueType: AttributeValue {
fn infer_type() -> Type;
fn infer_type_from_value(&self) -> Type {
Self::infer_type()
}
}
pub trait InferAttributeType: AttributeRegistration {
fn infer_type() -> Type;
fn infer_type_from_value(value: &<Self as AttributeRegistration>::Value) -> Type;
}
impl<T: AttributeRegistration> InferAttributeType for T
where
<T as AttributeRegistration>::Value: InferAttributeValueType,
{
#[inline]
fn infer_type() -> Type {
<<Self as AttributeRegistration>::Value as InferAttributeValueType>::infer_type()
}
#[inline]
fn infer_type_from_value(value: &<Self as AttributeRegistration>::Value) -> Type {
<<Self as AttributeRegistration>::Value as InferAttributeValueType>::infer_type_from_value(
value,
)
}
}
pub trait MaybeInferAttributeType: AttributeRegistration {
fn maybe_infer_type() -> Option<Type>;
fn maybe_infer_type_from_value(value: &<Self as AttributeRegistration>::Value) -> Option<Type>;
}
impl<T, V> MaybeInferAttributeType for T
where
V: AttributeValue,
T: AttributeRegistration<Value = V>,
{
default fn maybe_infer_type() -> Option<Type> {
None
}
default fn maybe_infer_type_from_value(
_value: &<Self as AttributeRegistration>::Value,
) -> Option<Type> {
None
}
}
impl<T, V> MaybeInferAttributeType for T
where
V: AttributeValue,
T: AttributeRegistration<Value = V> + InferAttributeType,
{
fn maybe_infer_type() -> Option<Type> {
Some(<T as InferAttributeType>::infer_type())
}
fn maybe_infer_type_from_value(value: &<Self as AttributeRegistration>::Value) -> Option<Type> {
Some(<T as InferAttributeType>::infer_type_from_value(value))
}
}
macro_rules! value_infers_as {
($value_ty:ty, $ty:expr) => {
impl InferAttributeValueType for $value_ty {
#[inline(always)]
fn infer_type() -> Type {
$ty
}
}
};
}
value_infers_as!(bool, Type::I1);
value_infers_as!(i8, Type::I8);
value_infers_as!(u8, Type::U8);
value_infers_as!(i16, Type::I16);
value_infers_as!(u16, Type::U16);
value_infers_as!(i32, Type::I32);
value_infers_as!(u32, Type::U32);
value_infers_as!(i64, Type::I64);
value_infers_as!(u64, Type::U64);
value_infers_as!(i128, Type::I128);
value_infers_as!(u128, Type::U128);
value_infers_as!(f64, Type::F64);