async_main proc macro

This commit is contained in:
missing 2022-02-25 14:24:38 -06:00
parent 8c9020d815
commit d118d4336f
11 changed files with 96 additions and 27 deletions

View file

@ -1,9 +1,7 @@
[package]
name = "messing_with_async"
version = "0.1.0"
edition = "2021"
[workspace]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
futures = "0.3"
members = [
"bin",
"messing_with_async",
"async_main"
]

13
async_main/Cargo.toml Normal file
View file

@ -0,0 +1,13 @@
[package]
name = "async_main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true
[dependencies]
quote = "1.0.15"
syn = { version = "1.0.86", features = [ "full" ] }

51
async_main/src/lib.rs Normal file
View file

@ -0,0 +1,51 @@
extern crate proc_macro;
use core::panic;
use proc_macro::TokenStream;
use syn::ItemFn;
use quote::quote;
/// Sets up the given `async fn` to be the entry point.
///
/// ```no_run
/// # // i see no way to `use messing_with_async::block_on`, so we cant run this test
/// #[async_main]
/// async fn async_main() {
/// println!("Hello, world!");
/// }
/// ```
#[proc_macro_attribute]
pub fn async_main(_: TokenStream, item: TokenStream) -> TokenStream {
let func = syn::parse::<ItemFn>(item).unwrap_or_else(
|_| panic!("`async_main` can only be applied to functions!")
);
if func.sig.asyncness.is_none() {
panic!("`async_main` can only be applied to an `async fn`!");
}
if !func.sig.inputs.is_empty() {
panic!("`async_main` cannot be applied to functions with arguments!");
}
if !func.sig.generics.params.is_empty() {
panic!("`async_main` cannot be applied to generic functions!");
}
if func.sig.unsafety.is_some() {
panic!("`async_main` cannot be applied to unsafe functions!");
}
let ident = func.sig.ident.clone();
quote! {
fn main() {
use ::messing_with_async::block_on;
#func
let _ = block_on(#ident());
}
}.into()
}

9
bin/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "bin"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
messing_with_async = { path = "../messing_with_async", features = [ "proc-macro" ] }

View file

@ -1,6 +1,6 @@
use messing_with_async::{async_main, all, sleep, FutureExt, stream::{from_iter, StreamExt}};
async_main!(async_main);
#[async_main]
async fn async_main() {
println!("hi!");
sleep!(1000).await;

View file

@ -0,0 +1,13 @@
[package]
name = "messing_with_async"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
# futures = "0.3"
async_main = { path = "../async_main", optional = true }
[features]
proc-macro = ["async_main"]

View file

@ -1,21 +1,6 @@
/// Sets up the given `async fn` to be the entry point.
///
/// ```
/// # use messing_with_async::async_main;
/// async_main!(async_main);
/// async fn async_main() {
/// println!("Hello, world!");
/// }
/// # main(); // needed cause the main generated by the macro isnt recognized by doctests
/// ```
#[macro_export]
macro_rules! async_main {
($ident:ident) => {
fn main() {
let _ = $crate::block_on($ident());
}
};
}
#[doc(inline)]
#[cfg(feature = "proc-macro")]
pub use async_main::async_main;
use std::{sync::{mpsc::{SyncSender, self, RecvError}, Arc, Mutex}, pin::Pin, future::Future, task::{Context, Poll}};