awf_codegen/
lib.rs

1extern crate proc_macro;
2extern crate proc_macro2;
3extern crate quote;
4extern crate syn;
5
6use core::convert::AsRef;
7use proc_macro::TokenStream;
8
9use proc_macro2::Span;
10use quote::{format_ident, quote};
11use syn::parse_macro_input;
12use syn::AttributeArgs;
13use syn::ItemFn;
14use syn::{ImplItem, ItemImpl};
15/// Creates route handler with `GET` method guard.
16///
17/// Syntax: `#[route(GET,"/")]`
18///
19#[proc_macro_attribute]
20pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
21    let args = parse_macro_input!(attr as AttributeArgs);
22    let mut path = None;
23    let mut reqtype = None;
24    for arg in args {
25        match arg {
26            syn::NestedMeta::Lit(syn::Lit::Str(ref fname)) => {
27                let fname = quote!(#fname).to_string();
28                path = Some(fname.as_str()[1..fname.len() - 1].to_owned());
29            }
30            syn::NestedMeta::Meta(syn::Meta::Path(ident)) => {
31                let identstr = quote!(#ident).to_string();
32                reqtype = Some(identstr);
33            }
34            _ => {
35                println!("error");
36            }
37        }
38    }
39    let psitem = parse_macro_input!(item as ItemFn);
40    let name = psitem.sig.ident.clone();
41    let classname = syn::Ident::new(&format!("{}{}", "class_", name), psitem.sig.ident.span());
42    let rtypestr = reqtype.expect("error");
43    let callprefix = format_ident!("web");
44    #[allow(unused_assignments)]
45    let mut method = None;
46    match rtypestr.as_ref() {
47        "GET" => method = Some(format_ident!("get")),
48        "POST" => method = Some(format_ident!("post")),
49        "PUT" => method = Some(format_ident!("put")),
50        "PATCH" => method = Some(format_ident!("patch")),
51        "DELETE" => method = Some(format_ident!("delete")),
52        "HEAD" => method = Some(format_ident!("head")),
53        _ => method = Some(format_ident!("")),
54    }
55    let func = quote! {
56        #[allow(non_camel_case_types)]
57        pub struct #classname;
58        #psitem
59        inventory::submit!(Box::new(#classname) as Box<dyn ServiceFactory>);
60        impl ServiceFactory for #classname {
61        fn register(&self, config: &mut web::ServiceConfig) {
62            config.route(#path, #callprefix::#method().to(#name));
63        }
64    }
65        };
66    func.into()
67}
68/// Creates route handler with `PATH` impl Resource.
69///
70/// Syntax: `#[route_res("/")]`
71///
72/// ```
73/// #[route_res("/Hello")]
74/// impl Hello {
75///     fn get(that:Option<Hello>, req: HttpRequest) -> String {
76///         format!("get Hello !")
77///     }
78///     fn post(that:Option<Hello>, req: HttpRequest) -> String {
79///         format!("post Hello !")
80///     }
81/// }
82/// ```
83#[proc_macro_attribute]
84pub fn route_res(attr: TokenStream, item: TokenStream) -> TokenStream {
85    //item
86    let mut itimpl = parse_macro_input!(item as ItemImpl);
87    let args = parse_macro_input!(attr as AttributeArgs);
88    let mut path = None;
89    let mut reqtype = None;
90    for arg in args {
91        match arg {
92            syn::NestedMeta::Lit(syn::Lit::Str(ref fname)) => {
93                let fname = quote!(#fname).to_string();
94                path = Some(fname.as_str()[1..fname.len() - 1].to_owned());
95            }
96            syn::NestedMeta::Meta(syn::Meta::Path(ident)) => {
97                let identstr = quote!(#ident).to_string();
98                reqtype = Some(identstr);
99            }
100            _ => {
101                println!("error");
102            }
103        }
104    }
105    let self_ty = &itimpl.self_ty;
106    let mut nameident = quote! {#self_ty};
107    //println!("ident {:?}", nameident.to_string());
108    let classname = syn::Ident::new(&format!("{}{}", "class_", nameident), Span::call_site());
109    //println!("classname ident {:?}", classname.to_string());
110    let callprefix = format_ident!("web");
111    let method = format_ident!("get");
112    let mut methods = vec![];
113    for arg in itimpl.items.iter() {
114        //println!("{:?}", arg);
115        match arg {
116            ImplItem::Method(m) => {
117                //println!("{:?}", m.sig.ident.to_string());
118                methods.push(m.sig.ident.to_string())
119            }
120            ImplItem::Type(t) => {
121                println!("ImplItem::Type {:?}", t.ident.to_string());
122            }
123            ImplItem::Const(t) => {
124                println!("ImplItem::Type {:?}", t.ident.to_string());
125            }
126            _ => {}
127        }
128    }
129    //println!("impl:{:?}", methods);
130    let mut methodscode = vec![];
131    for method in methods{
132        let methodident = format_ident!("{}",method.to_string());
133        let regcode = quote!{
134            config.route(#path, #callprefix::#methodident().to(#nameident::#methodident));
135        };
136        methodscode.push(regcode);
137    }
138
139    let mut func = quote! {
140        pub struct #classname;
141        /*impl FromRequest for #nameident {
142            type Error = Error;
143            type Future = Result<Self, Self::Error>;
144            type Config = ();
145            fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
146                return Ok(#nameident {
147                });
148            }
149        }*/
150        #itimpl
151        inventory::submit!(Box::new(#classname) as Box<dyn ServiceFactory>);
152        //inventory::submit!(Box::new(#classname) as Box<dyn ServiceFactory>);
153        impl ServiceFactory for #classname {
154            fn register(&self, config: &mut web::ServiceConfig) {
155                #(#methodscode)*
156                //mapRes.insert(stringify!(#nameident),Arc::new(#nameident::new(stringify!(#nameident).to_string())));
157            }
158        }
159    };
160    //println!("gen:{}", func.to_string());
161    func.into()
162}