use proc_macro2::TokenStream;
use quote::quote;
pub(crate) fn pat_is_forwardable(pat: &syn::Pat) -> bool {
match pat {
syn::Pat::Ident(pi) => pi.by_ref.is_none() && pi.subpat.is_none(),
syn::Pat::Tuple(t) => t.elems.iter().all(pat_is_forwardable),
syn::Pat::Slice(s) => s.elems.iter().all(pat_is_forwardable),
syn::Pat::Paren(p) => pat_is_forwardable(&p.pat),
syn::Pat::Reference(r) => pat_is_forwardable(&r.pat),
syn::Pat::Struct(s) => {
s.rest.is_none() && s.fields.iter().all(|f| pat_is_forwardable(&f.pat))
}
syn::Pat::TupleStruct(ts) => ts.elems.iter().all(pat_is_forwardable),
syn::Pat::Type(_) => false,
syn::Pat::Wild(_) => false,
syn::Pat::Or(_) => false,
syn::Pat::Range(_) => false,
syn::Pat::Lit(_) => false,
syn::Pat::Const(_) => false,
syn::Pat::Path(_) => false,
syn::Pat::Macro(_) => false,
syn::Pat::Rest(_) => false,
syn::Pat::Verbatim(_) => false,
syn::Pat::Guard(_) => false,
_ => false,
}
}
pub(crate) fn collect_call_args(
sig: &syn::Signature,
) -> Result<Vec<TokenStream>, String> {
let mut args = vec![];
for arg in &sig.inputs {
match arg {
syn::FnArg::Receiver(_) => {}
syn::FnArg::Typed(pat_type) => {
let pat = &*pat_type.pat;
match pat {
syn::Pat::Ident(pi) => {
let id = &pi.ident;
args.push(quote!(#id));
}
syn::Pat::Wild(_) => {
return Err(quote!(#pat_type).to_string());
}
_ => {
args.push(quote!(#pat));
}
}
}
}
}
Ok(args)
}