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