109 lines
1.8 KiB
Rust
109 lines
1.8 KiB
Rust
use proc_macro2::TokenStream;
|
|
use quote::quote;
|
|
use syn::{FnArg, ItemTrait, Pat};
|
|
|
|
pub fn impl_for_refs_core(
|
|
_attrs: TokenStream,
|
|
item: TokenStream,
|
|
) -> TokenStream {
|
|
let trt: ItemTrait = match syn::parse2(item.clone()) {
|
|
Ok(e) => e,
|
|
Err(e) => return e.into_compile_error(),
|
|
};
|
|
|
|
let trt_name = &trt.ident;
|
|
|
|
let fns = trt
|
|
.items
|
|
.iter()
|
|
.filter_map(|i| match i {
|
|
syn::TraitItem::Fn(f) => {
|
|
if f.default.is_some() {
|
|
return None;
|
|
}
|
|
|
|
let sig = &f.sig;
|
|
let fn_name = &f.sig.ident;
|
|
let args = sig.inputs.iter().map(|i| match i {
|
|
FnArg::Receiver(_s) => {
|
|
quote!((&**self))
|
|
},
|
|
FnArg::Typed(t) => match t.pat.as_ref() {
|
|
Pat::Ident(e) => quote!(#e),
|
|
_ => todo!(),
|
|
},
|
|
});
|
|
|
|
Some(quote! {
|
|
#sig {
|
|
#trt_name::#fn_name(#(#args),*)
|
|
}
|
|
})
|
|
},
|
|
_ => None,
|
|
})
|
|
.collect::<TokenStream>();
|
|
|
|
quote! {
|
|
#item
|
|
|
|
impl<'a, T> #trt_name for &'a T where T: ?Sized + #trt_name {
|
|
#fns
|
|
}
|
|
|
|
impl<'a, T> #trt_name for &'a mut T where T: ?Sized + #trt_name {
|
|
#fns
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use proc_macro2::TokenStream;
|
|
use quote::quote;
|
|
|
|
use crate::impl_for_refs_core;
|
|
|
|
fn expect_output(
|
|
attrs: TokenStream,
|
|
input: TokenStream,
|
|
output: TokenStream,
|
|
) {
|
|
assert_eq!(
|
|
impl_for_refs_core(attrs, input).to_string(),
|
|
output.to_string()
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn test_works() {
|
|
expect_output(
|
|
quote!(),
|
|
quote! {
|
|
#[impl_for_refs]
|
|
trait Test {
|
|
fn test(&self) -> usize;
|
|
}
|
|
},
|
|
quote! {
|
|
#[impl_for_refs]
|
|
trait Test {
|
|
fn test(&self) -> usize;
|
|
}
|
|
|
|
impl<'a, T> Test for &'a T where T: ?Sized + Test {
|
|
fn test(&self) -> usize {
|
|
Test::test((&**self))
|
|
}
|
|
}
|
|
|
|
impl<'a, T> Test for &'a mut T where T: ?Sized + Test {
|
|
fn test(&self) -> usize {
|
|
Test::test((&**self))
|
|
}
|
|
}
|
|
},
|
|
)
|
|
}
|
|
}
|