use crate::model::{ModelBuilder, VTableBuilder};
use crate::ptr::OpaqueConst;
use crate::types::{PrimitiveType, Type, TypeBuilder, TypeKind};
use crate::{Model, Reflect, VTable};
macro_rules! primitive {
($( $t:ty : $v:ident ;)* ) => {
$(
unsafe impl Reflect for $t {
const MODEL: &'static Model<'static> =
&ModelBuilder::new::<$t>()
.ty(&Type::primitive::<$t>(PrimitiveType::$v))
.build();
const VTABLE: &'static VTable =
&VTableBuilder::<$t>::new()
.display()
.debug()
.build();
}
)*
};
}
primitive! {
bool: Bool;
char: Char;
u8: U8;
u16: U16;
u32: U32;
u64: U64;
u128: U128;
i8: I8;
i16: I16;
i32: I32;
i64: I64;
i128: I128;
f32: F32;
f64: F64;
}
unsafe impl Reflect for str {
const MODEL: &'static Model<'static> =
&ModelBuilder::new::<str>()
.ty(&const {
TypeBuilder::new_unsized::<str>()
.kind(TypeKind::Str)
.build()
})
.build();
const VTABLE: &'static VTable =
&VTableBuilder::<str>::new()
.display()
.debug()
.build();
}
unsafe impl<T: Reflect + 'static, const N: usize> Reflect for [T; N] {
const MODEL: &'static Model<'static> =
&ModelBuilder::new::<[T; N]>()
.ty(&Type::array::<T, N>())
.build();
const VTABLE: &'static VTable =
&VTableBuilder::<[T; N]>::new()
.debug_array::<T, N>()
.build();
}
unsafe impl<T: Reflect + 'static> Reflect for [T] {
const MODEL: &'static Model<'static> =
&ModelBuilder::new::<[T]>()
.ty(&Type::slice::<T>())
.build();
const VTABLE: &'static VTable =
&VTableBuilder::<[T]>::new()
.debug_slice::<T>()
.build();
}
unsafe impl<T: ?Sized + Reflect + 'static> Reflect for *const T {
const MODEL: &'static Model<'static> =
&ModelBuilder::new::<*const T>()
.ty(&Type::ptr::<T>())
.build();
const VTABLE: &'static VTable =
&VTableBuilder::<*const T>::new().build();
}
unsafe impl<T: ?Sized + Reflect + 'static> Reflect for *mut T {
const MODEL: &'static Model<'static> =
&ModelBuilder::new::<*mut T>()
.ty(&Type::ptr_mut::<T>())
.build();
const VTABLE: &'static VTable =
&VTableBuilder::<*mut T>::new().build();
}
unsafe impl<R: ?Sized + Reflect + 'static> Reflect for &R {
const MODEL: &'static Model<'static> =
&ModelBuilder::new::<&R>()
.ty(& Type::reference::<R>())
.build();
const VTABLE: &'static VTable = const {
let mut vtable = VTableBuilder::<&R>::new();
if R::VTABLE.debug.is_some() {
vtable.debug = Some(|slf, f| {
let slf = unsafe { slf.cast_ref::<&R>() };
let dbg = R::VTABLE.debug.unwrap();
let ptr = OpaqueConst::new(*slf);
unsafe { dbg(ptr, f) }
});
}
&vtable.build()
};
}