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