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 //!
6 //! > **⚠️ Warning ⚠️**: this crate is an internal-only crate for the Wasmtime
7 //! > project and is not intended for general use. APIs are not strictly
8 //! > reviewed for safety and usage outside of Wasmtime may have bugs. If
9 //! > you're interested in using this feel free to file an issue on the
10 //! > Wasmtime repository to start a discussion about doing so, but otherwise
11 //! > be aware that your usage of this crate is not supported.
12 
13 use proc_macro2::{Ident, TokenStream, TokenTree};
14 use quote::quote;
15 
extract_ident(input: proc_macro::TokenStream) -> Ident16 fn extract_ident(input: proc_macro::TokenStream) -> Ident {
17     let input = TokenStream::from(input);
18     let i = match input.into_iter().next().unwrap() {
19         TokenTree::Ident(i) => i,
20         _ => panic!("expected an ident"),
21     };
22     let name = i.to_string();
23     assert!(name.ends_with("_t"));
24     return i;
25 }
26 
27 #[proc_macro]
declare_own(input: proc_macro::TokenStream) -> proc_macro::TokenStream28 pub fn declare_own(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
29     let ty = extract_ident(input);
30     let name = ty.to_string();
31     let delete = quote::format_ident!("{}_delete", &name[..name.len() - 2]);
32     let docs = format!("Deletes the [`{name}`].");
33 
34     (quote! {
35         #[doc = #docs]
36         #[unsafe(no_mangle)]
37         pub extern fn #delete(_: Box<#ty>) {}
38     })
39     .into()
40 }
41 
42 #[proc_macro]
declare_ty(input: proc_macro::TokenStream) -> proc_macro::TokenStream43 pub fn declare_ty(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
44     let ty = extract_ident(input);
45     let name = ty.to_string();
46     let prefix = &name[..name.len() - 2];
47     let copy = quote::format_ident!("{}_copy", &prefix);
48     let docs = format!(
49         "Creates a new [`{name}`] which matches the provided one.\n\n\
50         The caller is responsible for deleting the returned value via [`{prefix}_delete`].\n\n\
51     "
52     );
53 
54     (quote! {
55         wasmtime_c_api_macros::declare_own!(#ty);
56 
57         #[doc = #docs]
58         #[unsafe(no_mangle)]
59         pub extern fn #copy(src: &#ty) -> Box<#ty> {
60             Box::new(src.clone())
61         }
62     })
63     .into()
64 }
65 
66 #[proc_macro]
declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream67 pub fn declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
68     let ty = extract_ident(input);
69     let name = ty.to_string();
70     let prefix = &name[..name.len() - 2];
71     let same = quote::format_ident!("{}_same", prefix);
72     let same_docs = format!(
73         "Returns `true` if the given references are pointing to the same [`{name}`].\n\n\
74         This is not yet supported and aborts the process upon use."
75     );
76     let get_host_info = quote::format_ident!("{}_get_host_info", prefix);
77     let get_host_info_docs = format!(
78         "Returns the host information of the [`{name}`].\n\n\
79         This is not yet supported and always returns `NULL`."
80     );
81     let set_host_info = quote::format_ident!("{}_set_host_info", prefix);
82     let set_host_info_docs = format!(
83         "Sets the host information of the [`{name}`].\n\n\
84         This is not yet supported and aborts the process upon use."
85     );
86     let set_host_info_final = quote::format_ident!("{}_set_host_info_with_finalizer", prefix);
87     let set_host_info_final_docs = format!(
88         "Sets the host information finalizer of the [`{name}`].\n\n\
89         This is not yet supported and aborts the process upon use."
90     );
91     let as_ref = quote::format_ident!("{}_as_ref", prefix);
92     let as_ref_docs = format!(
93         "Returns the [`{name}`] as mutable reference.\n\n\
94         This is not yet supported and aborts the process upon use."
95     );
96     let as_ref_const = quote::format_ident!("{}_as_ref_const", prefix);
97     let as_ref_const_docs = format!(
98         "Returns the [`{name}`] as immutable reference.\n\n\
99         This is not yet supported and aborts the process upon use."
100     );
101 
102     (quote! {
103         wasmtime_c_api_macros::declare_ty!(#ty);
104 
105         #[doc = #same_docs]
106         #[unsafe(no_mangle)]
107         pub extern fn #same(_a: &#ty, _b: &#ty) -> bool {
108             eprintln!("`{}` is not implemented", stringify!(#same));
109             std::process::abort();
110         }
111 
112         #[doc = #get_host_info_docs]
113         #[unsafe(no_mangle)]
114         pub extern fn #get_host_info(a: &#ty) -> *mut std::os::raw::c_void {
115             std::ptr::null_mut()
116         }
117 
118         #[doc = #set_host_info_docs]
119         #[unsafe(no_mangle)]
120         pub extern fn #set_host_info(a: &#ty, info: *mut std::os::raw::c_void) {
121             eprintln!("`{}` is not implemented", stringify!(#set_host_info));
122             std::process::abort();
123         }
124 
125         #[doc = #set_host_info_final_docs]
126         #[unsafe(no_mangle)]
127         pub extern fn #set_host_info_final(
128             a: &#ty,
129             info: *mut std::os::raw::c_void,
130             finalizer: Option<extern "C" fn(*mut std::os::raw::c_void)>,
131         ) {
132             eprintln!("`{}` is not implemented", stringify!(#set_host_info_final));
133             std::process::abort();
134         }
135 
136         #[doc = #as_ref_docs]
137         #[unsafe(no_mangle)]
138         pub extern fn #as_ref(a: &#ty) -> Box<crate::wasm_ref_t> {
139             eprintln!("`{}` is not implemented", stringify!(#as_ref));
140             std::process::abort();
141         }
142 
143         #[doc = #as_ref_const_docs]
144         #[unsafe(no_mangle)]
145         pub extern fn #as_ref_const(a: &#ty) -> Box<crate::wasm_ref_t> {
146             eprintln!("`{}` is not implemented", stringify!(#as_ref_const));
147             std::process::abort();
148         }
149 
150         // TODO: implement `wasm_ref_as_#name#`
151         // TODO: implement `wasm_ref_as_#name#_const`
152     })
153     .into()
154 }
155