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}