gut_plugin/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::parse::{Parse, ParseStream};
4use syn::{parse_macro_input, Expr, ExprArray, Lit, Result, Token};
5
6struct PluginInput {
7    names: ExprArray,
8    descriptions: ExprArray,
9}
10
11impl Parse for PluginInput {
12    fn parse(input: ParseStream) -> Result<Self> {
13        let names: ExprArray = input.parse()?;
14        input.parse::<Token![,]>()?;
15        let descriptions: ExprArray = input.parse()?;
16
17        let out = Self {
18            names,
19            descriptions,
20        };
21        Ok(out)
22    }
23}
24
25#[proc_macro]
26pub fn gut_export(input: TokenStream) -> TokenStream {
27    // parse macro input
28    let data = parse_macro_input!(input as PluginInput);
29
30    // convert input into vector of strings
31    let names: Vec<String> = data
32        .names
33        .elems
34        .into_iter()
35        .map(|x| match x {
36            Expr::Lit(expr_lit) => match expr_lit.lit {
37                Lit::Str(lit_str) => lit_str.value(),
38                _ => "".to_string(),
39            },
40            _ => "".to_string(),
41        })
42        .collect();
43    let descriptions: Vec<String> = data
44        .descriptions
45        .elems
46        .into_iter()
47        .map(|x| match x {
48            Expr::Lit(expr_lit) => match expr_lit.lit {
49                Lit::Str(lit_str) => lit_str.value(),
50                _ => "".to_string(),
51            },
52            _ => "".to_string(),
53        })
54        .collect();
55
56    // convert to JSON string
57    let json_names = serde_json::to_string(&names).expect("Failed to convert to JSON string");
58    let json_descriptions =
59        serde_json::to_string(&descriptions).expect("Failed to convert to JSON string");
60
61    // create rust code with qoute
62    let exports = quote! {
63        use std::ffi::CString;
64        use std::os::raw::c_char;
65
66        #[no_mangle]
67        pub extern "C" fn gut_export_functions() -> *mut c_char {
68            let c_string = CString::new(#json_names).expect("Failed to create c_string");
69            c_string.into_raw()
70        }
71
72        #[no_mangle]
73        pub extern "C" fn gut_export_descriptions() -> *mut c_char {
74            let c_string = CString::new(#json_descriptions).expect("Failed to create c_string");
75            c_string.into_raw()
76        }
77    };
78
79    exports.into()
80}