1 use crate::{ 2 WasmtimeStoreContextMut, WasmtimeStoreData, wasm_engine_t, wasmtime_component_func_type_t, 3 wasmtime_component_resource_type_t, wasmtime_error_t, wasmtime_module_t, 4 }; 5 use std::ffi::c_void; 6 use wasmtime::component::{Instance, Linker, LinkerInstance, Val}; 7 8 use super::{wasmtime_component_t, wasmtime_component_val_t}; 9 10 #[repr(transparent)] 11 pub struct wasmtime_component_linker_t { 12 pub(crate) linker: Linker<WasmtimeStoreData>, 13 } 14 15 #[repr(transparent)] 16 pub struct wasmtime_component_linker_instance_t<'a> { 17 pub(crate) linker_instance: LinkerInstance<'a, WasmtimeStoreData>, 18 } 19 20 #[unsafe(no_mangle)] 21 pub extern "C" fn wasmtime_component_linker_new( 22 engine: &wasm_engine_t, 23 ) -> Box<wasmtime_component_linker_t> { 24 Box::new(wasmtime_component_linker_t { 25 linker: Linker::new(&engine.engine), 26 }) 27 } 28 29 #[unsafe(no_mangle)] 30 pub extern "C" fn wasmtime_component_linker_allow_shadowing( 31 linker: &mut wasmtime_component_linker_t, 32 allow: bool, 33 ) { 34 linker.linker.allow_shadowing(allow); 35 } 36 37 #[unsafe(no_mangle)] 38 pub extern "C" fn wasmtime_component_linker_root( 39 linker: &mut wasmtime_component_linker_t, 40 ) -> Box<wasmtime_component_linker_instance_t<'_>> { 41 Box::new(wasmtime_component_linker_instance_t { 42 linker_instance: linker.linker.root(), 43 }) 44 } 45 46 #[unsafe(no_mangle)] 47 pub extern "C" fn wasmtime_component_linker_instantiate( 48 linker: &wasmtime_component_linker_t, 49 context: WasmtimeStoreContextMut<'_>, 50 component: &wasmtime_component_t, 51 instance_out: &mut Instance, 52 ) -> Option<Box<wasmtime_error_t>> { 53 let result = linker.linker.instantiate(context, &component.component); 54 crate::handle_result(result, |instance| *instance_out = instance) 55 } 56 57 #[unsafe(no_mangle)] 58 pub extern "C" fn wasmtime_component_linker_delete(_linker: Box<wasmtime_component_linker_t>) {} 59 60 #[unsafe(no_mangle)] 61 pub unsafe extern "C" fn wasmtime_component_linker_instance_add_instance<'a>( 62 linker_instance: &'a mut wasmtime_component_linker_instance_t<'a>, 63 name: *const u8, 64 name_len: usize, 65 linker_instance_out: &mut *mut wasmtime_component_linker_instance_t<'a>, 66 ) -> Option<Box<wasmtime_error_t>> { 67 let name = unsafe { std::slice::from_raw_parts(name, name_len) }; 68 let Ok(name) = std::str::from_utf8(name) else { 69 return crate::bad_utf8(); 70 }; 71 72 let result = linker_instance.linker_instance.instance(&name); 73 crate::handle_result(result, |linker_instance| { 74 *linker_instance_out = Box::into_raw(Box::new(wasmtime_component_linker_instance_t { 75 linker_instance, 76 })); 77 }) 78 } 79 80 #[unsafe(no_mangle)] 81 pub unsafe extern "C" fn wasmtime_component_linker_instance_add_module( 82 linker_instance: &mut wasmtime_component_linker_instance_t, 83 name: *const u8, 84 name_len: usize, 85 module: &wasmtime_module_t, 86 ) -> Option<Box<wasmtime_error_t>> { 87 let name = unsafe { std::slice::from_raw_parts(name, name_len) }; 88 let Ok(name) = std::str::from_utf8(name) else { 89 return crate::bad_utf8(); 90 }; 91 92 let result = linker_instance 93 .linker_instance 94 .module(&name, &module.module); 95 96 crate::handle_result(result, |_| ()) 97 } 98 99 pub type wasmtime_component_func_callback_t = extern "C" fn( 100 *mut c_void, 101 WasmtimeStoreContextMut<'_>, 102 &wasmtime_component_func_type_t, 103 *mut wasmtime_component_val_t, 104 usize, 105 *mut wasmtime_component_val_t, 106 usize, 107 ) -> Option<Box<wasmtime_error_t>>; 108 109 #[unsafe(no_mangle)] 110 pub unsafe extern "C" fn wasmtime_component_linker_instance_add_func( 111 linker_instance: &mut wasmtime_component_linker_instance_t, 112 name: *const u8, 113 name_len: usize, 114 callback: wasmtime_component_func_callback_t, 115 data: *mut c_void, 116 finalizer: Option<extern "C" fn(*mut c_void)>, 117 ) -> Option<Box<wasmtime_error_t>> { 118 let name = unsafe { std::slice::from_raw_parts(name, name_len) }; 119 let Ok(name) = std::str::from_utf8(name) else { 120 return crate::bad_utf8(); 121 }; 122 123 let foreign = crate::ForeignData { data, finalizer }; 124 125 let result = linker_instance 126 .linker_instance 127 .func_new(&name, move |ctx, ty, args, rets| { 128 let _ = &foreign; 129 130 let mut args = args 131 .iter() 132 .map(|x| wasmtime_component_val_t::from(x)) 133 .collect::<Vec<_>>(); 134 135 let mut c_rets = vec![wasmtime_component_val_t::Bool(false); rets.len()]; 136 137 let res = callback( 138 foreign.data, 139 ctx, 140 &ty.into(), 141 args.as_mut_ptr(), 142 args.len(), 143 c_rets.as_mut_ptr(), 144 c_rets.len(), 145 ); 146 147 if let Some(res) = res { 148 return Err((*res).into()); 149 } 150 151 for (rust_val, c_val) in std::iter::zip(rets, c_rets) { 152 *rust_val = Val::from(&c_val); 153 } 154 155 Ok(()) 156 }); 157 158 crate::handle_result(result, |_| ()) 159 } 160 161 #[unsafe(no_mangle)] 162 #[cfg(feature = "wasi")] 163 pub unsafe extern "C" fn wasmtime_component_linker_add_wasip2( 164 linker: &mut wasmtime_component_linker_t, 165 ) -> Option<Box<wasmtime_error_t>> { 166 let result = wasmtime_wasi::p2::add_to_linker_sync(&mut linker.linker); 167 crate::handle_result(result, |_| ()) 168 } 169 170 #[unsafe(no_mangle)] 171 pub unsafe extern "C" fn wasmtime_component_linker_define_unknown_imports_as_traps( 172 linker: &mut wasmtime_component_linker_t, 173 component: &wasmtime_component_t, 174 ) -> Option<Box<wasmtime_error_t>> { 175 let result = linker 176 .linker 177 .define_unknown_imports_as_traps(&component.component); 178 crate::handle_result(result, |_| ()) 179 } 180 181 pub type wasmtime_component_resource_destructor_t = 182 extern "C" fn(*mut c_void, WasmtimeStoreContextMut<'_>, u32) -> Option<Box<wasmtime_error_t>>; 183 184 #[unsafe(no_mangle)] 185 pub unsafe extern "C" fn wasmtime_component_linker_instance_add_resource( 186 linker_instance: &mut wasmtime_component_linker_instance_t, 187 name: *const u8, 188 name_len: usize, 189 ty: &wasmtime_component_resource_type_t, 190 callback: wasmtime_component_resource_destructor_t, 191 data: *mut c_void, 192 finalizer: Option<extern "C" fn(*mut c_void)>, 193 ) -> Option<Box<wasmtime_error_t>> { 194 let name = unsafe { std::slice::from_raw_parts(name, name_len) }; 195 let Ok(name) = std::str::from_utf8(name) else { 196 return crate::bad_utf8(); 197 }; 198 199 let foreign = crate::ForeignData { data, finalizer }; 200 201 let result = linker_instance 202 .linker_instance 203 .resource(name, ty.ty, move |ctx, rep| { 204 let _ = &foreign; 205 if let Some(res) = callback(foreign.data, ctx, rep) { 206 return Err((*res).into()); 207 } 208 Ok(()) 209 }); 210 211 crate::handle_result(result, |_| ()) 212 } 213 214 #[unsafe(no_mangle)] 215 pub unsafe extern "C" fn wasmtime_component_linker_instance_delete( 216 _linker_instance: Box<wasmtime_component_linker_instance_t>, 217 ) { 218 } 219