1 use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t};
2 use crate::{wasm_instancetype_t, wasm_store_t, wasmtime_error_t};
3 use anyhow::Result;
4 use std::ptr;
5 use wasmtime::{Extern, Instance, Trap};
6 
7 #[derive(Clone)]
8 #[repr(transparent)]
9 pub struct wasm_instance_t {
10     ext: wasm_extern_t,
11 }
12 
13 wasmtime_c_api_macros::declare_ref!(wasm_instance_t);
14 
15 impl wasm_instance_t {
16     pub(crate) fn new(instance: Instance) -> wasm_instance_t {
17         wasm_instance_t {
18             ext: wasm_extern_t {
19                 which: instance.into(),
20             },
21         }
22     }
23 
24     pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_instance_t> {
25         match &e.which {
26             Extern::Instance(_) => Some(unsafe { &*(e as *const _ as *const _) }),
27             _ => None,
28         }
29     }
30 
31     pub(crate) fn instance(&self) -> &Instance {
32         match &self.ext.which {
33             Extern::Instance(i) => i,
34             _ => unreachable!(),
35         }
36     }
37 }
38 
39 #[no_mangle]
40 pub unsafe extern "C" fn wasm_instance_new(
41     store: &wasm_store_t,
42     wasm_module: &wasm_module_t,
43     imports: *const Box<wasm_extern_t>,
44     result: Option<&mut *mut wasm_trap_t>,
45 ) -> Option<Box<wasm_instance_t>> {
46     let mut instance = ptr::null_mut();
47     let mut trap = ptr::null_mut();
48     let err = wasmtime_instance_new(
49         store,
50         wasm_module,
51         imports,
52         wasm_module.module().imports().len(),
53         &mut instance,
54         &mut trap,
55     );
56     match err {
57         Some(err) => {
58             assert!(trap.is_null());
59             assert!(instance.is_null());
60             if let Some(result) = result {
61                 *result = Box::into_raw(err.to_trap());
62             }
63             None
64         }
65         None => {
66             if instance.is_null() {
67                 assert!(!trap.is_null());
68                 if let Some(result) = result {
69                     *result = trap;
70                 } else {
71                     drop(Box::from_raw(trap))
72                 }
73                 None
74             } else {
75                 assert!(trap.is_null());
76                 Some(Box::from_raw(instance))
77             }
78         }
79     }
80 }
81 
82 #[no_mangle]
83 pub unsafe extern "C" fn wasmtime_instance_new(
84     store: &wasm_store_t,
85     module: &wasm_module_t,
86     imports: *const Box<wasm_extern_t>,
87     num_imports: usize,
88     instance_ptr: &mut *mut wasm_instance_t,
89     trap_ptr: &mut *mut wasm_trap_t,
90 ) -> Option<Box<wasmtime_error_t>> {
91     _wasmtime_instance_new(
92         store,
93         module,
94         std::slice::from_raw_parts(imports, num_imports),
95         instance_ptr,
96         trap_ptr,
97     )
98 }
99 
100 fn _wasmtime_instance_new(
101     store: &wasm_store_t,
102     module: &wasm_module_t,
103     imports: &[Box<wasm_extern_t>],
104     instance_ptr: &mut *mut wasm_instance_t,
105     trap_ptr: &mut *mut wasm_trap_t,
106 ) -> Option<Box<wasmtime_error_t>> {
107     let store = &store.store;
108     let imports = imports
109         .iter()
110         .map(|import| import.which.clone())
111         .collect::<Vec<_>>();
112     handle_instantiate(
113         Instance::new(store, module.module(), &imports),
114         instance_ptr,
115         trap_ptr,
116     )
117 }
118 
119 pub fn handle_instantiate(
120     instance: Result<Instance>,
121     instance_ptr: &mut *mut wasm_instance_t,
122     trap_ptr: &mut *mut wasm_trap_t,
123 ) -> Option<Box<wasmtime_error_t>> {
124     fn write<T>(ptr: &mut *mut T, val: T) {
125         *ptr = Box::into_raw(Box::new(val))
126     }
127 
128     match instance {
129         Ok(instance) => {
130             write(instance_ptr, wasm_instance_t::new(instance));
131             None
132         }
133         Err(e) => match e.downcast::<Trap>() {
134             Ok(trap) => {
135                 write(trap_ptr, wasm_trap_t::new(trap));
136                 None
137             }
138             Err(e) => Some(Box::new(e.into())),
139         },
140     }
141 }
142 
143 #[no_mangle]
144 pub extern "C" fn wasm_instance_as_extern(m: &wasm_instance_t) -> &wasm_extern_t {
145     &m.ext
146 }
147 
148 #[no_mangle]
149 pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) {
150     out.set_buffer(
151         instance
152             .instance()
153             .exports()
154             .map(|e| {
155                 Some(Box::new(wasm_extern_t {
156                     which: e.into_extern(),
157                 }))
158             })
159             .collect(),
160     );
161 }
162 
163 #[no_mangle]
164 pub extern "C" fn wasm_instance_type(f: &wasm_instance_t) -> Box<wasm_instancetype_t> {
165     Box::new(wasm_instancetype_t::new(f.instance().ty()))
166 }
167