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 wasm_extern_vec_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).as_slice(),
52         &mut instance,
53         &mut trap,
54     );
55     match err {
56         Some(err) => {
57             assert!(trap.is_null());
58             assert!(instance.is_null());
59             if let Some(result) = result {
60                 *result = Box::into_raw(err.to_trap());
61             }
62             None
63         }
64         None => {
65             if instance.is_null() {
66                 assert!(!trap.is_null());
67                 if let Some(result) = result {
68                     *result = trap;
69                 } else {
70                     drop(Box::from_raw(trap))
71                 }
72                 None
73             } else {
74                 assert!(trap.is_null());
75                 Some(Box::from_raw(instance))
76             }
77         }
78     }
79 }
80 
81 #[no_mangle]
82 pub unsafe extern "C" fn wasmtime_instance_new(
83     store: &wasm_store_t,
84     module: &wasm_module_t,
85     imports: *const wasm_extern_vec_t,
86     instance_ptr: &mut *mut wasm_instance_t,
87     trap_ptr: &mut *mut wasm_trap_t,
88 ) -> Option<Box<wasmtime_error_t>> {
89     _wasmtime_instance_new(store, module, (*imports).as_slice(), instance_ptr, trap_ptr)
90 }
91 
92 fn _wasmtime_instance_new(
93     store: &wasm_store_t,
94     module: &wasm_module_t,
95     imports: &[Option<Box<wasm_extern_t>>],
96     instance_ptr: &mut *mut wasm_instance_t,
97     trap_ptr: &mut *mut wasm_trap_t,
98 ) -> Option<Box<wasmtime_error_t>> {
99     let store = &store.store;
100     let imports = imports
101         .iter()
102         .filter_map(|import| match import {
103             Some(i) => Some(i.which.clone()),
104             None => None,
105         })
106         .collect::<Vec<_>>();
107     handle_instantiate(
108         Instance::new(store, module.module(), &imports),
109         instance_ptr,
110         trap_ptr,
111     )
112 }
113 
114 pub fn handle_instantiate(
115     instance: Result<Instance>,
116     instance_ptr: &mut *mut wasm_instance_t,
117     trap_ptr: &mut *mut wasm_trap_t,
118 ) -> Option<Box<wasmtime_error_t>> {
119     fn write<T>(ptr: &mut *mut T, val: T) {
120         *ptr = Box::into_raw(Box::new(val))
121     }
122 
123     match instance {
124         Ok(instance) => {
125             write(instance_ptr, wasm_instance_t::new(instance));
126             None
127         }
128         Err(e) => match e.downcast::<Trap>() {
129             Ok(trap) => {
130                 write(trap_ptr, wasm_trap_t::new(trap));
131                 None
132             }
133             Err(e) => Some(Box::new(e.into())),
134         },
135     }
136 }
137 
138 #[no_mangle]
139 pub extern "C" fn wasm_instance_as_extern(m: &wasm_instance_t) -> &wasm_extern_t {
140     &m.ext
141 }
142 
143 #[no_mangle]
144 pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) {
145     out.set_buffer(
146         instance
147             .instance()
148             .exports()
149             .map(|e| {
150                 Some(Box::new(wasm_extern_t {
151                     which: e.into_extern(),
152                 }))
153             })
154             .collect(),
155     );
156 }
157 
158 #[no_mangle]
159 pub extern "C" fn wasm_instance_type(f: &wasm_instance_t) -> Box<wasm_instancetype_t> {
160     Box::new(wasm_instancetype_t::new(f.instance().ty()))
161 }
162