picodata_plugin_proc_macro/
lib.rs1extern crate proc_macro;
2use proc_macro::TokenStream;
3
4use quote::quote;
5use syn::{parse_macro_input, ReturnType, Signature};
6
7#[proc_macro_attribute]
8pub fn proc_service_registrar(_attr: TokenStream, input: TokenStream) -> TokenStream {
9 let input = parse_macro_input!(input as syn::Item);
10
11 let syn::ItemFn { sig, block, .. } = match input {
12 syn::Item::Fn(f) => f,
13 _ => panic!("only `fn` items allowed"),
14 };
15
16 let (ident, inputs, _generics) = match sig {
17 Signature {
18 asyncness: Some(_), ..
19 } => {
20 panic!("async factory are not supported yet")
21 }
22 Signature {
23 variadic: Some(_), ..
24 } => {
25 panic!("variadic factory are not supported yet")
26 }
27 Signature {
28 ident,
29 output,
30 inputs,
31 generics,
32 ..
33 } => {
34 if !matches!(output, ReturnType::Default) {
35 panic!("function must have no output")
36 }
37
38 if inputs.len() != 1 {
39 panic!("there is only 1 input argument supported")
40 }
41
42 (ident, inputs, generics)
43 }
44 };
45
46 let inner_fn_name =
47 syn::Ident::new(&("__inner_".to_string() + &ident.to_string()), ident.span());
48
49 quote! {
51 #[export_name = "pico_service_registrar"]
52 pub extern "C" fn #ident(registry: &mut picodata_plugin::plugin::interface::ServiceRegistry) {
53 #[inline(always)]
54 fn #inner_fn_name (#inputs) {
55 picodata_plugin::internal::set_panic_hook();
56
57 #block
58 }
59
60 #inner_fn_name(registry)
61 }
62 }
63 .into()
64}