use proc_macro::TokenStream; use syn::{spanned::Spanned, Data}; /// Macro to allow Recordable to be implemented on an enum by dispatching over each variant. #[proc_macro_derive(Recordable)] pub fn extract(input: TokenStream) -> TokenStream { let ast = syn::parse_macro_input!(input); impl_recordable(&ast) } fn impl_recordable(ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; match &ast.data { Data::Enum(en) => { let extracted = en.variants.iter().map(|var| { let ident = &var.ident; quote::quote_spanned! {var.span()=> Self::#ident (opt) => opt.run(ctx).await? } }); TokenStream::from(quote::quote! { impl Recordable for #name { async fn run(self, ctx: crate::Context<'_>) -> Result<(), crate::Error> { match self { #(#extracted,)* } Ok(()) } } }) } _ => { panic!("Only enums can derive Recordable"); } } }