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 block = &input_fn.block;
21 let attrs = &input_fn.attrs;
22 let vis = &input_fn.vis;
23 let sig = &input_fn.sig;
24
25 let expanded = quote! {
26 #(#attrs)*
27 #vis #sig {
28 use std::error::Error;
29 let core_count = ::num_cpus::get();
30
31 let rt = bolt_web::tokio::runtime::Builder::new_multi_thread()
32 .worker_threads(core_count)
33 .enable_all()
34 .build()
35 .unwrap();
36
37 let result: Result<(), Box<dyn Error + Send + Sync>> = rt.block_on(async move {
38 #block
39 });
40
41
42 if let Err(e) = result {
43 eprintln!("Bolt Web Application Error: {}", e);
44 ::std::process::exit(1);
45 }
46
47 Ok(())
48
49 }
50 };
51
52 expanded.into()
53}