tauri_plugin_dev_invoke_macros/
lib.rs1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{parse_macro_input, FnArg, ItemFn, Pat};
4
5#[proc_macro_attribute]
6pub fn command(_attr: TokenStream, item: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(item as ItemFn);
8 let name = &input.sig.ident;
9 let vis = &input.vis;
10 let wrapper_name = format_ident!("__dev_invoke_wrapper_{}", name);
11 let args_struct_name = format_ident!("__DevInvokeArgs_{}", name);
12
13 let mut struct_fields = Vec::new();
15 let mut call_args = Vec::new();
16
17 for arg in &input.sig.inputs {
18 if let FnArg::Typed(pat_type) = arg {
19 if let Pat::Ident(pat_ident) = &*pat_type.pat {
20 let arg_name = &pat_ident.ident;
21 let arg_type = &pat_type.ty;
22
23 struct_fields.push(quote! {
24 pub #arg_name: #arg_type
25 });
26 call_args.push(quote! {
27 args.#arg_name
28 });
29 }
30 }
31 }
32
33 let expanded = quote! {
34 #[tauri::command]
35 #input
36
37 #[allow(non_camel_case_types)]
38 #[derive(serde::Deserialize)]
39 pub struct #args_struct_name {
40 #(#struct_fields),*
41 }
42
43 #vis fn #wrapper_name(args_json: serde_json::Value) -> std::result::Result<serde_json::Value, String> {
44 let args: #args_struct_name = serde_json::from_value(args_json)
45 .map_err(|e| format!("Failed to deserialize arguments for {}: {}", stringify!(#name), e))?;
46
47 let result = #name(#(#call_args),*);
49
50 serde_json::to_value(result)
52 .map_err(|e| format!("Failed to serialize result for {}: {}", stringify!(#name), e))
53 }
54 };
55
56 TokenStream::from(expanded)
57}