1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{ItemFn, parse_macro_input};
4
5#[proc_macro_attribute]
6pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
7 let mut input_fn = parse_macro_input!(item as ItemFn);
8
9 if input_fn.sig.asyncness.is_none() {
10 return syn::Error::new_spanned(
11 &input_fn.sig.fn_token,
12 "The #[bolt_web::main] function must be async.",
13 )
14 .to_compile_error()
15 .into();
16 }
17
18 input_fn.sig.asyncness = None;
19
20 let core_count = num_cpus::get();
21
22 let block = &input_fn.block;
23 let attrs = &input_fn.attrs;
24 let vis = &input_fn.vis;
25 let sig = &input_fn.sig;
26
27 let expanded = quote! {
28 #(#attrs)*
29 #vis #sig {
30 use std::error::Error;
31
32 let rt = bolt_web::tokio::runtime::Builder::new_multi_thread()
33 .worker_threads(#core_count)
34 .enable_all()
35 .build()
36 .unwrap();
37
38 let result: Result<(), Box<dyn Error + Send + Sync>> = rt.block_on(async move {
39 #block
40 });
41
42
43 if let Err(e) = result {
44 eprintln!("Bolt Web Application Error: {}", e);
45 ::std::process::exit(1);
46 }
47
48 Ok(())
49
50 }
51 };
52
53 expanded.into()
54}