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