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 16 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] 28 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] 43 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] 67 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