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 use proc_macro2::{Ident, TokenStream, TokenTree};
7 use quote::quote;
8 
9 fn 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]
21 pub 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 
26     (quote! {
27         #[no_mangle]
28         pub extern fn #delete(_: Box<#ty>) {}
29     })
30     .into()
31 }
32 
33 #[proc_macro]
34 pub fn declare_ty(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
35     let ty = extract_ident(input);
36     let name = ty.to_string();
37     let copy = quote::format_ident!("{}_copy", &name[..name.len() - 2]);
38 
39     (quote! {
40         wasmtime_c_api_macros::declare_own!(#ty);
41 
42         #[no_mangle]
43         pub extern fn #copy(src: &#ty) -> Box<#ty> {
44             Box::new(src.clone())
45         }
46     })
47     .into()
48 }
49 
50 #[proc_macro]
51 pub fn declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
52     let ty = extract_ident(input);
53     let name = ty.to_string();
54     let prefix = &name[..name.len() - 2];
55     let copy = quote::format_ident!("{}_copy", prefix);
56     let same = quote::format_ident!("{}_same", prefix);
57     let get_host_info = quote::format_ident!("{}_get_host_info", prefix);
58     let set_host_info = quote::format_ident!("{}_set_host_info", prefix);
59     let set_host_info_final = quote::format_ident!("{}_set_host_info_with_finalizer", prefix);
60     let as_ref = quote::format_ident!("{}_as_ref", prefix);
61     let as_ref_const = quote::format_ident!("{}_as_ref_const", prefix);
62 
63     (quote! {
64         wasmtime_c_api_macros::declare_own!(#ty);
65 
66         #[no_mangle]
67         pub extern fn #copy(src: &#ty) -> Box<#ty> {
68             Box::new(src.clone())
69         }
70 
71         #[no_mangle]
72         pub extern fn #same(_a: &#ty, _b: &#ty) -> bool {
73             eprintln!("`{}` is not implemented", stringify!(#same));
74             std::process::abort();
75         }
76 
77         #[no_mangle]
78         pub extern fn #get_host_info(a: &#ty) -> *mut std::os::raw::c_void {
79             std::ptr::null_mut()
80         }
81 
82         #[no_mangle]
83         pub extern fn #set_host_info(a: &#ty, info: *mut std::os::raw::c_void) {
84             eprintln!("`{}` is not implemented", stringify!(#set_host_info));
85             std::process::abort();
86         }
87 
88         #[no_mangle]
89         pub extern fn #set_host_info_final(
90             a: &#ty,
91             info: *mut std::os::raw::c_void,
92             finalizer: Option<extern "C" fn(*mut std::os::raw::c_void)>,
93         ) {
94             eprintln!("`{}` is not implemented", stringify!(#set_host_info_final));
95             std::process::abort();
96         }
97 
98         #[no_mangle]
99         pub extern fn #as_ref(a: &#ty) -> Box<crate::wasm_ref_t> {
100             eprintln!("`{}` is not implemented", stringify!(#as_ref));
101             std::process::abort();
102         }
103 
104         #[no_mangle]
105         pub extern fn #as_ref_const(a: &#ty) -> Box<crate::wasm_ref_t> {
106             eprintln!("`{}` is not implemented", stringify!(#as_ref_const));
107             std::process::abort();
108         }
109 
110         // TODO: implement `wasm_ref_as_#name#`
111         // TODO: implement `wasm_ref_as_#name#_const`
112     })
113     .into()
114 }
115