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 let docs = format!("Deletes the [`{name}`]."); 26 27 (quote! { 28 #[doc = #docs] 29 #[unsafe(no_mangle)] 30 pub extern fn #delete(_: Box<#ty>) {} 31 }) 32 .into() 33 } 34 35 #[proc_macro] 36 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 prefix = &name[..name.len() - 2]; 40 let copy = quote::format_ident!("{}_copy", &prefix); 41 let docs = format!( 42 "Creates a new [`{name}`] which matches the provided one.\n\n\ 43 The caller is responsible for deleting the returned value via [`{prefix}_delete`].\n\n\ 44 " 45 ); 46 47 (quote! { 48 wasmtime_c_api_macros::declare_own!(#ty); 49 50 #[doc = #docs] 51 #[unsafe(no_mangle)] 52 pub extern fn #copy(src: &#ty) -> Box<#ty> { 53 Box::new(src.clone()) 54 } 55 }) 56 .into() 57 } 58 59 #[proc_macro] 60 pub fn declare_ref(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 61 let ty = extract_ident(input); 62 let name = ty.to_string(); 63 let prefix = &name[..name.len() - 2]; 64 let same = quote::format_ident!("{}_same", prefix); 65 let same_docs = format!( 66 "Returns `true` if the given references are pointing to the same [`{name}`].\n\n\ 67 This is not yet supported and aborts the process upon use." 68 ); 69 let get_host_info = quote::format_ident!("{}_get_host_info", prefix); 70 let get_host_info_docs = format!( 71 "Returns the host information of the [`{name}`].\n\n\ 72 This is not yet supported and always returns `NULL`." 73 ); 74 let set_host_info = quote::format_ident!("{}_set_host_info", prefix); 75 let set_host_info_docs = format!( 76 "Sets the host information of the [`{name}`].\n\n\ 77 This is not yet supported and aborts the process upon use." 78 ); 79 let set_host_info_final = quote::format_ident!("{}_set_host_info_with_finalizer", prefix); 80 let set_host_info_final_docs = format!( 81 "Sets the host information finalizer of the [`{name}`].\n\n\ 82 This is not yet supported and aborts the process upon use." 83 ); 84 let as_ref = quote::format_ident!("{}_as_ref", prefix); 85 let as_ref_docs = format!( 86 "Returns the [`{name}`] as mutable reference.\n\n\ 87 This is not yet supported and aborts the process upon use." 88 ); 89 let as_ref_const = quote::format_ident!("{}_as_ref_const", prefix); 90 let as_ref_const_docs = format!( 91 "Returns the [`{name}`] as immutable reference.\n\n\ 92 This is not yet supported and aborts the process upon use." 93 ); 94 95 (quote! { 96 wasmtime_c_api_macros::declare_ty!(#ty); 97 98 #[doc = #same_docs] 99 #[unsafe(no_mangle)] 100 pub extern fn #same(_a: &#ty, _b: &#ty) -> bool { 101 eprintln!("`{}` is not implemented", stringify!(#same)); 102 std::process::abort(); 103 } 104 105 #[doc = #get_host_info_docs] 106 #[unsafe(no_mangle)] 107 pub extern fn #get_host_info(a: &#ty) -> *mut std::os::raw::c_void { 108 std::ptr::null_mut() 109 } 110 111 #[doc = #set_host_info_docs] 112 #[unsafe(no_mangle)] 113 pub extern fn #set_host_info(a: &#ty, info: *mut std::os::raw::c_void) { 114 eprintln!("`{}` is not implemented", stringify!(#set_host_info)); 115 std::process::abort(); 116 } 117 118 #[doc = #set_host_info_final_docs] 119 #[unsafe(no_mangle)] 120 pub extern fn #set_host_info_final( 121 a: &#ty, 122 info: *mut std::os::raw::c_void, 123 finalizer: Option<extern "C" fn(*mut std::os::raw::c_void)>, 124 ) { 125 eprintln!("`{}` is not implemented", stringify!(#set_host_info_final)); 126 std::process::abort(); 127 } 128 129 #[doc = #as_ref_docs] 130 #[unsafe(no_mangle)] 131 pub extern fn #as_ref(a: &#ty) -> Box<crate::wasm_ref_t> { 132 eprintln!("`{}` is not implemented", stringify!(#as_ref)); 133 std::process::abort(); 134 } 135 136 #[doc = #as_ref_const_docs] 137 #[unsafe(no_mangle)] 138 pub extern fn #as_ref_const(a: &#ty) -> Box<crate::wasm_ref_t> { 139 eprintln!("`{}` is not implemented", stringify!(#as_ref_const)); 140 std::process::abort(); 141 } 142 143 // TODO: implement `wasm_ref_as_#name#` 144 // TODO: implement `wasm_ref_as_#name#_const` 145 }) 146 .into() 147 } 148