hirun_macros/
lib.rs

1//!  hirun-macros提供hirun的过程宏实现部分的功能
2//!
3
4#[allow(unused_extern_crates)]
5extern crate proc_macro;
6
7use proc_macro::TokenStream;
8use proc_macro2::Span;
9use quote::{quote, ToTokens};
10use syn::{parse_macro_input, ItemFn};
11
12///
13/// 如下的实现的async函数内部使用了Rc,因为不支持Send,无法利用tokio::spawn调度
14///
15/// ```rust
16/// async fn foo() -> i32 {
17///     let id = Rc::new(0);
18///     bar(*id).await;
19/// }
20/// ```
21/// 如下定义即可保证Rc可在Future内部正常使用,同时保证安全和性能
22/// ```rust
23/// #[hirun::future]
24/// async fn foo() -> i32 {
25///     let id = Rc::new(0);
26///     bar(*id).await;
27/// }
28/// ```
29///
30
31#[proc_macro_attribute]
32pub fn future(_args: TokenStream, item: TokenStream) -> TokenStream {
33    let mut input = parse_macro_input!(item as ItemFn);
34
35    if input.sig.asyncness.is_none() {
36        let msg = "only used with `async` function";
37        return syn::Error::new(Span::call_site(), msg)
38            .into_compile_error()
39            .into();
40    }
41
42    make_send_future(&mut input)
43}
44
45fn make_send_future(input: &mut ItemFn) -> TokenStream {
46    let body = input.block.to_token_stream();
47
48    let body_tokens: TokenStream = quote!({
49    let future = unsafe { ::hirun::runtime::SendFuture::new(async move { #body }) };
50    future.await
51    })
52    .into();
53
54    let wrapper = parse_macro_input!(body_tokens as syn::Stmt);
55    input.block.stmts.clear();
56    input.block.stmts.push(wrapper);
57
58    input.to_token_stream().into()
59}
60