use proc_macro2::{Ident, TokenStream};
use quote::quote;
use syn::Result;
use syn::{DeriveInput, ImplGenerics, TypeGenerics, WhereClause};
pub struct DeriveInputContext<'a> {
pub input: &'a DeriveInput,
pub impl_generics: ImplGenerics<'a>,
pub ty_generics: TypeGenerics<'a>,
pub where_clause: Option<&'a WhereClause>,
pub trait_ty: Option<Ident>,
pub target_ty: Ident,
}
impl<'a> DeriveInputContext<'a> {
pub fn new(input: &'a DeriveInput, trait_ty: Option<Ident>, target_ty: Ident) -> Self {
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
Self {
input,
impl_generics,
ty_generics,
where_clause,
trait_ty,
target_ty,
}
}
pub fn impl_token(
self,
block_fn: impl Fn(&DeriveInputContext<'a>) -> Result<TokenStream>,
) -> TokenStream {
let impl_generics = &self.impl_generics;
let ty_generics = &self.ty_generics;
let where_clause = &self.where_clause;
let block = block_fn(&self).unwrap_or_else(|err| err.into_compile_error());
let target_ty = &self.target_ty;
match self.trait_ty {
Some(trait_ty) => {
quote! {
impl #impl_generics #trait_ty for #target_ty #ty_generics #where_clause {
#block
}
}
}
None => {
quote! {
impl #impl_generics #target_ty #ty_generics #where_clause {
#block
}
}
}
}
}
}