1use proc_macro::TokenStream;
2
3#[proc_macro_attribute]
4pub fn handler(_attr: TokenStream, tokens: TokenStream) -> TokenStream {
5 let mut components = Vec::new();
6 let mut next_function_name = false;
7 let mut filtered: Vec<proc_macro::TokenTree> = Vec::new();
8 for t in tokens {
9 match t {
10 proc_macro::TokenTree::Group(g) => {
11 if filtered.len() == 1 {
12 for group in g.stream() {
13 match group {
14 proc_macro::TokenTree::Ident(token) => match token.to_string().as_str() {
15 "Request" => components.push("req"),
16 "Response" => components.push("res"),
17 _ => {},
18 },
19 _ => {},
20 }
21 }
22 }
23 filtered.push(g.into());
24 },
25 proc_macro::TokenTree::Ident(i) => {
26 if next_function_name {
27 filtered.push(i.into());
28 next_function_name = false;
29 continue;
30 }
31 if i.to_string().eq("fn") {
32 next_function_name = true;
33 }
34 }
35 _ => {}
36 }
37 }
38
39 format!(r#"
40 #[allow(non_camel_case_types)]
41 struct {name};
42 #[allow(non_camel_case_types)]
43 impl ::core::fmt::Debug for {name} {{
44 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {{
45 ::core::fmt::Formatter::write_str(f, "{name}")
46 }}
47 }}
48 impl {name} {{
49 async fn {name}{args} {{
50 {body}
51 }}
52 }}
53 impl yadro::router::Handler for {name} {{
54 #[must_use = "handle future must be used"]
55 #[allow(clippy::type_complexity,clippy::type_repetition_in_bounds)]
56 fn handle<'life0,'life1,'life2,'async_trait>(
57 &'life0 self,req: &'life1 mut yadro::http::Request,res: &'life2 mut yadro::http::Response
58 ) -> ::core::pin::Pin<Box<dyn ::core::future::Future<Output = ()> + ::core::marker::Send+'async_trait> >
59 where 'life0:'async_trait,'life1:'async_trait,'life2:'async_trait,Self:'async_trait {{
60 Box::pin(async move {{
61 let __self = self;
62 let () = {{ Self::{name}({}).await }};
63 }})
64 }}
65 }}"#,
66 components.join(","),
67 name = &filtered[0],
68 args = &filtered[1],
69 body = &filtered[2],
70 ).parse().unwrap()
71}