1use {
2 crate::{
3 const_expr::EvaluationContext,
4 data::{Data, UnguardedData},
5 elem::{Elem, UnguardedElem},
6 extern_val::{ExternVal, UnguardedExternVal},
7 func::{Func, UnguardedFunc},
8 global::{Global, UnguardedGlobal},
9 mem::{Mem, UnguardedMem},
10 store::{InternedFuncType, StoreId, UnguardedInternedFuncType},
11 table::{Table, UnguardedTable},
12 },
13 std::{
14 cell::OnceCell,
15 collections::{hash_map, HashMap},
16 sync::Arc,
17 },
18};
19
20#[derive(Clone, Debug)]
22pub struct Instance {
23 store_id: StoreId,
24 inner: Arc<OnceCell<InstanceInner>>,
25}
26
27impl Instance {
28 pub fn exported_val(&self, name: &str) -> Option<ExternVal> {
30 self.inner()
31 .exports
32 .get(name)
33 .map(|val| unsafe { ExternVal::from_unguarded(*val, self.store_id) })
34 }
35
36 pub fn exported_func(&self, name: &str) -> Option<Func> {
38 self.exported_val(name).and_then(|val| val.to_func())
39 }
40
41 pub fn exported_table(&self, name: &str) -> Option<Table> {
43 self.exported_val(name).and_then(|val| val.to_table())
44 }
45
46 pub fn exported_mem(&self, name: &str) -> Option<Mem> {
48 self.exported_val(name).and_then(|val| val.to_mem())
49 }
50
51 pub fn exported_global(&self, name: &str) -> Option<Global> {
53 self.exported_val(name).and_then(|val| val.to_global())
54 }
55
56 pub fn exports(&self) -> InstanceExports<'_> {
58 InstanceExports {
59 store_id: self.store_id,
60 iter: self.inner().exports.iter(),
61 }
62 }
63
64 pub(crate) fn uninited(store_id: StoreId) -> Instance {
66 Instance {
67 store_id,
68 inner: Arc::new(OnceCell::new()),
69 }
70 }
71
72 pub(crate) fn init(&self, initer: InstanceIniter) {
74 assert_eq!(initer.store_id, self.store_id);
75 self.inner
76 .set(InstanceInner {
77 types: initer.types.into(),
78 funcs: initer.funcs.into(),
79 tables: initer.tables.into(),
80 mems: initer.mems.into(),
81 globals: initer.globals.into(),
82 elems: initer.elems.into(),
83 datas: initer.datas.into(),
84 exports: initer.exports,
85 })
86 .expect("instance already initialized");
87 }
88
89 pub(crate) fn type_(&self, idx: u32) -> Option<InternedFuncType> {
91 self.inner()
92 .types
93 .get(idx as usize)
94 .map(|type_| unsafe { InternedFuncType::from_unguarded(*type_, self.store_id) })
95 }
96
97 pub(crate) fn func(&self, idx: u32) -> Option<Func> {
99 self.unguarded_func(idx)
100 .map(|func| unsafe { Func::from_unguarded(func, self.store_id) })
101 }
102
103 fn unguarded_func(&self, idx: u32) -> Option<UnguardedFunc> {
105 self.inner().funcs.get(idx as usize).copied()
106 }
107
108 pub(crate) fn table(&self, idx: u32) -> Option<Table> {
110 self.unguarded_table(idx)
111 .map(|table| unsafe { Table::from_unguarded(table, self.store_id) })
112 }
113
114 fn unguarded_table(&self, idx: u32) -> Option<UnguardedTable> {
116 self.inner().tables.get(idx as usize).copied()
117 }
118
119 pub(crate) fn mem(&self, idx: u32) -> Option<Mem> {
121 self.unguarded_mem(idx)
122 .map(|mem| unsafe { Mem::from_unguarded(mem, self.store_id) })
123 }
124
125 fn unguarded_mem(&self, idx: u32) -> Option<UnguardedMem> {
127 self.inner().mems.get(idx as usize).copied()
128 }
129
130 pub(crate) fn global(&self, idx: u32) -> Option<Global> {
132 self.unguarded_global(idx)
133 .map(|global| unsafe { Global::from_unguarded(global, self.store_id) })
134 }
135
136 fn unguarded_global(&self, idx: u32) -> Option<UnguardedGlobal> {
138 self.inner().globals.get(idx as usize).copied()
139 }
140
141 pub(crate) fn elem(&self, idx: u32) -> Option<Elem> {
143 self.unguarded_elem(idx)
144 .map(|elem| unsafe { Elem::from_unguarded(elem, self.store_id) })
145 }
146
147 fn unguarded_elem(&self, idx: u32) -> Option<UnguardedElem> {
149 self.inner().elems.get(idx as usize).copied()
150 }
151
152 pub(crate) fn data(&self, idx: u32) -> Option<Data> {
154 self.unguarded_data(idx)
155 .map(|data| unsafe { Data::from_unguarded(data, self.store_id) })
156 }
157
158 fn unguarded_data(&self, idx: u32) -> Option<UnguardedData> {
160 self.inner().datas.get(idx as usize).copied()
161 }
162
163 fn inner(&self) -> &InstanceInner {
164 self.inner.get().expect("instance not yet initialized")
165 }
166}
167
168impl EvaluationContext for Instance {
169 fn func(&self, idx: u32) -> Option<Func> {
170 self.func(idx)
171 }
172
173 fn global(&self, idx: u32) -> Option<Global> {
174 self.global(idx)
175 }
176}
177
178#[derive(Clone, Debug)]
180pub struct InstanceExports<'a> {
181 store_id: StoreId,
182 iter: hash_map::Iter<'a, Arc<str>, UnguardedExternVal>,
183}
184
185impl<'a> Iterator for InstanceExports<'a> {
186 type Item = (&'a str, ExternVal);
187
188 fn next(&mut self) -> Option<Self::Item> {
189 self.iter.next().map(|(name, val)| {
190 (&**name, unsafe {
191 ExternVal::from_unguarded(*val, self.store_id)
192 })
193 })
194 }
195}
196
197#[derive(Debug)]
198struct InstanceInner {
199 types: Box<[UnguardedInternedFuncType]>,
200 funcs: Box<[UnguardedFunc]>,
201 tables: Box<[UnguardedTable]>,
202 mems: Box<[UnguardedMem]>,
203 globals: Box<[UnguardedGlobal]>,
204 elems: Box<[UnguardedElem]>,
205 datas: Box<[UnguardedData]>,
206 exports: HashMap<Arc<str>, UnguardedExternVal>,
207}
208
209#[derive(Debug)]
211pub(crate) struct InstanceIniter {
212 store_id: StoreId,
213 types: Vec<UnguardedInternedFuncType>,
214 funcs: Vec<UnguardedFunc>,
215 tables: Vec<UnguardedTable>,
216 mems: Vec<UnguardedMem>,
217 globals: Vec<UnguardedGlobal>,
218 elems: Vec<UnguardedElem>,
219 datas: Vec<UnguardedData>,
220 exports: HashMap<Arc<str>, UnguardedExternVal>,
221}
222
223impl InstanceIniter {
224 pub(crate) fn new(store_id: StoreId) -> InstanceIniter {
226 InstanceIniter {
227 types: Vec::new(),
228 funcs: Vec::new(),
229 tables: Vec::new(),
230 mems: Vec::new(),
231 globals: Vec::new(),
232 elems: Vec::new(),
233 datas: Vec::new(),
234 exports: HashMap::new(),
235 store_id,
236 }
237 }
238
239 pub(crate) fn func(&self, idx: u32) -> Option<Func> {
241 self.unguarded_func(idx)
242 .map(|func| unsafe { Func::from_unguarded(func, self.store_id) })
243 }
244
245 fn unguarded_func(&self, idx: u32) -> Option<UnguardedFunc> {
247 self.funcs.get(idx as usize).copied()
248 }
249
250 pub(crate) fn table(&self, idx: u32) -> Option<Table> {
252 self.unguarded_table(idx)
253 .map(|table| unsafe { Table::from_unguarded(table, self.store_id) })
254 }
255
256 fn unguarded_table(&self, idx: u32) -> Option<UnguardedTable> {
258 self.tables.get(idx as usize).copied()
259 }
260
261 pub(crate) fn mem(&self, idx: u32) -> Option<Mem> {
263 self.unguarded_mem(idx)
264 .map(|mem| unsafe { Mem::from_unguarded(mem, self.store_id) })
265 }
266
267 fn unguarded_mem(&self, idx: u32) -> Option<UnguardedMem> {
269 self.mems.get(idx as usize).copied()
270 }
271
272 pub(crate) fn global(&self, idx: u32) -> Option<Global> {
274 self.unguarded_global(idx)
275 .map(|global| unsafe { Global::from_unguarded(global, self.store_id) })
276 }
277
278 fn unguarded_global(&self, idx: u32) -> Option<UnguardedGlobal> {
279 self.globals.get(idx as usize).copied()
280 }
281
282 pub(crate) fn push_type(&mut self, type_: InternedFuncType) {
284 self.types.push(type_.to_unguarded(self.store_id));
285 }
286
287 pub(crate) fn push_func(&mut self, func: Func) {
289 self.funcs.push(func.to_unguarded(self.store_id));
290 }
291
292 pub(crate) fn push_table(&mut self, table: Table) {
294 self.tables.push(table.to_unguarded(self.store_id));
295 }
296
297 pub(crate) fn push_mem(&mut self, mem: Mem) {
299 self.mems.push(mem.to_unguarded(self.store_id));
300 }
301
302 pub(crate) fn push_global(&mut self, global: Global) {
304 self.globals.push(global.to_unguarded(self.store_id));
305 }
306
307 pub(crate) fn push_elem(&mut self, elem: Elem) {
309 self.elems.push(elem.to_unguarded(self.store_id));
310 }
311
312 pub(crate) fn push_data(&mut self, data: Data) {
314 self.datas.push(data.to_unguarded(self.store_id));
315 }
316
317 pub(crate) fn push_export(&mut self, name: Arc<str>, val: ExternVal) {
319 self.exports.insert(name, val.to_unguarded(self.store_id));
320 }
321}
322
323impl EvaluationContext for InstanceIniter {
324 fn func(&self, idx: u32) -> Option<Func> {
325 self.func(idx)
326 }
327
328 fn global(&self, idx: u32) -> Option<Global> {
329 self.global(idx)
330 }
331}