use std::alloc::Layout; use std::any::TypeId; pub use engine_macros::Reflection; pub trait With: 'static { const REFLECTION: &Reflection; fn reflection() -> &'static Reflection where Self: Sized; fn get_reflection(&self) -> &'static Reflection; } #[derive(Debug, Clone)] #[non_exhaustive] pub enum Reflection { Struct(Struct), Array(Array), Slice(Slice), Literal, } #[derive(Debug, Clone)] pub struct Struct { pub fields: &'static [StructField], } #[derive(Debug, Clone)] pub struct StructField { pub name: &'static str, pub index: usize, pub layout: Layout, pub byte_offset: usize, pub type_id: TypeId, pub type_name: &'static str, pub reflection: &'static Reflection, } #[derive(Debug, Clone)] pub struct Array { pub item_reflection: &'static Reflection, pub length: usize, } #[derive(Debug, Clone)] pub struct Slice { pub item_reflection: &'static Reflection, } macro_rules! impl_with_for_literals { ($($literal: ty),*) => { $( impl With for $literal { const REFLECTION: &Reflection = &Reflection::Literal; fn reflection() -> &'static Reflection where Self: Sized { Self::REFLECTION } fn get_reflection(&self) -> &'static Reflection { Self::reflection() } } )* }; } impl_with_for_literals!( u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64, usize, isize, &'static str ); impl With for [T; LEN] { const REFLECTION: &Reflection = &Reflection::Array(Array { item_reflection: T::REFLECTION, length: LEN, }); fn reflection() -> &'static Reflection where Self: Sized, { Self::REFLECTION } fn get_reflection(&self) -> &'static Reflection { Self::reflection() } } impl With for &'static [T] { const REFLECTION: &Reflection = &Reflection::Slice(Slice { item_reflection: T::REFLECTION }); fn reflection() -> &'static Reflection where Self: Sized, { Self::REFLECTION } fn get_reflection(&self) -> &'static Reflection { Self::reflection() } } // Used by the Reflection derive macro #[doc(hidden)] pub mod __private { pub const fn get_type_reflection() -> &'static super::Reflection where T: super::With, { T::REFLECTION } }