wasmtime_c_api_macros/
lib.rs

1//! A set of convenience macros for our wasmtime-c-api crate.
2//!
3//! These are intended to mirror the macros in the `wasm.h` header file and
4//! largely facilitate the `declare_ref` macro.
5
6use proc_macro2::{Ident, TokenStream, TokenTree};
7use quote::quote;
8
9fn extract_ident(input: proc_macro::TokenStream) -> Ident {
10    let input = TokenStream::from(input);
11    let i = match input.into_iter().next().unwrap() {
12        TokenTree::Ident(i) => i,
13        _ => panic!("expected an ident"),
14    };
15    let name = i.to_string();
16    assert!(name.ends_with("_t"));
17    return i;
18}
19
20#[proc_macro]
21pub fn declare_own(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
22    let ty = extract_ident(input);
23    let name = ty.to_string();
24    let delete = quote::format_ident!("{}_delete", &name[..name.len() - 2]);
25    let docs = format!("Deletes the [`{name}`].");
26
27    (quote! {
28        #[doc = #docs]
29        #[unsafe(no_mangle)]
30        pub extern fn #delete(_: Box<#ty>) {}
31    })
32    .into()
33}
34
35#[proc_macro]
36pub fn declare_ty(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
37    let ty = extract_ident(input);
38    let name = ty.to_string();
39    let prefix = &name[..name.len() - 2];
40    let copy = quote::format_ident!("{}_copy", &prefix);
41    let docs = format!(
42        "Creates a new [`{name}`] which matches the provided one.\n\n\
43        The caller is responsible for deleting the returned value via [`{prefix}_delete`].\n\n\
44    "
45    );
46
47    (quote! {
48        wasmtime_c_api_macros::declare_own!(#ty);
49
50        #[doc = #docs]
51        #[unsafe(no_mangle)]
52        pub extern fn #copy(src: &#ty) -> Box<#ty> {
53            Box::new(src.clone())
54        }
55    })
56    .into()
57}
58
59#[proc_macro]
60pub fn declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
61    let ty = extract_ident(input);
62    let name = ty.to_string();
63    let prefix = &name[..name.len() - 2];
64    let same = quote::format_ident!("{}_same", prefix);
65    let same_docs = format!(
66        "Returns `true` if the given references are pointing to the same [`{name}`].\n\n\
67        This is not yet supported and aborts the process upon use."
68    );
69    let get_host_info = quote::format_ident!("{}_get_host_info", prefix);
70    let get_host_info_docs = format!(
71        "Returns the host information of the [`{name}`].\n\n\
72        This is not yet supported and always returns `NULL`."
73    );
74    let set_host_info = quote::format_ident!("{}_set_host_info", prefix);
75    let set_host_info_docs = format!(
76        "Sets the host information of the [`{name}`].\n\n\
77        This is not yet supported and aborts the process upon use."
78    );
79    let set_host_info_final = quote::format_ident!("{}_set_host_info_with_finalizer", prefix);
80    let set_host_info_final_docs = format!(
81        "Sets the host information finalizer of the [`{name}`].\n\n\
82        This is not yet supported and aborts the process upon use."
83    );
84    let as_ref = quote::format_ident!("{}_as_ref", prefix);
85    let as_ref_docs = format!(
86        "Returns the [`{name}`] as mutable reference.\n\n\
87        This is not yet supported and aborts the process upon use."
88    );
89    let as_ref_const = quote::format_ident!("{}_as_ref_const", prefix);
90    let as_ref_const_docs = format!(
91        "Returns the [`{name}`] as immutable reference.\n\n\
92        This is not yet supported and aborts the process upon use."
93    );
94
95    (quote! {
96        wasmtime_c_api_macros::declare_ty!(#ty);
97
98        #[doc = #same_docs]
99        #[unsafe(no_mangle)]
100        pub extern fn #same(_a: &#ty, _b: &#ty) -> bool {
101            eprintln!("`{}` is not implemented", stringify!(#same));
102            std::process::abort();
103        }
104
105        #[doc = #get_host_info_docs]
106        #[unsafe(no_mangle)]
107        pub extern fn #get_host_info(a: &#ty) -> *mut std::os::raw::c_void {
108            std::ptr::null_mut()
109        }
110
111        #[doc = #set_host_info_docs]
112        #[unsafe(no_mangle)]
113        pub extern fn #set_host_info(a: &#ty, info: *mut std::os::raw::c_void) {
114            eprintln!("`{}` is not implemented", stringify!(#set_host_info));
115            std::process::abort();
116        }
117
118        #[doc = #set_host_info_final_docs]
119        #[unsafe(no_mangle)]
120        pub extern fn #set_host_info_final(
121            a: &#ty,
122            info: *mut std::os::raw::c_void,
123            finalizer: Option<extern "C" fn(*mut std::os::raw::c_void)>,
124        ) {
125            eprintln!("`{}` is not implemented", stringify!(#set_host_info_final));
126            std::process::abort();
127        }
128
129        #[doc = #as_ref_docs]
130        #[unsafe(no_mangle)]
131        pub extern fn #as_ref(a: &#ty) -> Box<crate::wasm_ref_t> {
132            eprintln!("`{}` is not implemented", stringify!(#as_ref));
133            std::process::abort();
134        }
135
136        #[doc = #as_ref_const_docs]
137        #[unsafe(no_mangle)]
138        pub extern fn #as_ref_const(a: &#ty) -> Box<crate::wasm_ref_t> {
139            eprintln!("`{}` is not implemented", stringify!(#as_ref_const));
140            std::process::abort();
141        }
142
143        // TODO: implement `wasm_ref_as_#name#`
144        // TODO: implement `wasm_ref_as_#name#_const`
145    })
146    .into()
147}