flect 0.1.1

Rust reflection [WIP]
Documentation
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()
    };
}