wasmtime_internal_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//!
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
13use proc_macro2::{Ident, TokenStream, TokenTree};
14use quote::quote;
15
16fn 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]
28pub 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]
43pub 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]
67pub 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}