1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, Ident, ItemFn};
4
5#[proc_macro_attribute]
6pub fn bun(_attr: TokenStream, item: TokenStream) -> TokenStream {
7 let input_fn = parse_macro_input!(item as ItemFn);
9 let fn_name = &input_fn.sig.ident;
10 let inner_fn_name = Ident::new(&format!("__{}", fn_name), fn_name.span());
11 let fn_block = &input_fn.block;
12
13 let output = quote! {
15 #[no_mangle]
16 pub unsafe extern "C" fn #fn_name(
17 args_raw: *mut bun_native_plugin::sys::OnBeforeParseArguments,
18 result: *mut bun_native_plugin::sys::OnBeforeParseResult,
19 ) {
20 fn #inner_fn_name(handle: &mut bun_native_plugin::OnBeforeParse) -> Result<()> {
21 #fn_block
22 }
23
24 let args_path = unsafe { (*args_raw).path_ptr };
25 let args_path_len = unsafe { (*args_raw).path_len };
26 let result_pointer = result;
27
28 let result = std::panic::catch_unwind(|| {
29 let mut handle = match bun_native_plugin::OnBeforeParse::from_raw(args_raw, result) {
30 Ok(handle) => handle,
31 Err(_) => return,
32 };
33 if let Err(e) = #inner_fn_name(&mut handle) {
34 handle.log_error(&format!("{:?}", e));
35 }
36 });
37
38 if let Err(e) = result {
39 let msg_string = format!("Plugin crashed: {:?}", e);
40 let mut log_options = bun_native_plugin::log_from_message_and_level(
41 &msg_string,
42 bun_native_plugin::sys::BunLogLevel::BUN_LOG_LEVEL_ERROR,
43 args_path,
44 args_path_len,
45 );
46 unsafe {
47 ((*result_pointer).log.unwrap())(args_raw, &mut log_options);
48 }
49 }
50 }
51 };
52
53 output.into()
54}