1use proc_macro::TokenStream;
2use proc_macro2::TokenTree;
3use quote::quote;
4use syn::{parse_macro_input, ItemStruct, parse::Parse, Type};
5
6struct ExtendArgs {
7 target: Box<Type>,
8 field_name: TokenTree,
9}
10
11impl Parse for ExtendArgs {
12 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
13 let target = input.parse()?;
14 input.parse::<syn::Token![,]>()?;
15 let field_name = input.parse()?;
16 Ok(
17 Self {
18 target,
19 field_name,
20 }
21 )
22 }
23}
24
25#[proc_macro_attribute]
26pub fn extend(attr: TokenStream, mut item: TokenStream) -> TokenStream {
27 let item2 = item.clone();
28 let input = parse_macro_input!(item2 as ItemStruct);
29 let args = parse_macro_input!(attr as ExtendArgs);
30
31 let struct_name = input.ident;
32 let target = args.target;
33 let field_name = args.field_name;
34 item.extend::<TokenStream>(
35 quote! {
36 impl ::core::ops::Deref for #struct_name {
37 type Target = #target;
38
39 fn deref(&self) -> &Self::Target {
40 &self.#field_name
41 }
42 }
43
44 impl ::core::ops::DerefMut for #struct_name {
45 fn deref_mut(&mut self) -> &mut Self::Target {
46 &mut self.#field_name
47 }
48 }
49
50 impl #struct_name {
51 pub fn _super(&self) -> &#target {
52 <Self as ::core::ops::Deref>::deref(self)
53 }
54
55 pub fn _super_mut(&mut self) -> &mut #target {
56 <Self as ::core::ops::DerefMut>::deref_mut(self)
57 }
58 }
59 }.into()
60 );
61
62 item
63}