libuio_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, ItemFn};
4
5#[proc_macro_attribute]
6pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
7    // Parse the input tokens into a syntax tree
8    let input = parse_macro_input!(item as ItemFn);
9    let block = input.block;
10    let output = input.sig.output;
11
12    // Check if the function is async
13    if input.sig.asyncness.is_none() {
14        panic!("The function must be async");
15    }
16
17    // Generate new Rust code based on the transformed AST
18    let expanded = quote! {
19        // Create new async function so we can replace the main function. Ensuring we handle the
20        // output type and proper block representation.
21        async fn __internal_main() #output #block
22
23        // Create the new main function with the proper output type to satisfy the original main
24        // function.
25        fn main() #output {
26            // First we need to create a new thread pool to execute on.
27            libuio::executor::ThreadPoolBuilder::new()
28                .name_prefix("libuio-executor")
29                .create()
30                .expect("Failed to configure thread pool.");
31
32            // Now we spawn our main async task, which will drive any/all async operations needed by our
33            // application.
34            libuio::executor::block_on(__internal_main())
35        }
36    };
37
38    // Return the generated code
39    TokenStream::from(expanded)
40}