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
extern crate proc_macro;
extern crate quote;
extern crate syn;
use core::convert::AsRef;
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::parse_macro_input;
use syn::AttributeArgs;
use syn::ItemFn;
#[proc_macro_attribute]
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
let args = parse_macro_input!(attr as AttributeArgs);
let mut path = None;
let mut reqtype = None;
for arg in args {
match arg {
syn::NestedMeta::Lit(syn::Lit::Str(ref fname)) => {
let fname = quote!(#fname).to_string();
path = Some(fname.as_str()[1..fname.len() - 1].to_owned());
}
syn::NestedMeta::Meta(syn::Meta::Path(ident)) => {
let identstr = quote!(#ident).to_string();
reqtype = Some(identstr);
}
_ => {
println!("error");
}
}
}
let psitem = parse_macro_input!(item as ItemFn);
let name = psitem.sig.ident.clone();
let classname = syn::Ident::new(&format!("{}{}", "class_", name), psitem.sig.ident.span());
let rtypestr = reqtype.expect("error");
let callprefix = format_ident!("web");
#[allow(unused_assignments)]
let mut method = None;
match rtypestr.as_ref() {
"GET" => method = Some(format_ident!("get")),
"POST" => method = Some(format_ident!("post")),
"PUT" => method = Some(format_ident!("put")),
"PATCH" => method = Some(format_ident!("patch")),
"DELETE" => method = Some(format_ident!("delete")),
"HEAD" => method = Some(format_ident!("head")),
_ => method = Some(format_ident!("")),
}
let func = quote! {
#[allow(non_camel_case_types)]
pub struct #classname;
#psitem
inventory::submit!(Box::new(#classname) as Box<dyn ServiceFactory>);
impl ServiceFactory for #classname {
fn register(&self, config: &mut web::ServiceConfig) {
config.route(#path, #callprefix::#method().to(#name));
}
}
};
func.into()
}