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
7fn create_plugin_proc_macro_fn(
8 input: TokenStream,
9 export_name: &str,
10 parameter_type: &str,
11) -> TokenStream {
12 let parameter_type: syn::Type =
13 syn::parse_str(parameter_type).expect("failed to parse ServiceRegistry type");
14 let input = parse_macro_input!(input as syn::Item);
15
16 let syn::ItemFn { sig, block, .. } = match input {
17 syn::Item::Fn(f) => f,
18 _ => panic!("only `fn` items allowed"),
19 };
20
21 let (ident, inputs) = match sig {
22 Signature {
23 asyncness: Some(_), ..
24 } => {
25 panic!("async factories are not yet supported")
26 }
27 Signature {
28 variadic: Some(_), ..
29 } => {
30 panic!("variadic factories are not yet supported")
31 }
32 Signature {
33 ident,
34 output,
35 inputs,
36 generics,
37 ..
38 } => {
39 if !matches!(output, ReturnType::Default) {
40 panic!("function must have no output")
41 }
42
43 if !generics.params.is_empty() {
44 panic!("generic factories are not yet supported")
45 }
46
47 if inputs.len() != 1 {
48 panic!("only one input parameter is supported")
49 }
50
51 (ident, inputs)
52 }
53 };
54
55 let inner_fn_name =
56 syn::Ident::new(&("__inner_".to_string() + &ident.to_string()), ident.span());
57
58 quote! {
59 #[export_name = #export_name]
60 pub extern "C" fn #ident(registry: #parameter_type) {
61 #[inline(always)]
62 fn #inner_fn_name (#inputs) {
63 picodata_plugin::internal::set_panic_hook();
64
65 #block
66 }
67
68 #inner_fn_name(registry)
69 }
70 }
71 .into()
72}
73
74#[proc_macro_attribute]
75pub fn proc_service_registrar(_attr: TokenStream, input: TokenStream) -> TokenStream {
76 create_plugin_proc_macro_fn(
77 input,
78 "pico_service_registrar",
79 "&mut picodata_plugin::plugin::interface::ServiceRegistry",
80 )
81}
82
83#[proc_macro_attribute]
114pub fn proc_migration_validator(_attr: TokenStream, input: TokenStream) -> TokenStream {
115 create_plugin_proc_macro_fn(
116 input,
117 "pico_migration_validator",
118 "&mut picodata_plugin::plugin::interface::MigrationValidator",
119 )
120}