1use proc_macro::{self, Span, TokenStream};
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput, Ident};
4
5#[proc_macro_derive(Member)]
11pub fn derive_member(input: TokenStream) -> TokenStream {
12 let input = parse_macro_input!(input);
13 let DeriveInput {
14 vis,
15 ident,
16 generics,
17 ..
18 } = input;
19
20 let lifetimes = generics.lifetimes().count();
21 let (family_ident, generics_gat) = match lifetimes {
22 0 => (ident.clone(), quote! {}),
23 1 => (
24 Ident::new(&format!("{}F", ident), Span::call_site().into()),
25 quote! { <'a> },
26 ),
27 _ => panic!("derive macro only supports 0 or 1 lifetimes"),
28 };
29
30 let family_type = if family_ident != ident {
32 quote! {
33 #vis enum #family_ident {}
34 }
35 } else {
36 quote! {}
37 };
38
39 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
40 let output = quote! {
41 #family_type
42
43 impl #impl_generics family::Member<#family_ident> for #ident #ty_generics #where_clause {}
44
45 impl family::Family for #family_ident {
46 type Member<'a> = #ident #generics_gat;
47 }
48 };
49 output.into()
50}