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