procmeta_core/
derive_input_context.rs

1use proc_macro2::{Ident, TokenStream};
2use quote::quote;
3use syn::Result;
4use syn::{DeriveInput, ImplGenerics, TypeGenerics, WhereClause};
5
6pub struct DeriveInputContext<'a> {
7    pub input: &'a DeriveInput,
8    pub impl_generics: ImplGenerics<'a>,
9    pub ty_generics: TypeGenerics<'a>,
10    pub where_clause: Option<&'a WhereClause>,
11    pub trait_ty: Option<Ident>,
12    pub target_ty: Ident,
13}
14
15impl<'a> DeriveInputContext<'a> {
16    pub fn new(input: &'a DeriveInput, trait_ty: Option<Ident>, target_ty: Ident) -> Self {
17        let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
18        Self {
19            input,
20            impl_generics,
21            ty_generics,
22            where_clause,
23            trait_ty,
24            target_ty,
25        }
26    }
27
28    pub fn impl_token(
29        self,
30        block_fn: impl Fn(&DeriveInputContext<'a>) -> Result<TokenStream>,
31    ) -> TokenStream {
32        let impl_generics = &self.impl_generics;
33        let ty_generics = &self.ty_generics;
34        let where_clause = &self.where_clause;
35        let block = block_fn(&self).unwrap_or_else(|err| err.into_compile_error());
36        let target_ty = &self.target_ty;
37        match self.trait_ty {
38            Some(trait_ty) => {
39                quote! {
40                    impl #impl_generics #trait_ty for #target_ty #ty_generics #where_clause {
41                        #block
42                    }
43                }
44            }
45            None => {
46                quote! {
47                    impl #impl_generics #target_ty #ty_generics #where_clause {
48                        #block
49                    }
50                }
51            }
52        }
53    }
54}