minihttp_codegen/
lib.rs

1use std::ops::Deref;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::parse_macro_input;
6
7#[proc_macro_attribute]
8pub fn get(attr: TokenStream, item: TokenStream) -> TokenStream {
9    eprintln!("{:#?}\n{:#?}", attr, item);
10    let args = parse_macro_input!(attr as syn::AttributeArgs);
11    let item: syn::ItemFn = syn::parse(item).unwrap();
12
13    let name = item.sig.ident.clone();
14    let body = item.block.deref();
15    let path = args[0].clone();
16
17    let output = quote! {
18        fn #name() -> Box<Route> {
19
20            #[allow(non_camel_case_types)]
21
22            #[derive(Clone)]
23            struct route {
24                path: &'static str,
25                method: Method,
26            }
27
28            impl route {
29                fn new() -> Self {
30                    route {
31                        path: #path.into(),
32                        method: Method::GET,
33                    }
34                }
35            }
36
37            impl Default for route {
38                fn default() -> route {
39                    route {
40                        path: #path.into(),
41                        method: Method::GET,
42                    }
43                }
44            }
45
46            impl Route for route {
47                fn get_path(&self) -> &str {
48                    self.path
49                }
50                fn get_method(&self) -> Method {
51                    self.method
52                }
53                fn get_body(&self) -> Vec<u8> {
54                    #body.into()
55                }
56                fn post_body(&self) -> fn(Vec<u8>) -> Vec<u8> {
57                    fn panic(post: Vec<u8>) -> Vec<u8> {
58                        panic!("NOT A POST ROUTE");
59                    };
60                    panic
61                }
62            }
63
64            Box::new(route::new())
65        }
66    };
67
68    output.into()
69}
70
71#[proc_macro_attribute]
72pub fn post(attr: TokenStream, item: TokenStream) -> TokenStream {
73    eprintln!("{:#?}\n{:#?}", attr, item);
74    let args = parse_macro_input!(attr as syn::AttributeArgs);
75    let item: syn::ItemFn = syn::parse(item).unwrap();
76
77    let name = item.sig.ident.clone();
78    let body = item.block.deref();
79    let path = args[0].clone();
80
81    let output = quote! {
82        fn #name() -> Box<Route> {
83
84            #[allow(non_camel_case_types)]
85
86            #[derive(Clone)]
87            struct route {
88                path: &'static str,
89                method: Method,
90            }
91
92            impl route {
93                fn new() -> Self {
94                    route {
95                        path: #path.into(),
96                        method: Method::POST,
97                    }
98                }
99            }
100
101            impl Default for route {
102                fn default() -> route {
103                    route {
104                        path: #path.into(),
105                        method: Method::POST,
106                    }
107                }
108            }
109
110            impl Route for route {
111                fn get_path(&self) -> &str {
112                    self.path
113                }
114                fn get_method(&self) -> Method {
115                    self.method
116                }
117                fn get_body(&self) -> Vec<u8> {
118                    panic!("NOT A GET!");
119                }
120                fn post_body(&self) -> fn(Vec<u8>) -> Vec<u8> {
121                    fn body(post: Vec<u8>) -> Vec<u8> {
122                        #body
123                    };
124                    body
125                }
126            }
127
128            Box::new(route::new())
129        }
130    };
131
132    /*let output = quote! {
133        fn #name() -> (String, Vec<u8>, Method) {
134            fn body() #output {
135                #body
136            }
137
138            (#path.into(), body().into(), Method::POST)
139        }
140    };*/
141
142    output.into()
143}