1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use proc_macro::TokenStream;
use quote::quote;
fn impl_expose(input_stream: TokenStream) -> syn::Result<proc_macro2::TokenStream> {
let item_impl = syn::parse::<syn::ItemImpl>(input_stream)?;
let mut implementations = Vec::new();
let self_ty = &item_impl.self_ty;
let trait_name = match item_impl.trait_ {
Some((_, ref path, _)) => path,
None => {
return Err(syn::Error::new(
item_impl.impl_token.span,
"Impl must be for a trait",
))
}
};
for item in item_impl.items.iter() {
implementations.push(match *item {
syn::ImplItem::Const(ref impl_const) => {
let name = &impl_const.ident;
let ty = &impl_const.ty;
quote! {
pub const #name: #ty = <#self_ty as #trait_name>::#name;
}
}
syn::ImplItem::Type(ref impl_type) => {
let name = &impl_type.ident;
quote! {
pub type #name = <#self_ty as #trait_name>::#name;
}
}
syn::ImplItem::Method(ref impl_method) => {
let signature = &impl_method.sig;
let name = &signature.ident;
quote! {
pub #signature {
#trait_name::#name(self)
}
}
}
_ => continue,
});
}
Ok(quote! {
#item_impl
impl #self_ty {
#(#implementations)*
}
})
}
#[proc_macro_attribute]
pub fn expose(_attr: TokenStream, input: TokenStream) -> TokenStream {
let stream = match impl_expose(input) {
Ok(tokens) => tokens,
Err(err) => err.into_compile_error(),
};
stream.into()
}