asar_snes_proc_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::parse_macro_input;
4
5/// This macro is used to ensure that the global lock is used in the function.
6/// 
7/// Usage 
8/// ```ignore
9/// use asar_snes::use_asar_global_lock;
10/// 
11/// #[use_asar_global_lock]
12/// fn my_function() {
13///    // code that uses multiple asar api calls in a multithreaded environment
14/// }
15/// ```
16/// # Note
17/// This attribute **only** does something if the `thread-safe` feature is **enabled**. Otherwise it is a no-op.
18#[proc_macro_attribute]
19pub fn use_asar_global_lock(_attr: TokenStream, item: TokenStream) -> TokenStream {
20    let input_fn = parse_macro_input!(item as syn::ItemFn);
21    let fn_name = &input_fn.sig.ident;
22    let fn_block = &input_fn.block;
23    let fn_return_type = &input_fn.sig.output;
24    let fn_arguments = &input_fn.sig.inputs;
25    let fn_visilibility = &input_fn.vis;
26    let doc_comments = &input_fn.attrs;
27    let generics = &input_fn.sig.generics;
28
29    let expanded = quote! {
30        #(#doc_comments)*
31        #fn_visilibility fn #fn_name #generics (#fn_arguments) #fn_return_type {
32            crate::with_asar_lock(|| {
33                #fn_block
34            })
35        }
36    };
37
38    TokenStream::from(expanded)
39}