Skip to content

Commit

Permalink
Add async-await based lambda.
Browse files Browse the repository at this point in the history
  • Loading branch information
David Barsky committed Jun 28, 2019
1 parent f914c3f commit c3fb792
Show file tree
Hide file tree
Showing 19 changed files with 3,347 additions and 0 deletions.
948 changes: 948 additions & 0 deletions lambda-attributes/Cargo.lock

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions lambda-attributes/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "lambda-attributes"
version = "0.1.0"
authors = ["David Barsky <[email protected]>"]
edition = "2018"

[lib]
proc-macro = true

[dependencies]
syn = { version = "0.15.33", features = ["full"] }
proc-macro2 = { version = "0.4.29", features = ["nightly"] }
quote = "0.6.12"
runtime = "0.3.0-alpha.5"
bytes = "0.4.12"

[dev-dependencies]
runtime = "0.3.0-alpha.5"
104 changes: 104 additions & 0 deletions lambda-attributes/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote_spanned;
use syn::{spanned::Spanned, FnArg, ItemFn};

#[cfg(not(test))]
#[proc_macro_attribute]
pub fn lambda(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(item as ItemFn);

let ret = &input.decl.output;
let name = &input.ident;
let body = &input.block;
let attrs = &input.attrs;
let asyncness = &input.asyncness;
let inputs = &input.decl.inputs;

if name != "main" {
let tokens = quote_spanned! { name.span() =>
compile_error!("only the main function can be tagged with #[lambda::main]");
};
return TokenStream::from(tokens);
}

if asyncness.is_none() {
let tokens = quote_spanned! { input.span() =>
compile_error!("the async keyword is missing from the function declaration");
};
return TokenStream::from(tokens);
}

let result = match inputs.len() {
1 => {
let event = match inputs.first().unwrap().into_value() {
FnArg::Captured(arg) => arg,
_ => {
let tokens = quote_spanned! { inputs.span() =>
compile_error!("fn main should take a fully formed argument");
};
return TokenStream::from(tokens);
}
};
let arg_name = &event.pat;
let arg_type = &event.ty;

quote_spanned! { input.span() =>
#(#attrs)*
#asyncness fn main() {
async fn actual(#arg_name: #arg_type, ctx: Option<lambda::LambdaCtx>) #ret {
#body
}
let f = lambda::handler_fn(actual);

lambda::run(f).await.unwrap();
}
}
}
2 => {
let event = match inputs.first().unwrap().into_value() {
FnArg::Captured(arg) => arg,
_ => {
let tokens = quote_spanned! { inputs.span() =>
compile_error!("fn main should take a fully formed argument");
};
return TokenStream::from(tokens);
}
};
let ctx = match &inputs[1] {
FnArg::Captured(arg) => arg,
_ => {
let tokens = quote_spanned! { inputs.span() =>
compile_error!("fn main should take a fully formed argument");
};
return TokenStream::from(tokens);
}
};
let arg_name = &event.pat;
let arg_type = &event.ty;
let ctx_name = &ctx.pat;
let ctx_type = &ctx.ty;
quote_spanned! { input.span() =>
#(#attrs)*
#asyncness fn main() {
async fn actual(#arg_name: #arg_type, #ctx_name: Option<#ctx_type>) #ret {
let #ctx_name = #ctx_name.unwrap();
#body
}
let f = lambda::handler_fn(actual);

lambda::run(f).await.unwrap();
}
}
}
_ => {
let tokens = quote_spanned! { inputs.span() =>
compile_error!("The #[lambda] macro can accept one or two arguments.");
};
return TokenStream::from(tokens);
}
};

result.into()
}
Loading

0 comments on commit c3fb792

Please sign in to comment.