zonbi_macros/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro2::Span;
3use quote::quote;
4use syn::{ConstParam, GenericParam, Lifetime, LifetimeParam, TypeParam};
5
6#[proc_macro_derive(Zonbi)]
7pub fn derive_zonbi(input: TokenStream) -> TokenStream {
8    let ast = syn::parse_macro_input!(input as syn::DeriveInput);
9
10    let name = &ast.ident;
11    let generics = ast.generics;
12
13    let zonbi_life = Lifetime::new("'__zonbi_life", Span::call_site());
14
15    let mut zonbi_lifetimes = quote!();
16    for ig in &generics.params {
17        match ig {
18            GenericParam::Lifetime(_) => {
19                zonbi_lifetimes = quote! {
20                    #zonbi_lifetimes
21                    #zonbi_life // here we inject the zonbi lifetime
22                    ,
23                };
24            }
25            GenericParam::Const(ConstParam { ident, .. }) => {
26                zonbi_lifetimes = quote! {
27                    #zonbi_lifetimes
28                    #ident
29                    ,
30                };
31            }
32            GenericParam::Type(TypeParam { ident, .. }) => {
33                zonbi_lifetimes = quote! {
34                    #zonbi_lifetimes
35                    #ident
36                    ,
37                };
38            }
39        }
40    }
41
42    let mut generics2 = generics.clone();
43    let (_, ty_generics, _) = generics.split_for_impl();
44
45    let life_param = LifetimeParam::new(zonbi_life.clone());
46    generics2.params.push(GenericParam::Lifetime(life_param));
47
48    let (impl_generics, _, where_clause) = generics2.split_for_impl();
49    let other_clauses = where_clause.map(|w| &w.predicates);
50
51    quote! {
52        unsafe impl #impl_generics ::zonbi::Zonbi<#zonbi_life> for #name #ty_generics
53        where
54            Self: #zonbi_life,
55            #other_clauses
56        {
57            type Casted = #name<#zonbi_lifetimes>;
58
59            fn zonbi_id() -> ::zonbi::ZonbiId {
60                ::zonbi::ZonbiId::from(core::any::TypeId::of::<#name<'static>>())
61            }
62
63            unsafe fn zonbify(self) -> Self::Casted {
64                ::core::mem::transmute(self)
65            }
66
67            unsafe fn zonbify_ref(&self) -> &Self::Casted {
68                ::core::mem::transmute(self)
69            }
70
71            unsafe fn zonbify_mut(&mut self) -> &mut Self::Casted {
72                ::core::mem::transmute(self)
73            }
74        }
75    }
76    .into()
77}