1 use std::ffi::{CStr, c_char}; 2 3 use anyhow::Context; 4 use wasmtime::component::{Component, ComponentExportIndex}; 5 6 use crate::{wasm_byte_vec_t, wasm_config_t, wasm_engine_t, wasmtime_error_t}; 7 8 #[unsafe(no_mangle)] 9 pub unsafe extern "C" fn wasmtime_config_wasm_component_model_set( 10 c: &mut wasm_config_t, 11 enable: bool, 12 ) { 13 c.config.wasm_component_model(enable); 14 } 15 16 #[derive(Clone)] 17 #[repr(transparent)] 18 pub struct wasmtime_component_t { 19 pub(crate) component: Component, 20 } 21 22 #[unsafe(no_mangle)] 23 #[cfg(any(feature = "cranelift", feature = "winch"))] 24 pub unsafe extern "C" fn wasmtime_component_new( 25 engine: &wasm_engine_t, 26 buf: *const u8, 27 len: usize, 28 component_out: &mut *mut wasmtime_component_t, 29 ) -> Option<Box<wasmtime_error_t>> { 30 let bytes = unsafe { crate::slice_from_raw_parts(buf, len) }; 31 crate::handle_result(Component::new(&engine.engine, bytes), |component| { 32 *component_out = Box::into_raw(Box::new(wasmtime_component_t { component })); 33 }) 34 } 35 36 #[unsafe(no_mangle)] 37 #[cfg(any(feature = "cranelift", feature = "winch"))] 38 pub unsafe extern "C" fn wasmtime_component_serialize( 39 component: &wasmtime_component_t, 40 ret: &mut wasm_byte_vec_t, 41 ) -> Option<Box<wasmtime_error_t>> { 42 crate::handle_result(component.component.serialize(), |buffer| { 43 ret.set_buffer(buffer); 44 }) 45 } 46 47 #[unsafe(no_mangle)] 48 pub unsafe extern "C" fn wasmtime_component_deserialize( 49 engine: &wasm_engine_t, 50 buf: *const u8, 51 len: usize, 52 component_out: &mut *mut wasmtime_component_t, 53 ) -> Option<Box<wasmtime_error_t>> { 54 let binary = unsafe { crate::slice_from_raw_parts(buf, len) }; 55 crate::handle_result( 56 unsafe { Component::deserialize(&engine.engine, binary) }, 57 |component| { 58 *component_out = Box::into_raw(Box::new(wasmtime_component_t { component })); 59 }, 60 ) 61 } 62 63 #[unsafe(no_mangle)] 64 pub unsafe extern "C" fn wasmtime_component_deserialize_file( 65 engine: &wasm_engine_t, 66 path: *const c_char, 67 component_out: &mut *mut wasmtime_component_t, 68 ) -> Option<Box<wasmtime_error_t>> { 69 let path = unsafe { CStr::from_ptr(path) }; 70 let result = path 71 .to_str() 72 .context("input path is not valid utf-8") 73 .and_then(|path| unsafe { Component::deserialize_file(&engine.engine, path) }); 74 crate::handle_result(result, |component| { 75 *component_out = Box::into_raw(Box::new(wasmtime_component_t { component })); 76 }) 77 } 78 79 #[unsafe(no_mangle)] 80 pub unsafe extern "C" fn wasmtime_component_clone( 81 component: &wasmtime_component_t, 82 ) -> Box<wasmtime_component_t> { 83 Box::new(component.clone()) 84 } 85 86 #[unsafe(no_mangle)] 87 pub unsafe extern "C" fn wasmtime_component_delete(_component: Box<wasmtime_component_t>) {} 88 89 #[repr(transparent)] 90 pub struct wasmtime_component_export_index_t { 91 pub(crate) export_index: ComponentExportIndex, 92 } 93 94 #[unsafe(no_mangle)] 95 pub unsafe extern "C" fn wasmtime_component_get_export_index( 96 component: &wasmtime_component_t, 97 instance_export_index: *const wasmtime_component_export_index_t, 98 name: *const u8, 99 name_len: usize, 100 ) -> Option<Box<wasmtime_component_export_index_t>> { 101 let name = unsafe { std::slice::from_raw_parts(name, name_len) }; 102 let Ok(name) = std::str::from_utf8(name) else { 103 return None; 104 }; 105 106 let instance_export_index = if instance_export_index.is_null() { 107 None 108 } else { 109 Some((*instance_export_index).export_index) 110 }; 111 112 component 113 .component 114 .get_export_index(instance_export_index.as_ref(), &name) 115 .map(|export_index| Box::new(wasmtime_component_export_index_t { export_index })) 116 } 117 118 #[unsafe(no_mangle)] 119 pub unsafe extern "C" fn wasmtime_component_export_index_delete( 120 _export_index: Box<wasmtime_component_export_index_t>, 121 ) { 122 } 123