alchemist-macros 0.0.0

Hot-reload game engine & editor (WIP—MVP coming)
Documentation
use super::*;
use quote::*;
use syn::*;

pub fn derive_manifest(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let core_path = utils::core_path_attr(&input.attrs);

    let ident = input.ident.clone();

    let implementation = quote! {
        impl #core_path::manifest::Manifest for #ident {}

        #core_path::inventory::submit! {
            #core_path::manifest::ManifestRegistration {
                type_id_fn: || ::std::any::TypeId::of::<#ident>(),
                qualifier_fn: || {
                    use #core_path::manifest::Qualify;
                    #ident::qualifier()
                },
                default_fn: || {
                    use ::std::default::Default;
                    Box::new(#ident::default())
                },
                encode_fn: |v, encoder| {
                    let force_downcasted: &#ident = unsafe {
                        let (data, _vtable): (*const (), *const ()) = ::std::mem::transmute(v);
                        ::std::mem::transmute(data)
                    };
                    encoder.delegate_encoding(force_downcasted)
                },
                decode_fn: |v, decoder| -> Result<(), Box<dyn ::std::error::Error>> {
                    let force_downcasted: &mut #ident = unsafe {
                        let (data, _vtable): (*const (), *const ()) = ::std::mem::transmute(v);
                        ::std::mem::transmute(data)
                    };
                    decoder.delegate_decoding(force_downcasted)?;
                    Ok(())
                },
                encompass_fn: |v, visitor| {
                    let force_downcasted: &#ident = unsafe {
                        let (data, _vtable): (*const (), *const ()) = ::std::mem::transmute(v);
                        ::std::mem::transmute(data)
                    };
                    use #core_path::encompass::Encompass;
                    force_downcasted.encompass(visitor)
                },
                inspect_fn: |v, ui_context, ui| {
                    let force_downcasted: &mut #ident = unsafe {
                        let (data, _vtable): (*const (), *const ()) = ::std::mem::transmute(v);
                        ::std::mem::transmute(data)
                    };
                    use #core_path::inspect::Inspect;
                    force_downcasted.inspect(ui_context, ui);
                },
                debug_fn: |v, formatter| {
                    let force_downcasted: &#ident = unsafe {
                        let (data, _vtable): (*const (), *const ()) = ::std::mem::transmute(v);
                        ::std::mem::transmute(data)
                    };
                    use ::std::fmt::Debug;
                    force_downcasted.fmt(formatter)
                },
            }
        }
    };

    implementation.into()
}