byte_slab_derive/
lib.rs

1use synstructure::{quote, BindStyle};
2use proc_macro2::{TokenStream, Ident, Span};
3use quote::ToTokens;
4use syn::GenericParam;
5
6fn reroot_derive(mut s: synstructure::Structure) -> proc_macro2::TokenStream {
7    s.bind_with(|_| {
8        BindStyle::Move
9    });
10
11    let mut ret_val = TokenStream::new();
12
13    let mut sname = s.ast().clone();
14    sname.generics.lifetimes_mut().for_each(|lt| {
15        lt.lifetime.ident = Ident::new("static", Span::call_site());
16    });
17
18    let ident = sname.ident;
19    let gens = sname.generics;
20
21    let mut gen_fixed = TokenStream::new();
22
23    for gen in gens.params.iter() {
24        match gen {
25            GenericParam::Type(tp) => quote! { #tp, },
26            GenericParam::Lifetime(ltd) => quote! { #ltd, },
27            GenericParam::Const(cp) => {
28                let ident = &cp.ident;
29                quote! { #ident, }
30            }
31        }.to_tokens(&mut gen_fixed);
32    }
33
34    quote!{
35        #ident < #gen_fixed >
36    }.to_tokens(&mut ret_val);
37
38    let mut body = TokenStream::new();
39
40    for var in s.variants().iter() {
41        let pat = var.pat();
42        let cons = var.construct(|_field, i| {
43            let binding = var.bindings().iter().nth(i).unwrap();
44            quote!{
45                #binding.reroot(key)?
46            }
47        });
48
49        quote! {
50            #pat => Ok(#cons),
51        }.to_tokens(&mut body);
52    }
53
54    s.gen_impl(quote! {
55        extern crate byte_slab;
56
57        gen impl byte_slab::Reroot for @Self {
58            type Retval = #ret_val;
59            #[inline]
60            fn reroot(self, key: &byte_slab::RerooterKey) -> Result<Self::Retval, ()> {
61                match self {
62                    #body
63                }
64            }
65        }
66    })
67}
68
69synstructure::decl_derive!([Reroot] => reroot_derive);