diff --git a/src/macros/implement.rs b/src/macros/implement.rs index b5c8d787..b798bae5 100644 --- a/src/macros/implement.rs +++ b/src/macros/implement.rs @@ -1,26 +1,32 @@ -use proc_macro::TokenStream; +use proc_macro::{Span, TokenStream}; use quote::quote; -use syn::{ItemFn, Meta, MetaList}; +use syn::{Error, ItemFn, Meta, Path}; +use utils::get_named_generics; -use crate::Result; +use crate::{utils, Result}; pub(super) fn implement(item: ItemFn, args: &[Meta]) -> Result { - let Meta::List(MetaList { - path, - .. - }) = &args - .first() - .expect("missing path to trait or item to implement") - else { - panic!("invalid path to item for implement"); - }; - + let generics = get_named_generics(args, "generics")?; + let receiver = get_receiver(args)?; + let params = get_named_generics(args, "params")?; let input = item; let out = quote! { - impl #path { + impl #generics #receiver #params { #input } }; Ok(out.into()) } + +fn get_receiver(args: &[Meta]) -> Result { + let receiver = &args + .first() + .ok_or_else(|| Error::new(Span::call_site().into(), "Missing required argument to receiver"))?; + + let Meta::Path(receiver) = receiver else { + return Err(Error::new(Span::call_site().into(), "First argument is not path to receiver")); + }; + + Ok(receiver.clone()) +} diff --git a/src/macros/utils.rs b/src/macros/utils.rs index 7ae55d39..58074e3a 100644 --- a/src/macros/utils.rs +++ b/src/macros/utils.rs @@ -1,4 +1,12 @@ -use syn::{Expr, Lit, Meta}; +use syn::{parse_str, Expr, Generics, Lit, Meta}; + +use crate::Result; + +pub(crate) fn get_named_generics(args: &[Meta], name: &str) -> Result { + const DEFAULT: &str = "<>"; + + parse_str::(&get_named_string(args, name).unwrap_or_else(|| DEFAULT.to_owned())) +} pub(crate) fn get_named_string(args: &[Meta], name: &str) -> Option { args.iter().find_map(|arg| {