use crate::info::UnionField;
use crate::utils::StaticTypeMap;
use crate::{AssocConst, AssocFn, Error, Field, Type, Value, Variant};
use rebound_proc::impl_find;
use std::ptr::NonNull;
pub unsafe trait Reflected {
type Key: ?Sized + 'static;
fn name() -> String;
fn assoc_fns() -> &'static [AssocFn] {
static ASSOC_FNS: StaticTypeMap<Vec<AssocFn>> = StaticTypeMap::new();
ASSOC_FNS.call_once::<Self, _>(|| {
let mut sum = Vec::new();
impl_find!(assoc_fns);
sum
})
}
fn assoc_consts() -> &'static [AssocConst] {
static ASSOC_CONSTS: StaticTypeMap<Vec<AssocConst>> = StaticTypeMap::new();
ASSOC_CONSTS.call_once::<Self, _>(|| {
let mut sum = Vec::new();
impl_find!(assoc_consts);
sum
})
}
#[doc(hidden)]
unsafe fn init();
}
pub trait ReflectedTuple: Reflected {
fn fields() -> &'static [Field];
}
pub trait ReflectedSlice: Reflected {
fn element() -> Type;
}
pub trait ReflectedArray: Reflected {
fn element() -> Type;
fn length() -> usize;
}
pub trait ReflectedPointer: Reflected {
fn element() -> Type;
fn mutability() -> bool;
}
pub trait ReflectedReference: Reflected {
fn element() -> Type;
fn mutability() -> bool;
}
pub trait ReflectedFunction: Reflected {
fn args() -> Vec<Type>;
fn ret() -> Type;
}
pub trait ReflectedStruct: Reflected {
fn fields() -> Vec<Field>;
}
pub trait ReflectedTupleStruct: Reflected {
fn fields() -> Vec<Field>;
}
pub trait ReflectedUnitStruct: Reflected {}
pub trait ReflectedEnum: Reflected {
fn variants() -> Vec<Variant>;
}
pub trait ReflectedUnion: Reflected {
fn fields() -> Vec<UnionField>;
}
pub trait ReflectedImpl<const N: u8>: Reflected {
fn assoc_fns() -> Vec<AssocFn>;
fn assoc_consts() -> Vec<AssocConst>;
}
impl<T: ?Sized + Reflected, const N: u8> ReflectedImpl<N> for T {
default fn assoc_fns() -> Vec<AssocFn> {
vec![]
}
default fn assoc_consts() -> Vec<AssocConst> {
vec![]
}
}
pub(crate) trait Ref: Reflected {
fn ref_val<'a>(val: &'a Value<'_>) -> Result<Value<'a>, Error>;
fn mut_val<'a>(val: &'a mut Value<'_>) -> Result<Value<'a>, Error>;
}
impl<T: ?Sized + Reflected> Ref for T {
default fn ref_val<'a>(val: &'a Value<'_>) -> Result<Value<'a>, Error> {
let val = unsafe { Value::from(val.borrow_unsafe::<Self>()) };
unsafe { Ok(core::mem::transmute::<Value<'_>, Value<'_>>(val)) }
}
default fn mut_val<'a>(val: &'a mut Value<'_>) -> Result<Value<'a>, Error> {
let val = unsafe { Value::from(val.borrow_unsafe_mut::<Self>()) };
unsafe { Ok(core::mem::transmute::<Value<'_>, Value<'_>>(val)) }
}
}
impl<T: ?Sized + Reflected> Ref for &T {
fn ref_val<'a>(val: &'a Value<'_>) -> Result<Value<'a>, Error> {
let new_ref = unsafe { NonNull::<&T>::from_raw_parts(val.raw_ptr(), ()).as_ref() };
let val = Value::from(*new_ref);
unsafe { Ok(core::mem::transmute::<Value<'_>, Value<'_>>(val)) }
}
fn mut_val<'a>(_: &'a mut Value<'_>) -> Result<Value<'a>, Error> {
Err(Error::CantReborrow)
}
}
impl<T: ?Sized + Reflected> Ref for &mut T {
fn ref_val<'a>(_: &'a Value<'_>) -> Result<Value<'a>, Error> {
Err(Error::CantReborrow)
}
fn mut_val<'a>(_: &'a mut Value<'_>) -> Result<Value<'a>, Error> {
Err(Error::CantReborrow)
}
}