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