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
62
63
64
65
66
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};

mod app_macro;
mod router_macro;

/// wraps your function in a new one that handles http requests and returns responses
///
/// # Syntax
///
/// the first thing to do is specify the method in all caps without quotes
/// #[router(GET)]
///
/// from there specify the path to the resource you want to bind to that is quoted & starts with a leading slash
/// #[router(GET "/my_route")]
///
///
/// # Examples
///
/// ```
/// #[router(GET "/my_route")]
/// pub async fn my_route(input: ()) -> Result<(), ()> {
///     todo!();
///     Ok(())
/// }
/// ```
#[proc_macro_attribute]
pub fn router(args: TokenStream, input: TokenStream) -> TokenStream {
    let arguments = parse_macro_input!(args as router_macro::arguments::Arguments);
    let item_fn = parse_macro_input!(input as ItemFn);

    let ast = router_macro::ast::Ast { item_fn, arguments };

    quote! {
        #ast
    }
    .into()
}

/// provides the entry point for lambdas to handle routing
///
/// # Syntax
/// app! { #EVENT,  ...#HANDLERS,  #\[default\] 404_HANDLER, ...#HANDLERS  }
///
/// you are not required to put #\[not_found\] for the 404 handler at the bottom but it is recommended
///
/// # Examples
///
/// ```
/// app! {
///     event,
///     my_route,
///     #[not_found]
///     not_found,
/// }
/// ```
#[proc_macro]
pub fn app(input: TokenStream) -> TokenStream {
    let lambda_app = parse_macro_input!(input as app_macro::lambda_app::LambdaApp);

    quote! {
        #lambda_app
    }
    .into()
}