1 use crate::{ 2 WasmtimeStoreContextMut, WasmtimeStoreData, wasm_engine_t, wasmtime_component_resource_type_t, 3 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 *const wasmtime_component_val_t, 103 usize, 104 *mut wasmtime_component_val_t, 105 usize, 106 ) -> Option<Box<wasmtime_error_t>>; 107 108 #[unsafe(no_mangle)] 109 pub unsafe extern "C" fn wasmtime_component_linker_instance_add_func( 110 linker_instance: &mut wasmtime_component_linker_instance_t, 111 name: *const u8, 112 name_len: usize, 113 callback: wasmtime_component_func_callback_t, 114 data: *mut c_void, 115 finalizer: Option<extern "C" fn(*mut c_void)>, 116 ) -> Option<Box<wasmtime_error_t>> { 117 let name = unsafe { std::slice::from_raw_parts(name, name_len) }; 118 let Ok(name) = std::str::from_utf8(name) else { 119 return crate::bad_utf8(); 120 }; 121 122 let foreign = crate::ForeignData { data, finalizer }; 123 124 let result = linker_instance 125 .linker_instance 126 .func_new(&name, move |ctx, _ty, args, rets| { 127 let _ = &foreign; 128 129 let args = args 130 .iter() 131 .map(|x| wasmtime_component_val_t::from(x)) 132 .collect::<Vec<_>>(); 133 134 let mut c_rets = vec![wasmtime_component_val_t::Bool(false); rets.len()]; 135 136 let res = callback( 137 foreign.data, 138 ctx, 139 args.as_ptr(), 140 args.len(), 141 c_rets.as_mut_ptr(), 142 c_rets.len(), 143 ); 144 145 if let Some(res) = res { 146 return Err((*res).into()); 147 } 148 149 for (rust_val, c_val) in std::iter::zip(rets, c_rets) { 150 *rust_val = Val::from(&c_val); 151 } 152 153 Ok(()) 154 }); 155 156 crate::handle_result(result, |_| ()) 157 } 158 159 #[unsafe(no_mangle)] 160 #[cfg(feature = "wasi")] 161 pub unsafe extern "C" fn wasmtime_component_linker_add_wasip2( 162 linker: &mut wasmtime_component_linker_t, 163 ) -> Option<Box<wasmtime_error_t>> { 164 let result = wasmtime_wasi::p2::add_to_linker_sync(&mut linker.linker); 165 crate::handle_result(result, |_| ()) 166 } 167 168 pub type wasmtime_component_resource_destructor_t = 169 extern "C" fn(*mut c_void, WasmtimeStoreContextMut<'_>, u32) -> Option<Box<wasmtime_error_t>>; 170 171 #[unsafe(no_mangle)] 172 pub unsafe extern "C" fn wasmtime_component_linker_instance_add_resource( 173 linker_instance: &mut wasmtime_component_linker_instance_t, 174 name: *const u8, 175 name_len: usize, 176 ty: &wasmtime_component_resource_type_t, 177 callback: wasmtime_component_resource_destructor_t, 178 data: *mut c_void, 179 finalizer: Option<extern "C" fn(*mut c_void)>, 180 ) -> Option<Box<wasmtime_error_t>> { 181 let name = unsafe { std::slice::from_raw_parts(name, name_len) }; 182 let Ok(name) = std::str::from_utf8(name) else { 183 return crate::bad_utf8(); 184 }; 185 186 let foreign = crate::ForeignData { data, finalizer }; 187 188 let result = linker_instance 189 .linker_instance 190 .resource(name, ty.ty, move |ctx, rep| { 191 let _ = &foreign; 192 if let Some(res) = callback(foreign.data, ctx, rep) { 193 return Err((*res).into()); 194 } 195 Ok(()) 196 }); 197 198 crate::handle_result(result, |_| ()) 199 } 200 201 #[unsafe(no_mangle)] 202 pub unsafe extern "C" fn wasmtime_component_linker_instance_delete( 203 _linker_instance: Box<wasmtime_component_linker_instance_t>, 204 ) { 205 } 206