makepad_stitch/
instance.rs

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/// A [`Module`](`crate::Module`) instance.
21#[derive(Clone, Debug)]
22pub struct Instance {
23    store_id: StoreId,
24    inner: Arc<OnceCell<InstanceInner>>,
25}
26
27impl Instance {
28    /// Returns the [`ExternVal`] of the export with the given name in this [`Instance`], if it exists.
29    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    /// Returns the exported [`Func`] with the given name in this [`Instance`], if it exists.
37    pub fn exported_func(&self, name: &str) -> Option<Func> {
38        self.exported_val(name).and_then(|val| val.to_func())
39    }
40
41    /// Returns the exported [`Table`] with the given name in this [`Instance`], if it exists.
42    pub fn exported_table(&self, name: &str) -> Option<Table> {
43        self.exported_val(name).and_then(|val| val.to_table())
44    }
45
46    /// Returns the exported [`Mem`] with the given name in this [`Instance`], if it exists.
47    pub fn exported_mem(&self, name: &str) -> Option<Mem> {
48        self.exported_val(name).and_then(|val| val.to_mem())
49    }
50
51    /// Returns the exported [`Global`] with the given name in this [`Instance`], if it exists.
52    pub fn exported_global(&self, name: &str) -> Option<Global> {
53        self.exported_val(name).and_then(|val| val.to_global())
54    }
55
56    /// Returns an iterator over the exports in this [`Instance`].
57    pub fn exports(&self) -> InstanceExports<'_> {
58        InstanceExports {
59            store_id: self.store_id,
60            iter: self.inner().exports.iter(),
61        }
62    }
63
64    /// Creates an uninitialized [`Instance`].
65    pub(crate) fn uninited(store_id: StoreId) -> Instance {
66        Instance {
67            store_id,
68            inner: Arc::new(OnceCell::new()),
69        }
70    }
71
72    /// Initialize this [`Instance`] with the given [`InstanceIniter`].
73    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    /// Returns the [`InternedFuncType`] at the given index in this [`Instance`], if it exists.
90    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    /// Returns the [`Func`] at the given index in this [`Instance`], if it exists.
98    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    /// An unguarded version of [`Instance::func`].
104    fn unguarded_func(&self, idx: u32) -> Option<UnguardedFunc> {
105        self.inner().funcs.get(idx as usize).copied()
106    }
107
108    /// Returns the [`Table`] at the given index in this [`Instance`], if it exists.
109    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    /// An unguarded version of [`Instance::table`].
115    fn unguarded_table(&self, idx: u32) -> Option<UnguardedTable> {
116        self.inner().tables.get(idx as usize).copied()
117    }
118
119    /// Returns the [`Mem`] at the given index in this [`Instance`], if it exists.
120    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    /// An unguarded version of [`Instance::mem`].
126    fn unguarded_mem(&self, idx: u32) -> Option<UnguardedMem> {
127        self.inner().mems.get(idx as usize).copied()
128    }
129
130    /// Returns the [`Global`] at the given index in this [`Instance`], if it exists.
131    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    /// An unguarded version of [`Instance::global`].
137    fn unguarded_global(&self, idx: u32) -> Option<UnguardedGlobal> {
138        self.inner().globals.get(idx as usize).copied()
139    }
140
141    /// Returns the [`Elem`] at the given index in this [`Instance`], if it exists.
142    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    /// An unguarded version of [`Instance::elem`].
148    fn unguarded_elem(&self, idx: u32) -> Option<UnguardedElem> {
149        self.inner().elems.get(idx as usize).copied()
150    }
151
152    /// Returns the [`Data`] at the given index in this [`Instance`], if it exists.
153    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    /// An unguarded version of [`Instance::data`].
159    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/// An iterator over the exports in an [`Instance`].
179#[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/// An initializer for an [`Instance`].
210#[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    /// Creates a new [`InstanceIniter`].
225    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    /// Returns the [`Func`] at the given index in this [`InstanceIniter`], if it exists.
240    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    /// An unguarded version of [`InstanceIniter::func`].
246    fn unguarded_func(&self, idx: u32) -> Option<UnguardedFunc> {
247        self.funcs.get(idx as usize).copied()
248    }
249
250    /// Returns the [`Table`] at the given index in this [`InstanceIniter`], if it exists.
251    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    /// An unguarded version of [`InstanceIniter::table`].
257    fn unguarded_table(&self, idx: u32) -> Option<UnguardedTable> {
258        self.tables.get(idx as usize).copied()
259    }
260
261    /// Returns the [`Mem`] at the given index in this [`InstanceIniter`], if it exists.
262    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    /// An unguarded version of [`InstanceIniter::mem`].
268    fn unguarded_mem(&self, idx: u32) -> Option<UnguardedMem> {
269        self.mems.get(idx as usize).copied()
270    }
271
272    /// Returns the [`Global`] at the given index in this [`InstanceIniter`], if it exists.
273    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    /// Appends the given [`InternedFuncType`] to this [`InstanceIniter`].
283    pub(crate) fn push_type(&mut self, type_: InternedFuncType) {
284        self.types.push(type_.to_unguarded(self.store_id));
285    }
286
287    /// Appends the given [`Func`] to this [`InstanceIniter`].
288    pub(crate) fn push_func(&mut self, func: Func) {
289        self.funcs.push(func.to_unguarded(self.store_id));
290    }
291
292    /// Appends the given [`Table`] to this [`InstanceIniter`].
293    pub(crate) fn push_table(&mut self, table: Table) {
294        self.tables.push(table.to_unguarded(self.store_id));
295    }
296
297    /// Appends the given [`Mem`] to this [`InstanceIniter`].
298    pub(crate) fn push_mem(&mut self, mem: Mem) {
299        self.mems.push(mem.to_unguarded(self.store_id));
300    }
301
302    /// Appends the given [`Global`] to this [`InstanceIniter`].
303    pub(crate) fn push_global(&mut self, global: Global) {
304        self.globals.push(global.to_unguarded(self.store_id));
305    }
306
307    /// Appends the given [`Elem`] to this [`InstanceIniter`].
308    pub(crate) fn push_elem(&mut self, elem: Elem) {
309        self.elems.push(elem.to_unguarded(self.store_id));
310    }
311
312    /// Appends the given [`Data`] to this [`InstanceIniter`].
313    pub(crate) fn push_data(&mut self, data: Data) {
314        self.datas.push(data.to_unguarded(self.store_id));
315    }
316
317    /// Appends an export with the given name and [`ExternVal`] to this [`InstanceIniter`].
318    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}