53 lines
1.5 KiB
Rust
53 lines
1.5 KiB
Rust
|
use proc_macro::TokenStream;
|
||
|
use syn::{spanned::Spanned, Data, Fields};
|
||
|
|
||
|
#[proc_macro_derive(Extract)]
|
||
|
pub fn extract(input: TokenStream) -> TokenStream {
|
||
|
let ast = syn::parse_macro_input!(input);
|
||
|
|
||
|
impl_extract(&ast)
|
||
|
}
|
||
|
|
||
|
fn impl_extract(ast: &syn::DeriveInput) -> TokenStream {
|
||
|
let name = &ast.ident;
|
||
|
|
||
|
match &ast.data {
|
||
|
Data::Struct(st) => match &st.fields {
|
||
|
Fields::Named(fields) => {
|
||
|
let extracted = fields.named.iter().map(|field| {
|
||
|
let ident = &field.ident;
|
||
|
let ty = &field.ty;
|
||
|
|
||
|
quote::quote_spanned! {field.span()=>
|
||
|
#ident : crate::utils::extract_arg!(ctx, #ident, #ty)
|
||
|
}
|
||
|
});
|
||
|
|
||
|
TokenStream::from(quote::quote! {
|
||
|
impl Extract for #name {
|
||
|
fn extract(ctx: crate::ApplicationContext) -> Self {
|
||
|
Self {
|
||
|
#(#extracted,)*
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
Fields::Unit => TokenStream::from(quote::quote! {
|
||
|
impl Extract for #name {
|
||
|
fn extract(ctx: crate::ApplicationContext) -> Self {
|
||
|
Self {}
|
||
|
}
|
||
|
}
|
||
|
}),
|
||
|
_ => {
|
||
|
panic!("Only named/unit structs can derive Extract");
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_ => {
|
||
|
panic!("Only structs can derive Extract");
|
||
|
}
|
||
|
}
|
||
|
}
|