1 use crate::{
2     wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_store_t, wasm_trap_t, wasmtime_error_t,
3     wasmtime_extern_t, wasmtime_module_t, WasmStoreRef, WasmtimeStoreContextMut, WasmtimeStoreData,
4 };
5 use std::mem::MaybeUninit;
6 use wasmtime::{Instance, InstancePre, Trap};
7 
8 #[derive(Clone)]
9 pub struct wasm_instance_t {
10     store: WasmStoreRef,
11     instance: Instance,
12 }
13 
14 wasmtime_c_api_macros::declare_ref!(wasm_instance_t);
15 
16 impl wasm_instance_t {
17     pub(crate) fn new(store: WasmStoreRef, instance: Instance) -> wasm_instance_t {
18         wasm_instance_t { store, instance }
19     }
20 }
21 
22 #[unsafe(no_mangle)]
23 pub unsafe extern "C" fn wasm_instance_new(
24     store: &mut wasm_store_t,
25     wasm_module: &wasm_module_t,
26     imports: *const wasm_extern_vec_t,
27     result: Option<&mut *mut wasm_trap_t>,
28 ) -> Option<Box<wasm_instance_t>> {
29     let imports = (*imports)
30         .as_slice()
31         .iter()
32         .filter_map(|import| match import {
33             Some(i) => Some(i.which.clone()),
34             None => None,
35         })
36         .collect::<Vec<_>>();
37     match Instance::new(store.store.context_mut(), &wasm_module.module, &imports) {
38         Ok(instance) => Some(Box::new(wasm_instance_t::new(
39             store.store.clone(),
40             instance,
41         ))),
42         Err(e) => {
43             if let Some(ptr) = result {
44                 *ptr = Box::into_raw(Box::new(wasm_trap_t::new(e)));
45             }
46             None
47         }
48     }
49 }
50 
51 #[unsafe(no_mangle)]
52 pub unsafe extern "C" fn wasm_instance_exports(
53     instance: &mut wasm_instance_t,
54     out: &mut wasm_extern_vec_t,
55 ) {
56     let store = instance.store.clone();
57     out.set_buffer(
58         instance
59             .instance
60             .exports(instance.store.context_mut())
61             .map(|e| {
62                 Some(Box::new(wasm_extern_t {
63                     which: e.into_extern(),
64                     store: store.clone(),
65                 }))
66             })
67             .collect(),
68     );
69 }
70 
71 #[unsafe(no_mangle)]
72 pub unsafe extern "C" fn wasmtime_instance_new(
73     store: WasmtimeStoreContextMut<'_>,
74     module: &wasmtime_module_t,
75     imports: *const wasmtime_extern_t,
76     nimports: usize,
77     instance: &mut Instance,
78     trap_ptr: &mut *mut wasm_trap_t,
79 ) -> Option<Box<wasmtime_error_t>> {
80     let imports = crate::slice_from_raw_parts(imports, nimports)
81         .iter()
82         .map(|i| i.to_extern())
83         .collect::<Vec<_>>();
84     handle_instantiate(
85         Instance::new(store, &module.module, &imports),
86         instance,
87         trap_ptr,
88     )
89 }
90 
91 pub(crate) fn handle_instantiate(
92     instance: anyhow::Result<Instance>,
93     instance_ptr: &mut Instance,
94     trap_ptr: &mut *mut wasm_trap_t,
95 ) -> Option<Box<wasmtime_error_t>> {
96     match instance {
97         Ok(i) => {
98             *instance_ptr = i;
99             None
100         }
101         Err(e) => {
102             if e.is::<Trap>() {
103                 *trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(e)));
104                 None
105             } else {
106                 Some(Box::new(e.into()))
107             }
108         }
109     }
110 }
111 
112 #[unsafe(no_mangle)]
113 pub unsafe extern "C" fn wasmtime_instance_export_get(
114     store: WasmtimeStoreContextMut<'_>,
115     instance: &Instance,
116     name: *const u8,
117     name_len: usize,
118     item: &mut MaybeUninit<wasmtime_extern_t>,
119 ) -> bool {
120     let name = crate::slice_from_raw_parts(name, name_len);
121     let name = match std::str::from_utf8(name) {
122         Ok(name) => name,
123         Err(_) => return false,
124     };
125     match instance.get_export(store, name) {
126         Some(e) => {
127             crate::initialize(item, e.into());
128             true
129         }
130         None => false,
131     }
132 }
133 
134 #[unsafe(no_mangle)]
135 pub unsafe extern "C" fn wasmtime_instance_export_nth(
136     store: WasmtimeStoreContextMut<'_>,
137     instance: &Instance,
138     index: usize,
139     name_ptr: &mut *const u8,
140     name_len: &mut usize,
141     item: &mut MaybeUninit<wasmtime_extern_t>,
142 ) -> bool {
143     match instance.exports(store).nth(index) {
144         Some(e) => {
145             *name_ptr = e.name().as_ptr();
146             *name_len = e.name().len();
147             crate::initialize(item, e.into_extern().into());
148             true
149         }
150         None => false,
151     }
152 }
153 
154 #[repr(transparent)]
155 pub struct wasmtime_instance_pre_t {
156     pub(crate) underlying: InstancePre<WasmtimeStoreData>,
157 }
158 
159 #[unsafe(no_mangle)]
160 pub unsafe extern "C" fn wasmtime_instance_pre_delete(_instance_pre: Box<wasmtime_instance_pre_t>) {
161 }
162 
163 #[unsafe(no_mangle)]
164 pub unsafe extern "C" fn wasmtime_instance_pre_instantiate(
165     instance_pre: &wasmtime_instance_pre_t,
166     store: WasmtimeStoreContextMut<'_>,
167     instance_ptr: &mut Instance,
168     trap_ptr: &mut *mut wasm_trap_t,
169 ) -> Option<Box<wasmtime_error_t>> {
170     let result = instance_pre.underlying.instantiate(store);
171     handle_instantiate(result, instance_ptr, trap_ptr)
172 }
173 
174 #[unsafe(no_mangle)]
175 pub unsafe extern "C" fn wasmtime_instance_pre_module(
176     instance_pre: &wasmtime_instance_pre_t,
177 ) -> Box<wasmtime_module_t> {
178     let module = instance_pre.underlying.module().clone();
179     Box::new(wasmtime_module_t { module })
180 }
181