1#![doc = include_str!("../README.md")]
2
3extern crate proc_macro2;
4
5use proc_macro::TokenStream;
6use quote::quote;
7use syn::{parse_macro_input, parse_str, Expr, ItemFn, LitStr};
8
9#[proc_macro_attribute]
10pub fn multithread(_: TokenStream, item: TokenStream) -> TokenStream {
11 let ItemFn {
12 sig,
13 vis,
14 block,
15 attrs,
16 } = parse_macro_input!(item as ItemFn);
17
18 let ident = &sig.ident;
19 let mut args = Vec::with_capacity(sig.inputs.len());
20 for input in sig.inputs.iter() {
21 let syn::FnArg::Typed(pat_type) = input else {
22 unreachable!()
23 };
24 args.push(&pat_type.pat);
25 }
26
27 quote!(
28 #(#attrs)*
29 #vis #sig {
30 let sqlite3 = sqlite();
31 if !sqlite3.main_thread() {
32 let CApiResp::#ident(ret) = call(sqlite3, CApiReq::#ident((#(#args),*))) else {
33 unreachable!()
34 };
35 return ret;
36 }
37 #block
38 }
39 )
40 .into()
41}
42
43#[proc_macro_attribute]
44pub fn multithread_v2(input: TokenStream, item: TokenStream) -> TokenStream {
45 let ItemFn {
46 sig,
47 vis,
48 block,
49 attrs,
50 } = parse_macro_input!(item as ItemFn);
51
52 let ident = &sig.ident;
53 let mut args = Vec::with_capacity(sig.inputs.len());
54 for input in sig.inputs.iter() {
55 let syn::FnArg::Typed(pat_type) = input else {
56 unreachable!()
57 };
58 args.push(&pat_type.pat);
59 }
60
61 let extra = parse_macro_input!(input as LitStr);
62 let expr = parse_str::<Expr>(&extra.value()).unwrap();
63
64 quote!(
65 #(#attrs)*
66 #vis #sig {
67 let handle = get_handle(#expr);
68 if !handle.main_thread() {
69 let CApiResp::#ident(ret) = call(handle, CApiReq::#ident((#(#args),*))) else {
70 unreachable!()
71 };
72 return ret;
73 }
74 #block
75 }
76 )
77 .into()
78}