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