titan_router_derive/
lib.rs1use proc_macro::TokenStream as TokenStream1;
2use proc_macro2::TokenStream as TokenStream2;
3use syn::{
4 braced,
5 parse::{Parse, ParseStream},
6 parse_macro_input, Expr, LitStr, Token,
7};
8
9struct PathMapping {
11 path: LitStr,
12 _arrow: Token![=>],
13 ident: Expr,
14}
15
16struct PathMappings {
18 mappings: Vec<PathMapping>,
19}
20
21impl Parse for PathMapping {
22 fn parse(input: ParseStream) -> syn::Result<Self> {
23 let path = input.parse()?; let _arrow = input.parse()?; let ident = input.parse()?; Ok(PathMapping { path, _arrow, ident })
27 }
28}
29
30impl Parse for PathMappings {
31 fn parse(input: ParseStream) -> syn::Result<Self> {
32 let content;
33 let _braces = braced!(content in input); let mut mappings = Vec::new();
36 while !content.is_empty() {
37 mappings.push(content.parse()?); if content.peek(Token![,]) {
39 content.parse::<Token![,]>()?; }
41 }
42
43 Ok(PathMappings { mappings })
44 }
45}
46
47#[proc_macro]
48pub fn define_routes(input: TokenStream1) -> TokenStream1 {
49 let path_mappings = parse_macro_input!(input as PathMappings);
50
51 impl_define_routes(path_mappings).into()
52}
53
54fn impl_define_routes(mappings: PathMappings) -> TokenStream2 {
55 let mut base = Vec::from_iter([quote::quote! {
56 let mut router = Router::default();
57 }]);
58
59 for mapping in mappings.mappings {
60 let key = mapping.path;
61 let value = mapping.ident;
62 base.push(quote::quote! {
63 router.at(#key, #value);
64 });
65 }
66
67 quote::quote! {{
68 #(#base)*
69
70 router
71 }}
72}