1 use crate::{ 2 CExternType, handle_result, wasm_byte_vec_t, wasm_engine_t, wasm_exporttype_t, 3 wasm_exporttype_vec_t, wasm_importtype_t, wasm_importtype_vec_t, wasm_store_t, 4 wasmtime_error_t, 5 }; 6 use anyhow::Context; 7 use std::ffi::CStr; 8 use std::os::raw::c_char; 9 use wasmtime::{Engine, Module}; 10 11 #[derive(Clone)] 12 pub struct wasm_module_t { 13 pub(crate) module: Module, 14 } 15 16 wasmtime_c_api_macros::declare_ref!(wasm_module_t); 17 18 impl wasm_module_t { 19 pub(crate) fn new(module: Module) -> wasm_module_t { 20 wasm_module_t { module } 21 } 22 } 23 24 #[repr(C)] 25 #[derive(Clone)] 26 pub struct wasm_shared_module_t { 27 module: Module, 28 } 29 30 wasmtime_c_api_macros::declare_own!(wasm_shared_module_t); 31 32 #[unsafe(no_mangle)] 33 #[cfg(any(feature = "cranelift", feature = "winch"))] 34 pub unsafe extern "C" fn wasm_module_new( 35 store: &mut wasm_store_t, 36 binary: &wasm_byte_vec_t, 37 ) -> Option<Box<wasm_module_t>> { 38 match Module::from_binary(store.store.context().engine(), binary.as_slice()) { 39 Ok(module) => Some(Box::new(wasm_module_t::new(module))), 40 Err(_) => None, 41 } 42 } 43 44 #[unsafe(no_mangle)] 45 #[cfg(any(feature = "cranelift", feature = "winch"))] 46 pub unsafe extern "C" fn wasm_module_validate( 47 store: &mut wasm_store_t, 48 binary: &wasm_byte_vec_t, 49 ) -> bool { 50 Module::validate(store.store.context().engine(), binary.as_slice()).is_ok() 51 } 52 53 fn fill_exports(module: &Module, out: &mut wasm_exporttype_vec_t) { 54 let exports = module 55 .exports() 56 .map(|e| { 57 Some(Box::new(wasm_exporttype_t::new( 58 e.name().to_owned(), 59 CExternType::new(e.ty()), 60 ))) 61 }) 62 .collect::<Vec<_>>(); 63 out.set_buffer(exports); 64 } 65 66 fn fill_imports(module: &Module, out: &mut wasm_importtype_vec_t) { 67 let imports = module 68 .imports() 69 .map(|i| { 70 Some(Box::new(wasm_importtype_t::new( 71 i.module().to_owned(), 72 i.name().to_owned(), 73 CExternType::new(i.ty()), 74 ))) 75 }) 76 .collect::<Vec<_>>(); 77 out.set_buffer(imports); 78 } 79 80 #[unsafe(no_mangle)] 81 pub extern "C" fn wasm_module_exports(module: &wasm_module_t, out: &mut wasm_exporttype_vec_t) { 82 fill_exports(&module.module, out); 83 } 84 85 #[unsafe(no_mangle)] 86 pub extern "C" fn wasm_module_imports(module: &wasm_module_t, out: &mut wasm_importtype_vec_t) { 87 fill_imports(&module.module, out); 88 } 89 90 #[unsafe(no_mangle)] 91 pub extern "C" fn wasm_module_share(module: &wasm_module_t) -> Box<wasm_shared_module_t> { 92 Box::new(wasm_shared_module_t { 93 module: module.module.clone(), 94 }) 95 } 96 97 #[unsafe(no_mangle)] 98 pub unsafe extern "C" fn wasm_module_obtain( 99 store: &mut wasm_store_t, 100 shared_module: &wasm_shared_module_t, 101 ) -> Option<Box<wasm_module_t>> { 102 let module = shared_module.module.clone(); 103 if Engine::same(store.store.context().engine(), module.engine()) { 104 Some(Box::new(wasm_module_t::new(module))) 105 } else { 106 None 107 } 108 } 109 110 #[unsafe(no_mangle)] 111 #[cfg(any(feature = "cranelift", feature = "winch"))] 112 pub extern "C" fn wasm_module_serialize(module: &wasm_module_t, ret: &mut wasm_byte_vec_t) { 113 if let Ok(buf) = module.module.serialize() { 114 ret.set_buffer(buf); 115 } 116 } 117 118 #[unsafe(no_mangle)] 119 pub unsafe extern "C" fn wasm_module_deserialize( 120 store: &mut wasm_store_t, 121 binary: &wasm_byte_vec_t, 122 ) -> Option<Box<wasm_module_t>> { 123 match Module::deserialize(store.store.context().engine(), binary.as_slice()) { 124 Ok(module) => Some(Box::new(wasm_module_t::new(module))), 125 Err(_) => None, 126 } 127 } 128 129 #[derive(Clone)] 130 pub struct wasmtime_module_t { 131 pub(crate) module: Module, 132 } 133 134 wasmtime_c_api_macros::declare_own!(wasmtime_module_t); 135 136 #[unsafe(no_mangle)] 137 #[cfg(any(feature = "cranelift", feature = "winch"))] 138 pub unsafe extern "C" fn wasmtime_module_new( 139 engine: &wasm_engine_t, 140 wasm: *const u8, 141 len: usize, 142 out: &mut *mut wasmtime_module_t, 143 ) -> Option<Box<wasmtime_error_t>> { 144 handle_result( 145 Module::from_binary(&engine.engine, crate::slice_from_raw_parts(wasm, len)), 146 |module| { 147 *out = Box::into_raw(Box::new(wasmtime_module_t { module })); 148 }, 149 ) 150 } 151 152 #[unsafe(no_mangle)] 153 pub extern "C" fn wasmtime_module_clone(module: &wasmtime_module_t) -> Box<wasmtime_module_t> { 154 Box::new(module.clone()) 155 } 156 157 #[unsafe(no_mangle)] 158 pub extern "C" fn wasmtime_module_exports( 159 module: &wasmtime_module_t, 160 out: &mut wasm_exporttype_vec_t, 161 ) { 162 fill_exports(&module.module, out); 163 } 164 165 #[unsafe(no_mangle)] 166 pub extern "C" fn wasmtime_module_imports( 167 module: &wasmtime_module_t, 168 out: &mut wasm_importtype_vec_t, 169 ) { 170 fill_imports(&module.module, out); 171 } 172 173 #[unsafe(no_mangle)] 174 #[cfg(any(feature = "cranelift", feature = "winch"))] 175 pub unsafe extern "C" fn wasmtime_module_validate( 176 engine: &wasm_engine_t, 177 wasm: *const u8, 178 len: usize, 179 ) -> Option<Box<wasmtime_error_t>> { 180 let binary = crate::slice_from_raw_parts(wasm, len); 181 handle_result(Module::validate(&engine.engine, binary), |()| {}) 182 } 183 184 #[unsafe(no_mangle)] 185 #[cfg(any(feature = "cranelift", feature = "winch"))] 186 pub extern "C" fn wasmtime_module_serialize( 187 module: &wasmtime_module_t, 188 ret: &mut wasm_byte_vec_t, 189 ) -> Option<Box<wasmtime_error_t>> { 190 handle_result(module.module.serialize(), |buf| ret.set_buffer(buf)) 191 } 192 193 #[unsafe(no_mangle)] 194 pub extern "C" fn wasmtime_module_image_range( 195 module: &wasmtime_module_t, 196 start: &mut *const u8, 197 end: &mut *const u8, 198 ) { 199 let range = module.module.image_range(); 200 *start = range.start; 201 *end = range.end; 202 } 203 204 #[unsafe(no_mangle)] 205 pub unsafe extern "C" fn wasmtime_module_deserialize( 206 engine: &wasm_engine_t, 207 bytes: *const u8, 208 len: usize, 209 out: &mut *mut wasmtime_module_t, 210 ) -> Option<Box<wasmtime_error_t>> { 211 let bytes = crate::slice_from_raw_parts(bytes, len); 212 handle_result(Module::deserialize(&engine.engine, bytes), |module| { 213 *out = Box::into_raw(Box::new(wasmtime_module_t { module })); 214 }) 215 } 216 217 #[unsafe(no_mangle)] 218 pub unsafe extern "C" fn wasmtime_module_deserialize_file( 219 engine: &wasm_engine_t, 220 path: *const c_char, 221 out: &mut *mut wasmtime_module_t, 222 ) -> Option<Box<wasmtime_error_t>> { 223 let path = CStr::from_ptr(path); 224 let result = path 225 .to_str() 226 .context("input path is not valid utf-8") 227 .and_then(|path| Module::deserialize_file(&engine.engine, path)); 228 handle_result(result, |module| { 229 *out = Box::into_raw(Box::new(wasmtime_module_t { module })); 230 }) 231 } 232