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}