/build/source/crates/checked/src/store.rs
Line | Count | Source |
1 | | use alloc::{string::String, vec::Vec}; |
2 | | use wasm::{ |
3 | | Config, FuncAddr, FuncType, GlobalAddr, GlobalType, HostResumable, Hostcode, MemAddr, MemType, |
4 | | Module, ModuleAddr, RuntimeError, TableAddr, TableType, WasmResumable, |
5 | | }; |
6 | | |
7 | | use crate::{ |
8 | | stored_types::{Stored, StoredExternVal, StoredInstantiationOutcome, StoredRunState}, |
9 | | AbstractStored, StoreId, StoredRef, StoredResumable, StoredValue, |
10 | | }; |
11 | | |
12 | | pub struct Store<'b, T: Config> { |
13 | | pub(crate) inner: wasm::Store<'b, T>, |
14 | | |
15 | | /// A unique identifier for this store. This is used to verify that stored |
16 | | /// objects belong to the current [`Store`](wasm::Store). |
17 | | pub(crate) id: StoreId, |
18 | | } |
19 | | |
20 | | impl<'b, T: Config> Store<'b, T> { |
21 | | /// Returns an immutable reference to the raw store. |
22 | 27 | pub fn inner(&self) -> &wasm::Store<'b, T> { |
23 | 27 | &self.inner |
24 | 27 | } |
25 | | |
26 | | /// Deconstructs this checked store and returns its inner representation. |
27 | 0 | pub fn into_inner(self) -> wasm::Store<'b, T> { |
28 | 0 | self.inner |
29 | 0 | } |
30 | | |
31 | | /// Returns the id of this store. |
32 | 0 | pub fn id(&self) -> StoreId { |
33 | 0 | self.id |
34 | 0 | } |
35 | | } |
36 | | |
37 | | // All functions in this impl block must occur in the same order as they are |
38 | | // defined in for the unchecked `Store` methods. Also all functions must follow |
39 | | // the same implementation scheme to make sure they are only light wrappers: |
40 | | // |
41 | | // 1. try unwrap [stored parameter objects] |
42 | | // 2. call [unchecked method] |
43 | | // 3. rewrap [results into stored objects] |
44 | | // 4. return [stored result objects] |
45 | | impl<'b, T: Config> Store<'b, T> { |
46 | 442 | pub fn new(user_data: T) -> Self { |
47 | 442 | Self { |
48 | 442 | inner: wasm::Store::new(user_data), |
49 | 442 | id: StoreId::new(), |
50 | 442 | } |
51 | 442 | } |
52 | | |
53 | | /// This is a safe variant of |
54 | | /// [`Store::module_instantiate`](wasm::Store::module_instantiate). |
55 | 294 | pub fn module_instantiate( |
56 | 294 | &mut self, |
57 | 294 | validation_info: &Module<'b>, |
58 | 294 | extern_vals: Vec<StoredExternVal>, |
59 | 294 | maybe_fuel: Option<u64>, |
60 | 294 | ) -> Result<StoredInstantiationOutcome, RuntimeError> { |
61 | | // 1. try unwrap |
62 | 294 | let extern_vals = extern_vals.try_unwrap_into_bare(self.id); |
63 | | // 2. call |
64 | | // SAFETY: It was just checked that the `ExternVal`s came from the |
65 | | // current store through their store ids. |
66 | 292 | let instantiation_outcome = unsafe { |
67 | 294 | self.inner |
68 | 294 | .module_instantiate(validation_info, extern_vals, maybe_fuel) |
69 | 2 | }?; |
70 | | // 3. rewrap |
71 | | // SAFETY: The `InstantiationOutcome` just came from the current store. |
72 | 292 | let stored_instantiation_outcome = |
73 | 292 | unsafe { StoredInstantiationOutcome::from_bare(instantiation_outcome, self.id) }; |
74 | | // 4. return |
75 | 292 | Ok(stored_instantiation_outcome) |
76 | 294 | } |
77 | | |
78 | | /// This is a safe variant of |
79 | | /// [`Store::instance_export`](wasm::Store::instance_export). |
80 | 48.1k | pub fn instance_export( |
81 | 48.1k | &self, |
82 | 48.1k | module_addr: Stored<ModuleAddr>, |
83 | 48.1k | name: &str, |
84 | 48.1k | ) -> Result<StoredExternVal, RuntimeError> { |
85 | | // 1. try unwrap |
86 | 48.1k | let module_addr = module_addr.try_unwrap_into_bare(self.id); |
87 | | // 2. call |
88 | | // SAFETY: It was just checked that the `ModuleAddr` came from the |
89 | | // current store through its store id. |
90 | 48.1k | let extern_val = unsafe { self.inner.instance_export(module_addr, name) }?0 ; |
91 | | // 3. rewrap |
92 | | // SAFETY: The `ExternVal` just came from the current store. |
93 | 48.1k | let stored_extern_val = unsafe { StoredExternVal::from_bare(extern_val, self.id) }; |
94 | | // 4. return |
95 | 48.1k | Ok(stored_extern_val) |
96 | 48.1k | } |
97 | | |
98 | | /// This is a variant of [`Store::func_alloc`](wasm::Store::func_alloc). It |
99 | | /// is functionally equal, with the only difference being that this function |
100 | | /// returns a [`Stored<FuncAddr>`]. |
101 | | #[allow(clippy::let_and_return)] // reason = "to follow the 1234 structure" |
102 | 1.02k | pub fn func_alloc(&mut self, func_type: FuncType, hostcode: Hostcode) -> Stored<FuncAddr> { |
103 | | // 1. try unwrap |
104 | | // no stored parameters |
105 | | // 2. call |
106 | 1.02k | let func_addr = self.inner.func_alloc(func_type, hostcode); |
107 | | // 3. rewrap |
108 | | // 4. return |
109 | | // SAFETY: The function address just came from the current store. |
110 | 1.02k | unsafe { Stored::from_bare(func_addr, self.id) } |
111 | 1.02k | } |
112 | | |
113 | | /// This is a safe variant of [`Store::func_type`](wasm::Store::func_type). |
114 | 0 | pub fn func_type(&self, func_addr: Stored<FuncAddr>) -> FuncType { |
115 | | // 1. try unwrap |
116 | 0 | let func_addr = func_addr.try_unwrap_into_bare(self.id); |
117 | | // 2. call |
118 | | // 3. rewrap |
119 | | // `FuncType` does not have a stored variant. |
120 | | // 4. return |
121 | | // SAFETY: It was just checked that the `FuncAddr` came from the current |
122 | | // store through its store id. |
123 | 0 | unsafe { self.inner.func_type(func_addr) } |
124 | 0 | } |
125 | | |
126 | | /// This is a safe variant of [`Store::invoke`](wasm::Store::invoke). |
127 | 1 | pub fn invoke( |
128 | 1 | &mut self, |
129 | 1 | func_addr: Stored<FuncAddr>, |
130 | 1 | params: Vec<StoredValue>, |
131 | 1 | maybe_fuel: Option<u64>, |
132 | 1 | ) -> Result<StoredRunState, RuntimeError> { |
133 | | // 1. try unwrap |
134 | 1 | let func_addr = func_addr.try_unwrap_into_bare(self.id); |
135 | 1 | let params = params.try_unwrap_into_bare(self.id); |
136 | | // 2. call |
137 | | // SAFETY: It was just checked that the `FuncAddr` and any addresses in |
138 | | // the parameters came from the current store through their store ids. |
139 | 1 | let run_state = unsafe { self.inner.invoke(func_addr, params, maybe_fuel) }?0 ; |
140 | | // 3. rewrap |
141 | | // SAFETY: The `RunState` just came from the current store. |
142 | 1 | let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) }; |
143 | | // 4. return |
144 | 1 | Ok(stored_run_state) |
145 | 1 | } |
146 | | |
147 | | /// This is a safe variant of |
148 | | /// [`Store::table_alloc`](wasm::Store::table_alloc). |
149 | 145 | pub fn table_alloc( |
150 | 145 | &mut self, |
151 | 145 | table_type: TableType, |
152 | 145 | r#ref: StoredRef, |
153 | 145 | ) -> Result<Stored<TableAddr>, RuntimeError> { |
154 | | // 1. try unwrap |
155 | 145 | let r#ref = r#ref.try_unwrap_into_bare(self.id); |
156 | | // 2. call |
157 | | // SAFETY: It was just checked that any address in the reference came |
158 | | // from the current store through its store id. |
159 | 145 | let table_addr = unsafe { self.inner.table_alloc(table_type, r#ref) }?0 ; |
160 | | // 3. rewrap |
161 | | // SAFETY: The `TableAddr` just came from the current store. |
162 | 145 | let stored_table_addr = unsafe { Stored::from_bare(table_addr, self.id) }; |
163 | | // 4. return |
164 | 145 | Ok(stored_table_addr) |
165 | 145 | } |
166 | | |
167 | | /// This is a safe variant of |
168 | | /// [`Store::table_type`](wasm::Store::table_type). |
169 | 0 | pub fn table_type(&self, table_addr: Stored<TableAddr>) -> TableType { |
170 | | // 1. try unwrap |
171 | 0 | let table_addr = table_addr.try_unwrap_into_bare(self.id); |
172 | | // 2. call |
173 | | // 3. rewrap |
174 | | // `TableType` has no stored variant. |
175 | | // 4. return |
176 | | // SAFETY: It was just checked that the `TableAddr` came from the |
177 | | // current store through its store id. |
178 | 0 | unsafe { self.inner.table_type(table_addr) } |
179 | 0 | } |
180 | | |
181 | | /// This is a safe variant of |
182 | | /// [`Store::table_read`](wasm::Store::table_read). |
183 | 2 | pub fn table_read( |
184 | 2 | &self, |
185 | 2 | table_addr: Stored<TableAddr>, |
186 | 2 | i: u32, |
187 | 2 | ) -> Result<StoredRef, RuntimeError> { |
188 | | // 1. try unwrap |
189 | 2 | let table_addr = table_addr.try_unwrap_into_bare(self.id); |
190 | | // 2. call |
191 | | // SAFETY: It was just checked that the `TableAddr` came from the |
192 | | // current store through its store id. |
193 | 2 | let r#ref = unsafe { self.inner.table_read(table_addr, i) }?0 ; |
194 | | // 3. rewrap |
195 | | // SAFETY: The `Ref` ust came from the current store. |
196 | 2 | let stored_ref = unsafe { StoredRef::from_bare(r#ref, self.id) }; |
197 | | // 4. return |
198 | 2 | Ok(stored_ref) |
199 | 2 | } |
200 | | |
201 | | /// This is a safe variant of |
202 | | /// [`Store::table_write`](wasm::Store::table_write). |
203 | 0 | pub fn table_write( |
204 | 0 | &mut self, |
205 | 0 | table_addr: Stored<TableAddr>, |
206 | 0 | i: u32, |
207 | 0 | r#ref: StoredRef, |
208 | 0 | ) -> Result<(), RuntimeError> { |
209 | | // 1. try unwrap |
210 | 0 | let table_addr = table_addr.try_unwrap_into_bare(self.id); |
211 | 0 | let r#ref = r#ref.try_unwrap_into_bare(self.id); |
212 | | // 2. call |
213 | | // SAFETY: It was just checked that the `TableAddr` and any address in |
214 | | // the reference came from the current store through their store ids. |
215 | 0 | unsafe { self.inner.table_write(table_addr, i, r#ref) }?; |
216 | | // 3. rewrap |
217 | | // result is the unit type. |
218 | | // 4. return |
219 | 0 | Ok(()) |
220 | 0 | } |
221 | | |
222 | | /// This is a safe variant of |
223 | | /// [`Store::table_size`](wasm::Store::table_size). |
224 | 0 | pub fn table_size(&self, table_addr: Stored<TableAddr>) -> u32 { |
225 | | // 1. try unwrap |
226 | 0 | let table_addr = table_addr.try_unwrap_into_bare(self.id); |
227 | | // 2. call |
228 | | // 3. rewrap |
229 | | // table size has no stored variant. |
230 | | // 4. return |
231 | | // SAFETY: It was just checked that the `TableAddr` came from the |
232 | | // current store through its store id. |
233 | 0 | unsafe { self.inner.table_size(table_addr) } |
234 | 0 | } |
235 | | |
236 | | /// This is a variant of [`Store::mem_alloc`](wasm::Store::mem_alloc) that |
237 | | /// returns a stored object. |
238 | | #[allow(clippy::let_and_return)] // reason = "to follow the 1234 structure" |
239 | 147 | pub fn mem_alloc(&mut self, mem_type: MemType) -> Stored<MemAddr> { |
240 | | // 1. try unwrap |
241 | | // no stored parameters |
242 | | // 2. call |
243 | 147 | let mem_addr = self.inner.mem_alloc(mem_type); |
244 | | // 3. rewrap |
245 | | // 4. return |
246 | | // SAFETY: The `MemAddr` just came from the current store. |
247 | 147 | unsafe { Stored::from_bare(mem_addr, self.id) } |
248 | 147 | } |
249 | | |
250 | | /// This is a safe variant of [`Store::mem_type`](wasm::Store::mem_type). |
251 | 0 | pub fn mem_type(&self, mem_addr: Stored<MemAddr>) -> MemType { |
252 | | // 1. try unwrap |
253 | 0 | let mem_addr = mem_addr.try_unwrap_into_bare(self.id); |
254 | | // 2. call |
255 | | // 3. rewrap |
256 | | // `MemType` does not have a stored variant. |
257 | | // 4. return |
258 | | // SAFETY: It was just checked that the `MemAddr` came from the current |
259 | | // store through its store id. |
260 | 0 | unsafe { self.inner.mem_type(mem_addr) } |
261 | 0 | } |
262 | | |
263 | | /// This is a safe variant of [`Store::mem_read`](wasm::Store::mem_read). |
264 | 210 | pub fn mem_read(&self, mem_addr: Stored<MemAddr>, i: u32) -> Result<u8, RuntimeError> { |
265 | | // 1. try unwrap |
266 | 210 | let mem_addr = mem_addr.try_unwrap_into_bare(self.id); |
267 | | // 2. call |
268 | | // SAFETY: It was just checked that the `MemAddr` came from the current |
269 | | // store through its store id. |
270 | 210 | let byte = unsafe { self.inner.mem_read(mem_addr, i) }?0 ; |
271 | | // 3. rewrap |
272 | | // a single byte does not have a stored variant. |
273 | | // 4. return |
274 | 210 | Ok(byte) |
275 | 210 | } |
276 | | |
277 | | /// This is a safe variant of [`Store::mem_write`](wasm::Store::mem_write). |
278 | 0 | pub fn mem_write( |
279 | 0 | &mut self, |
280 | 0 | mem_addr: Stored<MemAddr>, |
281 | 0 | i: u32, |
282 | 0 | byte: u8, |
283 | 0 | ) -> Result<(), RuntimeError> { |
284 | | // 1. try unwrap |
285 | 0 | let mem_addr = mem_addr.try_unwrap_into_bare(self.id); |
286 | | // 2. call |
287 | | // SAFETY: It was just checked that the `MemAddr` came from the current |
288 | | // store through its store id. |
289 | 0 | unsafe { self.inner.mem_write(mem_addr, i, byte) }?; |
290 | | // 3. rewrap |
291 | | // result is the unit type. |
292 | | // 4. return |
293 | 0 | Ok(()) |
294 | 0 | } |
295 | | |
296 | | /// This is a safe variant of [`Store::mem_size`](wasm::Store::mem_size). |
297 | 0 | pub fn mem_size(&self, mem_addr: Stored<MemAddr>) -> u32 { |
298 | | // 1. try unwrap |
299 | 0 | let mem_addr = mem_addr.try_unwrap_into_bare(self.id); |
300 | | // 2. call |
301 | | // 3. rewrap |
302 | | // mem size does not have a stored variant. |
303 | | // 4. return |
304 | | // SAFETY: It was just checked that the `MemAddr` came from the current |
305 | | // store through its store id. |
306 | 0 | unsafe { self.inner.mem_size(mem_addr) } |
307 | 0 | } |
308 | | |
309 | | /// This is a safe variant of [`Store::mem_grow`](wasm::Store::mem_grow). |
310 | 0 | pub fn mem_grow(&mut self, mem_addr: Stored<MemAddr>, n: u32) -> Result<(), RuntimeError> { |
311 | | // 1. try unwrap |
312 | 0 | let mem_addr = mem_addr.try_unwrap_into_bare(self.id); |
313 | | // 2. call |
314 | | // SAFETY: It was just checked that the `MemAddr` came from the current |
315 | | // store through its store id. |
316 | 0 | unsafe { self.inner.mem_grow(mem_addr, n) }?; |
317 | | // 3. rewrap |
318 | | // result is the unit type. |
319 | | // 4. return |
320 | 0 | Ok(()) |
321 | 0 | } |
322 | | |
323 | | /// This is a safe variant of |
324 | | /// [`Store::global_alloc`](wasm::Store::global_alloc). |
325 | 580 | pub fn global_alloc( |
326 | 580 | &mut self, |
327 | 580 | global_type: GlobalType, |
328 | 580 | val: StoredValue, |
329 | 580 | ) -> Result<Stored<GlobalAddr>, RuntimeError> { |
330 | | // 1. try unwrap |
331 | 580 | let val = val.try_unwrap_into_bare(self.id); |
332 | | // 2. call |
333 | | // SAFETY: It was just checked that any address the value came from the |
334 | | // current store through its store id. |
335 | 580 | let global_addr = unsafe { self.inner.global_alloc(global_type, val) }?0 ; |
336 | | // 3. rewrap |
337 | | // SAFETY: The `GlobalAddr` just came from the current store. |
338 | 580 | let stored_global_addr = unsafe { Stored::from_bare(global_addr, self.id) }; |
339 | | // 4. return |
340 | 580 | Ok(stored_global_addr) |
341 | 580 | } |
342 | | |
343 | | /// This is a safe variant of |
344 | | /// [`Store::global_type`](wasm::Store::global_type). |
345 | 2 | pub fn global_type(&self, global_addr: Stored<GlobalAddr>) -> Result<GlobalType, RuntimeError> { |
346 | | // 1. try unwrap |
347 | 2 | let global_addr = global_addr.try_unwrap_into_bare(self.id); |
348 | | // 2. call |
349 | | // SAFETY: It was just checked that the `GlobalAddr` came from the |
350 | | // current store through its store id. |
351 | 2 | let global_type = unsafe { self.inner.global_type(global_addr) }; |
352 | | // 3. rewrap |
353 | | // `GlobalType` does not have a stored variant. |
354 | | // 4. return |
355 | 2 | Ok(global_type) |
356 | 2 | } |
357 | | |
358 | | /// This is a safe variant of |
359 | | /// [`Store::global_read`](wasm::Store::global_read). |
360 | 99 | pub fn global_read(&self, global_addr: Stored<GlobalAddr>) -> StoredValue { |
361 | | // 1. try unwrap |
362 | 99 | let global_addr = global_addr.try_unwrap_into_bare(self.id); |
363 | | // 2. call |
364 | | // SAFETY: It was just checked that the `GlobalAddr` came from the |
365 | | // current store through its store id. |
366 | 99 | let value = unsafe { self.inner.global_read(global_addr) }; |
367 | | // 3. rewrap |
368 | | // 4. return |
369 | | // SAFETY: The `Value` just came from the current store. |
370 | 99 | unsafe { StoredValue::from_bare(value, self.id) } |
371 | 99 | } |
372 | | |
373 | | /// This is a safe variant of |
374 | | /// [`Store::global_write`](wasm::Store::global_write). |
375 | 1 | pub fn global_write( |
376 | 1 | &mut self, |
377 | 1 | global_addr: Stored<GlobalAddr>, |
378 | 1 | val: StoredValue, |
379 | 1 | ) -> Result<(), RuntimeError> { |
380 | | // 1. try unwrap |
381 | 1 | let global_addr = global_addr.try_unwrap_into_bare(self.id); |
382 | 1 | let val = val.try_unwrap_into_bare(self.id); |
383 | | // 2. call |
384 | | // SAFETY: It was just checked that the `GlobalAddr` any any address |
385 | | // contained in the value came from the current store through their |
386 | | // store ids. |
387 | 1 | unsafe { self.inner.global_write(global_addr, val) }?0 ; |
388 | | // 3. rewrap |
389 | | // result is the unit type. |
390 | | // 4. return |
391 | 1 | Ok(()) |
392 | 1 | } |
393 | | |
394 | | /// This is a safe variant of |
395 | | /// [`Store::create_resumable`](wasm::Store::create_resumable). |
396 | 47.8k | pub fn create_resumable( |
397 | 47.8k | &self, |
398 | 47.8k | func_addr: Stored<FuncAddr>, |
399 | 47.8k | params: Vec<StoredValue>, |
400 | 47.8k | maybe_fuel: Option<u64>, |
401 | 47.8k | ) -> Result<StoredResumable, RuntimeError> { |
402 | | // 1. try unwrap |
403 | 47.8k | let func_addr = func_addr.try_unwrap_into_bare(self.id); |
404 | 47.8k | let params = params.try_unwrap_into_bare(self.id); |
405 | | // 2. call |
406 | | // SAFETY: It was just checked that the `FuncAddr` any any addresses |
407 | | // contained in the parameters came from the current store through their |
408 | | // store ids. |
409 | 47.8k | let resumable = unsafe { self.inner.create_resumable(func_addr, params, maybe_fuel) }?0 ; |
410 | | // 3. rewrap |
411 | | // SAFETY: The `Resumable` just came from the current store. |
412 | 47.8k | let stored_resumable = unsafe { StoredResumable::from_bare(resumable, self.id) }; |
413 | | // 4. return |
414 | 47.8k | Ok(stored_resumable) |
415 | 47.8k | } |
416 | | |
417 | | /// This is a safe variant of [`Store::resume`](wasm::Store::resume). |
418 | 47.8k | pub fn resume(&mut self, resumable: StoredResumable) -> Result<StoredRunState, RuntimeError> { |
419 | | // 1. try unwrap |
420 | 47.8k | let resumable = resumable.try_unwrap_into_bare(self.id); |
421 | | // 2. call |
422 | | // SAFETY: It was just checked that the `Resumable` came from the |
423 | | // current store through its store id. |
424 | 47.8k | let run_state45.3k = unsafe { self.inner.resume(resumable) }?2.42k ; |
425 | | // 3. rewrap |
426 | | // SAFETY: The `RunState` just came from the current store. |
427 | 45.3k | let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) }; |
428 | | // 4. return |
429 | 45.3k | Ok(stored_run_state) |
430 | 47.8k | } |
431 | | |
432 | | /// This is a safe variant of [`Store::resume_wasm`](wasm::Store::resume_wasm). |
433 | 72 | pub fn resume_wasm( |
434 | 72 | &mut self, |
435 | 72 | resumable: Stored<WasmResumable>, |
436 | 72 | ) -> Result<StoredRunState, RuntimeError> { |
437 | | // 1. try unwrap |
438 | 72 | let resumable = resumable.try_unwrap_into_bare(self.id); |
439 | | // 2. call |
440 | | // SAFETY: It was just checked that the `WasmResumable` came from the |
441 | | // current store through its store id. |
442 | 72 | let run_state = unsafe { self.inner.resume_wasm(resumable) }?0 ; |
443 | | // 3. rewrap |
444 | | // SAFETY: The `RunState` just came from the current store. |
445 | 72 | let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) }; |
446 | | // 4. return |
447 | 72 | Ok(stored_run_state) |
448 | 72 | } |
449 | | |
450 | | /// This is a safe variant of [`wasm::Store::finish_host_call`]. |
451 | 28 | pub fn finish_host_call( |
452 | 28 | &mut self, |
453 | 28 | host_resumable: Stored<HostResumable>, |
454 | 28 | host_call_return_values: Vec<StoredValue>, |
455 | 28 | ) -> Result<StoredRunState, RuntimeError> { |
456 | | // 1. try unwrap |
457 | 28 | let host_resumable = host_resumable.try_unwrap_into_bare(self.id); |
458 | 28 | let host_call_return_values = host_call_return_values.try_unwrap_into_bare(self.id); |
459 | | // 2. call |
460 | | // SAFETY: It was just checked that the `HostResumable` and all `Value`s |
461 | | // came from the current store through their store ids. |
462 | 27 | let run_state = unsafe { |
463 | 28 | self.inner |
464 | 28 | .finish_host_call(host_resumable, host_call_return_values) |
465 | 1 | }?; |
466 | | // 3. rewrap |
467 | | // SAFETY: The `RunState`s just came from the current store. |
468 | 27 | let stored_run_state = unsafe { StoredRunState::from_bare(run_state, self.id) }; |
469 | | // 4. return |
470 | 27 | Ok(stored_run_state) |
471 | 28 | } |
472 | | |
473 | | /// This is a safe variant of |
474 | | /// [`Store::invoke_simple`](wasm::Store::invoke_simple) |
475 | 6.84k | pub fn invoke_simple( |
476 | 6.84k | &mut self, |
477 | 6.84k | function: Stored<FuncAddr>, |
478 | 6.84k | params: Vec<StoredValue>, |
479 | 6.84k | ) -> Result<Vec<StoredValue>, RuntimeError> { |
480 | | // 1. try unwrap |
481 | 6.84k | let function = function.try_unwrap_into_bare(self.id); |
482 | 6.84k | let params = params.try_unwrap_into_bare(self.id); |
483 | | // 2. call |
484 | | // SAFETY: It was just checked that the `FuncAddr` and all `Value`s came |
485 | | // from the current store through their store ids. |
486 | 6.84k | let return_values6.17k = unsafe { self.inner.invoke_simple(function, params) }?667 ; |
487 | | // 3. rewrap |
488 | | // SAFETY: The `Value`s just came from the current store. |
489 | 6.17k | let stored_return_values = unsafe { Vec::from_bare(return_values, self.id) }; |
490 | | // 4. return |
491 | 6.17k | Ok(stored_return_values) |
492 | 6.84k | } |
493 | | |
494 | | /// This is a safe variant of |
495 | | /// [`Store::mem_access_mut_slice`](crate::Store::mem_access_mut_slice). |
496 | 3 | pub fn mem_access_mut_slice<R>( |
497 | 3 | &self, |
498 | 3 | memory: Stored<MemAddr>, |
499 | 3 | accessor: impl FnOnce(&mut [u8]) -> R, |
500 | 3 | ) -> R { |
501 | | // 1. try unwrap |
502 | 3 | let memory = memory.try_unwrap_into_bare(self.id); |
503 | | // 2. call |
504 | | // 3. rewrap |
505 | | // result is generic |
506 | | // 4. return |
507 | | // SAFETY: It was just checked that the `MemAddr` came from the current |
508 | | // store through its store id. |
509 | 3 | unsafe { self.inner.mem_access_mut_slice(memory, accessor) } |
510 | 3 | } |
511 | | |
512 | | /// This is a safe variant of |
513 | | /// [`Store::instance_exports`](wasm::Store::instance_exports) |
514 | 0 | pub fn instance_exports( |
515 | 0 | &self, |
516 | 0 | module_addr: Stored<ModuleAddr>, |
517 | 0 | ) -> Vec<(String, StoredExternVal)> { |
518 | | // 1. try unwrap |
519 | 0 | let module_addr = module_addr.try_unwrap_into_bare(self.id); |
520 | | // 2. call |
521 | | // SAFETY: We just checked that this module address is valid in the |
522 | | // current store through its store id. |
523 | 0 | let exports = unsafe { self.inner.instance_exports(module_addr) }; |
524 | | // 3. rewrap |
525 | | // 4. return |
526 | 0 | exports |
527 | 0 | .into_iter() |
528 | 0 | .map(|(name, externval)| { |
529 | | // SAFETY: The `ExternVal`s just came from the current store. |
530 | 0 | let stored_externval = unsafe { StoredExternVal::from_bare(externval, self.id) }; |
531 | 0 | (name, stored_externval) |
532 | 0 | }) |
533 | 0 | .collect() |
534 | 0 | } |
535 | | } |