lando_attr/
lib.rs

1//! provides function attribute macros for AWS Api Gateway for use in lando
2
3extern crate proc_macro;
4#[macro_use]
5extern crate quote;
6extern crate syn;
7
8// std lib(ish)
9use proc_macro::TokenStream;
10
11// third party
12use syn::{parse, ItemFn, ReturnType};
13
14/// Implements the `lando` attribute.
15///
16/// This attribute is used to turn a Rust function into an AWS Gateway
17/// triggerable lambda. In lambda you can refer to these by path with
18/// `lib{crate_name}.{fn_name}`
19///
20/// # Examples
21///
22/// ```rust,ignore
23/// #[macro_use] extern crate lando;
24/// use lando::{LambdaContext, Request, Response};
25///
26/// #[lando]
27/// pub fn example<'a>(_: Request, _: LambdaContext) -> Response<&'a str> {
28///   Ok("hello lambda")
29/// }
30/// ```
31#[proc_macro_attribute]
32pub fn lando(args: TokenStream, input: TokenStream) -> TokenStream {
33    attr_impl(args, input)
34}
35
36// implementation. should expect the following
37// * verify function type
38// * input args are (lando::Request, lando::LambdaContext)
39// * return type is lando::LandoResponse
40fn attr_impl(_: TokenStream, input: TokenStream) -> TokenStream {
41    let target: ItemFn = match parse(input.clone()) {
42        Ok(f) => f,
43        _ => {
44            panic!("the 'lando' attribute can only be used on functions");
45            // https://doc.rust-lang.org/proc_macro/struct.Span.html#method.error
46            // use the following when this becomes stable
47            /*Span::call_site()
48            .error("the 'lando' attribute can only be used on functions")
49            .emit();*/        }
50    };
51    if target.decl.inputs.len() != 2 {
52        panic!(
53            "the 'lando' attribute requires a function with two arguments. expecting {}(_: lando::Request, _: lando::LambdaContext) -> lando::Result", target.ident
54            );
55        // https://doc.rust-lang.org/proc_macro/struct.Span.html#method.error
56        // use the following when it becomes stable
57    }
58    match target.decl.output {
59        ReturnType::Default => {
60            // https://doc.rust-lang.org/proc_macro/struct.Span.html#method.error
61            // use the following when it becomes stable
62            panic!("the 'lando' attribute requires a function that returns a value. expecting {}(_: lando::Request, _: lando::LambdaContext) -> lando::Result", target.ident);
63        }
64        _ => (),
65    }
66    let target_ident = target.ident.clone();
67    let target_name = target_ident.to_string();
68    let expanded = quote! {
69        #target
70
71        gateway!(#target_name => #target_ident);
72    };
73    expanded.into()
74}