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