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);