Skip to content

Commit c3fb792

Browse files
author
David Barsky
committed
Add async-await based lambda.
1 parent f914c3f commit c3fb792

19 files changed

+3347
-0
lines changed

lambda-attributes/Cargo.lock

+948
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lambda-attributes/Cargo.toml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "lambda-attributes"
3+
version = "0.1.0"
4+
authors = ["David Barsky <[email protected]>"]
5+
edition = "2018"
6+
7+
[lib]
8+
proc-macro = true
9+
10+
[dependencies]
11+
syn = { version = "0.15.33", features = ["full"] }
12+
proc-macro2 = { version = "0.4.29", features = ["nightly"] }
13+
quote = "0.6.12"
14+
runtime = "0.3.0-alpha.5"
15+
bytes = "0.4.12"
16+
17+
[dev-dependencies]
18+
runtime = "0.3.0-alpha.5"

lambda-attributes/src/lib.rs

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
extern crate proc_macro;
2+
3+
use proc_macro::TokenStream;
4+
use quote::quote_spanned;
5+
use syn::{spanned::Spanned, FnArg, ItemFn};
6+
7+
#[cfg(not(test))]
8+
#[proc_macro_attribute]
9+
pub fn lambda(_attr: TokenStream, item: TokenStream) -> TokenStream {
10+
let input = syn::parse_macro_input!(item as ItemFn);
11+
12+
let ret = &input.decl.output;
13+
let name = &input.ident;
14+
let body = &input.block;
15+
let attrs = &input.attrs;
16+
let asyncness = &input.asyncness;
17+
let inputs = &input.decl.inputs;
18+
19+
if name != "main" {
20+
let tokens = quote_spanned! { name.span() =>
21+
compile_error!("only the main function can be tagged with #[lambda::main]");
22+
};
23+
return TokenStream::from(tokens);
24+
}
25+
26+
if asyncness.is_none() {
27+
let tokens = quote_spanned! { input.span() =>
28+
compile_error!("the async keyword is missing from the function declaration");
29+
};
30+
return TokenStream::from(tokens);
31+
}
32+
33+
let result = match inputs.len() {
34+
1 => {
35+
let event = match inputs.first().unwrap().into_value() {
36+
FnArg::Captured(arg) => arg,
37+
_ => {
38+
let tokens = quote_spanned! { inputs.span() =>
39+
compile_error!("fn main should take a fully formed argument");
40+
};
41+
return TokenStream::from(tokens);
42+
}
43+
};
44+
let arg_name = &event.pat;
45+
let arg_type = &event.ty;
46+
47+
quote_spanned! { input.span() =>
48+
#(#attrs)*
49+
#asyncness fn main() {
50+
async fn actual(#arg_name: #arg_type, ctx: Option<lambda::LambdaCtx>) #ret {
51+
#body
52+
}
53+
let f = lambda::handler_fn(actual);
54+
55+
lambda::run(f).await.unwrap();
56+
}
57+
}
58+
}
59+
2 => {
60+
let event = match inputs.first().unwrap().into_value() {
61+
FnArg::Captured(arg) => arg,
62+
_ => {
63+
let tokens = quote_spanned! { inputs.span() =>
64+
compile_error!("fn main should take a fully formed argument");
65+
};
66+
return TokenStream::from(tokens);
67+
}
68+
};
69+
let ctx = match &inputs[1] {
70+
FnArg::Captured(arg) => arg,
71+
_ => {
72+
let tokens = quote_spanned! { inputs.span() =>
73+
compile_error!("fn main should take a fully formed argument");
74+
};
75+
return TokenStream::from(tokens);
76+
}
77+
};
78+
let arg_name = &event.pat;
79+
let arg_type = &event.ty;
80+
let ctx_name = &ctx.pat;
81+
let ctx_type = &ctx.ty;
82+
quote_spanned! { input.span() =>
83+
#(#attrs)*
84+
#asyncness fn main() {
85+
async fn actual(#arg_name: #arg_type, #ctx_name: Option<#ctx_type>) #ret {
86+
let #ctx_name = #ctx_name.unwrap();
87+
#body
88+
}
89+
let f = lambda::handler_fn(actual);
90+
91+
lambda::run(f).await.unwrap();
92+
}
93+
}
94+
}
95+
_ => {
96+
let tokens = quote_spanned! { inputs.span() =>
97+
compile_error!("The #[lambda] macro can accept one or two arguments.");
98+
};
99+
return TokenStream::from(tokens);
100+
}
101+
};
102+
103+
result.into()
104+
}

0 commit comments

Comments
 (0)