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 extern crate proc_macro;
7 
8 use proc_macro2::{Ident, TokenStream, TokenTree};
9 use quote::quote;
10 
extract_ident(input: proc_macro::TokenStream) -> Ident11 fn extract_ident(input: proc_macro::TokenStream) -> Ident {
12     let input = TokenStream::from(input);
13     let i = match input.into_iter().next().unwrap() {
14         TokenTree::Ident(i) => i,
15         _ => panic!("expected an ident"),
16     };
17     let name = i.to_string();
18     assert!(name.ends_with("_t"));
19     return i;
20 }
21 
22 #[proc_macro]
declare_own(input: proc_macro::TokenStream) -> proc_macro::TokenStream23 pub fn declare_own(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
24     let ty = extract_ident(input);
25     let name = ty.to_string();
26     let delete = quote::format_ident!("{}_delete", &name[..name.len() - 2]);
27 
28     (quote! {
29         #[no_mangle]
30         pub extern fn #delete(_: Box<#ty>) {}
31     })
32     .into()
33 }
34 
35 #[proc_macro]
declare_ty(input: proc_macro::TokenStream) -> proc_macro::TokenStream36 pub fn declare_ty(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
37     let ty = extract_ident(input);
38     let name = ty.to_string();
39     let copy = quote::format_ident!("{}_copy", &name[..name.len() - 2]);
40 
41     (quote! {
42         wasmtime_c_api_macros::declare_own!(#ty);
43 
44         #[no_mangle]
45         pub extern fn #copy(src: &#ty) -> Box<#ty> {
46             Box::new(src.clone())
47         }
48     })
49     .into()
50 }
51 
52 #[proc_macro]
declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream53 pub fn declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
54     let ty = extract_ident(input);
55     let name = ty.to_string();
56     let prefix = &name[..name.len() - 2];
57     let copy = quote::format_ident!("{}_copy", prefix);
58     let same = quote::format_ident!("{}_same", prefix);
59     let get_host_info = quote::format_ident!("{}_get_host_info", prefix);
60     let set_host_info = quote::format_ident!("{}_set_host_info", prefix);
61     let set_host_info_final = quote::format_ident!("{}_set_host_info_with_finalizer", prefix);
62     let as_ref = quote::format_ident!("{}_as_ref", prefix);
63     let as_ref_const = quote::format_ident!("{}_as_ref_const", prefix);
64 
65     (quote! {
66         wasmtime_c_api_macros::declare_own!(#ty);
67 
68         #[no_mangle]
69         pub extern fn #copy(src: &#ty) -> Box<#ty> {
70             Box::new(src.clone())
71         }
72 
73         #[no_mangle]
74         pub extern fn #same(a: &#ty, b: &#ty) -> bool {
75             a.externref().ptr_eq(&b.externref())
76         }
77 
78         #[no_mangle]
79         pub extern fn #get_host_info(a: &#ty) -> *mut std::os::raw::c_void {
80             crate::r#ref::get_host_info(&a.externref())
81         }
82 
83         #[no_mangle]
84         pub extern fn #set_host_info(a: &#ty, info: *mut std::os::raw::c_void) {
85             crate::r#ref::set_host_info(&a.externref(), info, None)
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             crate::r#ref::set_host_info(&a.externref(), info, finalizer)
95         }
96 
97         #[no_mangle]
98         pub extern fn #as_ref(a: &#ty) -> Box<crate::wasm_ref_t> {
99             let r = Some(a.externref());
100             Box::new(crate::wasm_ref_t { r })
101         }
102 
103         #[no_mangle]
104         pub extern fn #as_ref_const(a: &#ty) -> Box<crate::wasm_ref_t> {
105             #as_ref(a)
106         }
107 
108         // TODO: implement `wasm_ref_as_#name#`
109         // TODO: implement `wasm_ref_as_#name#_const`
110     })
111     .into()
112 }
113