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