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