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