Skip to main content

component_init_macro/
lib.rs

1use proc_macro::TokenStream;
2use quote::{quote, quote_spanned};
3use syn::{ItemFn, parse_macro_input, spanned::Spanned};
4
5#[proc_macro_attribute]
6pub fn init(_attr: TokenStream, item: TokenStream) -> TokenStream {
7    let input = parse_macro_input!(item as ItemFn);
8    if input.sig.asyncness.is_some() {
9        return quote_spanned! { input.sig.fn_token.span()=>
10            compile_error!("fn cannot be async");
11        }
12        .into();
13    }
14    if !input.sig.inputs.is_empty() {
15        return quote_spanned! { input.sig.inputs.span()=>
16            compile_error!("function cannot have arguments");
17        }
18        .into();
19    }
20    let callee = &input.sig.ident;
21
22    quote! {
23        #input
24
25        mod __component_init {
26            component_init::__bindgen::generate!({
27                inline: r"
28                package this:wit;
29                world w {
30                    export component-init: func();
31                }
32                ",
33                runtime_path: "component_init::__bindgen::rt",
34            });
35            struct __S;
36            impl Guest for __S {
37                fn component_init() {
38                    super::#callee()
39                }
40            }
41            export!(__S);
42        }
43    }
44    .into()
45}