radix_wasmi/store.rs
1extern crate radix_wasmi_arena as wasmi_arena;
2
3use super::{
4 engine::DedupFuncType,
5 Engine,
6 Func,
7 FuncEntity,
8 FuncIdx,
9 FuncType,
10 Global,
11 GlobalEntity,
12 GlobalIdx,
13 Instance,
14 InstanceEntity,
15 InstanceIdx,
16 Memory,
17 MemoryEntity,
18 MemoryIdx,
19 Table,
20 TableEntity,
21 TableIdx,
22};
23use core::{
24 fmt::Debug,
25 sync::atomic::{AtomicU32, Ordering},
26};
27use wasmi_arena::{Arena, ArenaIndex, ComponentVec, GuardedEntity};
28
29/// A unique store index.
30///
31/// # Note
32///
33/// Used to protect against invalid entity indices.
34#[derive(Debug, Copy, Clone, PartialEq, Eq)]
35pub struct StoreIdx(u32);
36
37impl ArenaIndex for StoreIdx {
38 fn into_usize(self) -> usize {
39 self.0 as usize
40 }
41
42 fn from_usize(value: usize) -> Self {
43 let value = value.try_into().unwrap_or_else(|error| {
44 panic!("index {value} is out of bounds as store index: {error}")
45 });
46 Self(value)
47 }
48}
49
50impl StoreIdx {
51 /// Returns a new unique [`StoreIdx`].
52 fn new() -> Self {
53 /// A static store index counter.
54 static CURRENT_STORE_IDX: AtomicU32 = AtomicU32::new(0);
55 let next_idx = CURRENT_STORE_IDX.fetch_add(1, Ordering::AcqRel);
56 Self(next_idx)
57 }
58}
59
60/// A stored entity.
61pub type Stored<Idx> = GuardedEntity<StoreIdx, Idx>;
62
63/// The store that owns all data associated to Wasm modules.
64#[derive(Debug, Clone)]
65pub struct Store<T> {
66 /// All data that is not associated to `T`.
67 ///
68 /// # Note
69 ///
70 /// This is re-exported to the rest of the crate since
71 /// it is used directly by the engine's executor.
72 pub(crate) inner: StoreInner,
73 /// Stored Wasm or host functions.
74 funcs: Arena<FuncIdx, FuncEntity<T>>,
75 /// User provided host data owned by the [`Store`].
76 data: T,
77}
78
79/// The inner store that owns all data not associated to the host state.
80#[derive(Debug, Clone)]
81pub struct StoreInner {
82 /// The unique store index.
83 ///
84 /// Used to protect against invalid entity indices.
85 store_idx: StoreIdx,
86 /// Stores the function type for each function.
87 ///
88 /// # Note
89 ///
90 /// This is required so that the [`Engine`] can work entirely
91 /// with a `&mut StoreInner` reference.
92 func_types: ComponentVec<FuncIdx, DedupFuncType>,
93 /// Stored linear memories.
94 memories: Arena<MemoryIdx, MemoryEntity>,
95 /// Stored tables.
96 tables: Arena<TableIdx, TableEntity>,
97 /// Stored global variables.
98 globals: Arena<GlobalIdx, GlobalEntity>,
99 /// Stored module instances.
100 instances: Arena<InstanceIdx, InstanceEntity>,
101 /// The [`Engine`] in use by the [`Store`].
102 ///
103 /// Amongst others the [`Engine`] stores the Wasm function definitions.
104 engine: Engine,
105}
106
107#[test]
108fn test_store_is_send_sync() {
109 const _: () = {
110 fn assert_send<T: Send>() {}
111 fn assert_sync<T: Sync>() {}
112 let _ = assert_send::<Store<()>>;
113 let _ = assert_sync::<Store<()>>;
114 };
115}
116
117impl StoreInner {
118 /// Creates a new [`StoreInner`] for the given [`Engine`].
119 pub fn new(engine: &Engine) -> Self {
120 StoreInner {
121 engine: engine.clone(),
122 store_idx: StoreIdx::new(),
123 func_types: ComponentVec::new(),
124 memories: Arena::new(),
125 tables: Arena::new(),
126 globals: Arena::new(),
127 instances: Arena::new(),
128 }
129 }
130
131 /// Returns the [`Engine`] that this store is associated with.
132 pub fn engine(&self) -> &Engine {
133 &self.engine
134 }
135
136 /// Allocates a new [`FuncType`] and returns a [`DedupFuncType`] reference to it.
137 ///
138 /// # Note
139 ///
140 /// This deduplicates [`FuncType`] instances that compare as equal.
141 pub fn alloc_func_type(&mut self, func_type: FuncType) -> DedupFuncType {
142 self.engine.alloc_func_type(func_type)
143 }
144
145 /// Wraps an entitiy `Idx` (index type) as a [`Stored<Idx>`] type.
146 ///
147 /// # Note
148 ///
149 /// [`Stored<Idx>`] associates an `Idx` type with the internal store index.
150 /// This way wrapped indices cannot be misused with incorrect [`Store`] instances.
151 fn wrap_stored<Idx>(&self, entity_idx: Idx) -> Stored<Idx> {
152 Stored::new(self.store_idx, entity_idx)
153 }
154
155 /// Unwraps the given [`Stored<Idx>`] reference and returns the `Idx`.
156 ///
157 /// # Panics
158 ///
159 /// If the [`Stored<Idx>`] does not originate from this [`Store`].
160 fn unwrap_stored<Idx>(&self, stored: Stored<Idx>) -> Idx
161 where
162 Idx: ArenaIndex + Debug,
163 {
164 stored.entity_index(self.store_idx).unwrap_or_else(|| {
165 panic!(
166 "entity reference ({:?}) does not belong to store {:?}",
167 stored, self.store_idx,
168 )
169 })
170 }
171
172 /// Registers the `func_type` for the given `func`.
173 ///
174 /// # Note
175 ///
176 /// This is required so that the [`Engine`] can work entirely
177 /// with a `&mut StoreInner` reference.
178 pub fn register_func_type(&mut self, func: Func, func_type: DedupFuncType) {
179 let idx = self.unwrap_stored(func.into_inner());
180 let previous = self.func_types.set(idx, func_type);
181 debug_assert!(previous.is_none());
182 }
183
184 /// Returns the [`DedupFuncType`] for the given [`Func`].
185 ///
186 /// # Note
187 ///
188 /// Panics if no [`DedupFuncType`] for the given [`Func`] was registered.
189 pub fn get_func_type(&self, func: Func) -> DedupFuncType {
190 let idx = self.unwrap_stored(func.into_inner());
191 self.func_types
192 .get(idx)
193 .copied()
194 .unwrap_or_else(|| panic!("missing function type for func: {func:?}"))
195 }
196
197 /// Allocates a new [`GlobalEntity`] and returns a [`Global`] reference to it.
198 pub fn alloc_global(&mut self, global: GlobalEntity) -> Global {
199 let global = self.globals.alloc(global);
200 Global::from_inner(self.wrap_stored(global))
201 }
202
203 /// Allocates a new [`TableEntity`] and returns a [`Table`] reference to it.
204 pub fn alloc_table(&mut self, table: TableEntity) -> Table {
205 let table = self.tables.alloc(table);
206 Table::from_inner(self.wrap_stored(table))
207 }
208
209 /// Allocates a new [`MemoryEntity`] and returns a [`Memory`] reference to it.
210 pub fn alloc_memory(&mut self, memory: MemoryEntity) -> Memory {
211 let memory = self.memories.alloc(memory);
212 Memory::from_inner(self.wrap_stored(memory))
213 }
214
215 /// Allocates a new uninitialized [`InstanceEntity`] and returns an [`Instance`] reference to it.
216 ///
217 /// # Note
218 ///
219 /// - This will create an uninitialized dummy [`InstanceEntity`] as a place holder
220 /// for the returned [`Instance`]. Using this uninitialized [`Instance`] will result
221 /// in a runtime panic.
222 /// - The returned [`Instance`] must later be initialized via the [`Store::initialize_instance`]
223 /// method. Afterwards the [`Instance`] may be used.
224 pub fn alloc_instance(&mut self) -> Instance {
225 let instance = self.instances.alloc(InstanceEntity::uninitialized());
226 Instance::from_inner(self.wrap_stored(instance))
227 }
228
229 /// Initializes the [`Instance`] using the given [`InstanceEntity`].
230 ///
231 /// # Note
232 ///
233 /// After this operation the [`Instance`] is initialized and can be used.
234 ///
235 /// # Panics
236 ///
237 /// - If the [`Instance`] does not belong to the [`Store`].
238 /// - If the [`Instance`] is unknown to the [`Store`].
239 /// - If the [`Instance`] has already been initialized.
240 /// - If the given [`InstanceEntity`] is itself not initialized, yet.
241 pub fn initialize_instance(&mut self, instance: Instance, init: InstanceEntity) {
242 assert!(
243 init.is_initialized(),
244 "encountered an uninitialized new instance entity: {init:?}",
245 );
246 let idx = self.unwrap_stored(instance.into_inner());
247 let uninit = self
248 .instances
249 .get_mut(idx)
250 .unwrap_or_else(|| panic!("missing entity for the given instance: {instance:?}"));
251 assert!(
252 !uninit.is_initialized(),
253 "encountered an already initialized instance: {uninit:?}",
254 );
255 *uninit = init;
256 }
257
258 /// Returns a shared reference to the entity indexed by the given `idx`.
259 ///
260 /// # Panics
261 ///
262 /// - If the indexed entity does not originate from this [`Store`].
263 /// - If the entity index cannot be resolved to its entity.
264 fn resolve<'a, Idx, Entity>(
265 &self,
266 idx: Stored<Idx>,
267 entities: &'a Arena<Idx, Entity>,
268 ) -> &'a Entity
269 where
270 Idx: ArenaIndex + Debug,
271 {
272 let idx = self.unwrap_stored(idx);
273 entities
274 .get(idx)
275 .unwrap_or_else(|| panic!("failed to resolve stored entity: {idx:?}"))
276 }
277
278 /// Returns an exclusive reference to the entity indexed by the given `idx`.
279 ///
280 /// # Note
281 ///
282 /// Due to borrow checking issues this method takes an already unwrapped
283 /// `Idx` unlike the [`StoreInner::resolve`] method.
284 ///
285 /// # Panics
286 ///
287 /// - If the entity index cannot be resolved to its entity.
288 fn resolve_mut<Idx, Entity>(idx: Idx, entities: &mut Arena<Idx, Entity>) -> &mut Entity
289 where
290 Idx: ArenaIndex + Debug,
291 {
292 entities
293 .get_mut(idx)
294 .unwrap_or_else(|| panic!("failed to resolve stored entity: {idx:?}"))
295 }
296
297 /// Returns the [`FuncType`] associated to the given [`DedupFuncType`].
298 ///
299 /// # Panics
300 ///
301 /// - If the [`DedupFuncType`] does not originate from this [`Store`].
302 /// - If the [`DedupFuncType`] cannot be resolved to its entity.
303 pub fn resolve_func_type(&self, func_type: DedupFuncType) -> FuncType {
304 self.resolve_func_type_with(func_type, FuncType::clone)
305 }
306
307 /// Calls `f` on the [`FuncType`] associated to the given [`DedupFuncType`] and returns the result.
308 ///
309 /// # Panics
310 ///
311 /// - If the [`DedupFuncType`] does not originate from this [`Store`].
312 /// - If the [`DedupFuncType`] cannot be resolved to its entity.
313 pub fn resolve_func_type_with<R>(
314 &self,
315 func_type: DedupFuncType,
316 f: impl FnOnce(&FuncType) -> R,
317 ) -> R {
318 self.engine.resolve_func_type(func_type, f)
319 }
320
321 /// Returns a shared reference to the [`GlobalEntity`] associated to the given [`Global`].
322 ///
323 /// # Panics
324 ///
325 /// - If the [`Global`] does not originate from this [`Store`].
326 /// - If the [`Global`] cannot be resolved to its entity.
327 pub fn resolve_global(&self, global: Global) -> &GlobalEntity {
328 self.resolve(global.into_inner(), &self.globals)
329 }
330
331 /// Returns an exclusive reference to the [`GlobalEntity`] associated to the given [`Global`].
332 ///
333 /// # Panics
334 ///
335 /// - If the [`Global`] does not originate from this [`Store`].
336 /// - If the [`Global`] cannot be resolved to its entity.
337 pub fn resolve_global_mut(&mut self, global: Global) -> &mut GlobalEntity {
338 let idx = self.unwrap_stored(global.into_inner());
339 Self::resolve_mut(idx, &mut self.globals)
340 }
341
342 /// Returns a shared reference to the [`TableEntity`] associated to the given [`Table`].
343 ///
344 /// # Panics
345 ///
346 /// - If the [`Table`] does not originate from this [`Store`].
347 /// - If the [`Table`] cannot be resolved to its entity.
348 pub fn resolve_table(&self, table: Table) -> &TableEntity {
349 self.resolve(table.into_inner(), &self.tables)
350 }
351
352 /// Returns an exclusive reference to the [`TableEntity`] associated to the given [`Table`].
353 ///
354 /// # Panics
355 ///
356 /// - If the [`Table`] does not originate from this [`Store`].
357 /// - If the [`Table`] cannot be resolved to its entity.
358 pub fn resolve_table_mut(&mut self, table: Table) -> &mut TableEntity {
359 let idx = self.unwrap_stored(table.into_inner());
360 Self::resolve_mut(idx, &mut self.tables)
361 }
362
363 /// Returns a shared reference to the [`MemoryEntity`] associated to the given [`Memory`].
364 ///
365 /// # Panics
366 ///
367 /// - If the [`Memory`] does not originate from this [`Store`].
368 /// - If the [`Memory`] cannot be resolved to its entity.
369 pub fn resolve_memory(&self, memory: Memory) -> &MemoryEntity {
370 self.resolve(memory.into_inner(), &self.memories)
371 }
372
373 /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`].
374 ///
375 /// # Panics
376 ///
377 /// - If the [`Memory`] does not originate from this [`Store`].
378 /// - If the [`Memory`] cannot be resolved to its entity.
379 pub fn resolve_memory_mut(&mut self, memory: Memory) -> &mut MemoryEntity {
380 let idx = self.unwrap_stored(memory.into_inner());
381 Self::resolve_mut(idx, &mut self.memories)
382 }
383
384 /// Returns a shared reference to the [`InstanceEntity`] associated to the given [`Instance`].
385 ///
386 /// # Panics
387 ///
388 /// - If the [`Instance`] does not originate from this [`Store`].
389 /// - If the [`Instance`] cannot be resolved to its entity.
390 pub fn resolve_instance(&self, instance: Instance) -> &InstanceEntity {
391 self.resolve(instance.into_inner(), &self.instances)
392 }
393}
394
395impl<T> Store<T> {
396 /// Creates a new store.
397 pub fn new(engine: &Engine, data: T) -> Self {
398 Self {
399 inner: StoreInner::new(engine),
400 funcs: Arena::new(),
401 data,
402 }
403 }
404
405 /// Returns the [`Engine`] that this store is associated with.
406 pub fn engine(&self) -> &Engine {
407 self.inner.engine()
408 }
409
410 /// Returns a shared reference to the user provided data owned by this [`Store`].
411 pub fn data(&self) -> &T {
412 &self.data
413 }
414
415 /// Returns an exclusive reference to the user provided data owned by this [`Store`].
416 pub fn data_mut(&mut self) -> &mut T {
417 &mut self.data
418 }
419
420 /// Consumes `self` and returns its user provided data.
421 pub fn into_data(self) -> T {
422 self.data
423 }
424
425 /// Wraps an entitiy `Idx` (index type) as a [`Stored<Idx>`] type.
426 ///
427 /// # Note
428 ///
429 /// [`Stored<Idx>`] associates an `Idx` type with the internal store index.
430 /// This way wrapped indices cannot be misused with incorrect [`Store`] instances.
431 fn wrap_stored<Idx>(&self, entity_idx: Idx) -> Stored<Idx> {
432 self.inner.wrap_stored(entity_idx)
433 }
434
435 /// Unwraps the given [`Stored<Idx>`] reference and returns the `Idx`.
436 ///
437 /// # Panics
438 ///
439 /// If the [`Stored<Idx>`] does not originate from this [`Store`].
440 fn unwrap_stored<Idx>(&self, stored: Stored<Idx>) -> Idx
441 where
442 Idx: ArenaIndex + Debug,
443 {
444 self.inner.unwrap_stored(stored)
445 }
446
447 /// Allocates a new [`FuncType`] and returns a [`DedupFuncType`] reference to it.
448 ///
449 /// # Note
450 ///
451 /// This deduplicates [`FuncType`] instances that compare as equal.
452 pub(super) fn alloc_func_type(&mut self, func_type: FuncType) -> DedupFuncType {
453 self.inner.alloc_func_type(func_type)
454 }
455
456 /// Allocates a new [`GlobalEntity`] and returns a [`Global`] reference to it.
457 pub(super) fn alloc_global(&mut self, global: GlobalEntity) -> Global {
458 self.inner.alloc_global(global)
459 }
460
461 /// Allocates a new [`TableEntity`] and returns a [`Table`] reference to it.
462 pub(super) fn alloc_table(&mut self, table: TableEntity) -> Table {
463 self.inner.alloc_table(table)
464 }
465
466 /// Allocates a new [`MemoryEntity`] and returns a [`Memory`] reference to it.
467 pub(super) fn alloc_memory(&mut self, memory: MemoryEntity) -> Memory {
468 self.inner.alloc_memory(memory)
469 }
470
471 /// Allocates a new Wasm or host [`FuncEntity`] and returns a [`Func`] reference to it.
472 pub(super) fn alloc_func(&mut self, func: FuncEntity<T>) -> Func {
473 let func_type = func.ty_dedup();
474 let idx = self.funcs.alloc(func);
475 let func = Func::from_inner(self.wrap_stored(idx));
476 self.inner.register_func_type(func, func_type);
477 func
478 }
479
480 /// Allocates a new uninitialized [`InstanceEntity`] and returns an [`Instance`] reference to it.
481 ///
482 /// # Note
483 ///
484 /// - This will create an uninitialized dummy [`InstanceEntity`] as a place holder
485 /// for the returned [`Instance`]. Using this uninitialized [`Instance`] will result
486 /// in a runtime panic.
487 /// - The returned [`Instance`] must later be initialized via the [`Store::initialize_instance`]
488 /// method. Afterwards the [`Instance`] may be used.
489 pub(super) fn alloc_instance(&mut self) -> Instance {
490 self.inner.alloc_instance()
491 }
492
493 /// Initializes the [`Instance`] using the given [`InstanceEntity`].
494 ///
495 /// # Note
496 ///
497 /// After this operation the [`Instance`] is initialized and can be used.
498 ///
499 /// # Panics
500 ///
501 /// - If the [`Instance`] does not belong to the [`Store`].
502 /// - If the [`Instance`] is unknown to the [`Store`].
503 /// - If the [`Instance`] has already been initialized.
504 /// - If the given [`InstanceEntity`] is itself not initialized, yet.
505 pub(super) fn initialize_instance(&mut self, instance: Instance, init: InstanceEntity) {
506 self.inner.initialize_instance(instance, init)
507 }
508
509 /// Returns the [`FuncType`] associated to the given [`DedupFuncType`].
510 ///
511 /// # Panics
512 ///
513 /// - If the [`DedupFuncType`] does not originate from this [`Store`].
514 /// - If the [`DedupFuncType`] cannot be resolved to its entity.
515 pub(super) fn resolve_func_type(&self, func_type: DedupFuncType) -> FuncType {
516 self.inner.resolve_func_type(func_type)
517 }
518
519 /// Calls `f` on the [`FuncType`] associated to the given [`DedupFuncType`] and returns the result.
520 ///
521 /// # Panics
522 ///
523 /// - If the [`DedupFuncType`] does not originate from this [`Store`].
524 /// - If the [`DedupFuncType`] cannot be resolved to its entity.
525 pub(super) fn resolve_func_type_with<R>(
526 &self,
527 func_type: DedupFuncType,
528 f: impl FnOnce(&FuncType) -> R,
529 ) -> R {
530 self.inner.resolve_func_type_with(func_type, f)
531 }
532
533 /// Returns a shared reference to the [`GlobalEntity`] associated to the given [`Global`].
534 ///
535 /// # Panics
536 ///
537 /// - If the [`Global`] does not originate from this [`Store`].
538 /// - If the [`Global`] cannot be resolved to its entity.
539 pub(super) fn resolve_global(&self, global: Global) -> &GlobalEntity {
540 self.inner.resolve_global(global)
541 }
542
543 /// Returns an exclusive reference to the [`GlobalEntity`] associated to the given [`Global`].
544 ///
545 /// # Panics
546 ///
547 /// - If the [`Global`] does not originate from this [`Store`].
548 /// - If the [`Global`] cannot be resolved to its entity.
549 pub(super) fn resolve_global_mut(&mut self, global: Global) -> &mut GlobalEntity {
550 self.inner.resolve_global_mut(global)
551 }
552
553 /// Returns a shared reference to the [`TableEntity`] associated to the given [`Table`].
554 ///
555 /// # Panics
556 ///
557 /// - If the [`Table`] does not originate from this [`Store`].
558 /// - If the [`Table`] cannot be resolved to its entity.
559 pub(super) fn resolve_table(&self, table: Table) -> &TableEntity {
560 self.inner.resolve_table(table)
561 }
562
563 /// Returns an exclusive reference to the [`TableEntity`] associated to the given [`Table`].
564 ///
565 /// # Panics
566 ///
567 /// - If the [`Table`] does not originate from this [`Store`].
568 /// - If the [`Table`] cannot be resolved to its entity.
569 pub(super) fn resolve_table_mut(&mut self, table: Table) -> &mut TableEntity {
570 self.inner.resolve_table_mut(table)
571 }
572
573 /// Returns a shared reference to the [`MemoryEntity`] associated to the given [`Memory`].
574 ///
575 /// # Panics
576 ///
577 /// - If the [`Memory`] does not originate from this [`Store`].
578 /// - If the [`Memory`] cannot be resolved to its entity.
579 pub(super) fn resolve_memory(&self, memory: Memory) -> &MemoryEntity {
580 self.inner.resolve_memory(memory)
581 }
582
583 /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`].
584 ///
585 /// # Panics
586 ///
587 /// - If the [`Memory`] does not originate from this [`Store`].
588 /// - If the [`Memory`] cannot be resolved to its entity.
589 pub(super) fn resolve_memory_mut(&mut self, memory: Memory) -> &mut MemoryEntity {
590 self.inner.resolve_memory_mut(memory)
591 }
592
593 /// Returns an exclusive reference to the [`MemoryEntity`] associated to the given [`Memory`]
594 /// and an exclusive reference to the user provided host state.
595 ///
596 /// # Panics
597 ///
598 /// - If the [`Memory`] does not originate from this [`Store`].
599 /// - If the [`Memory`] cannot be resolved to its entity.
600 pub(super) fn resolve_memory_and_state_mut(
601 &mut self,
602 memory: Memory,
603 ) -> (&mut MemoryEntity, &mut T) {
604 (self.inner.resolve_memory_mut(memory), &mut self.data)
605 }
606
607 /// Returns a shared reference to the associated entity of the Wasm or host function.
608 ///
609 /// # Panics
610 ///
611 /// - If the [`Func`] does not originate from this [`Store`].
612 /// - If the [`Func`] cannot be resolved to its entity.
613 pub(super) fn resolve_func(&self, func: Func) -> &FuncEntity<T> {
614 let entity_index = self.unwrap_stored(func.into_inner());
615 self.funcs.get(entity_index).unwrap_or_else(|| {
616 panic!("failed to resolve stored Wasm or host function: {entity_index:?}")
617 })
618 }
619
620 /// Returns a shared reference to the associated entity of the [`Instance`].
621 ///
622 /// # Panics
623 ///
624 /// - If the [`Instance`] does not originate from this [`Store`].
625 /// - If the [`Instance`] cannot be resolved to its entity.
626 pub(super) fn resolve_instance(&self, instance: Instance) -> &InstanceEntity {
627 self.inner.resolve_instance(instance)
628 }
629}
630
631/// A trait used to get shared access to a [`Store`] in `wasmi`.
632pub trait AsContext {
633 /// The user state associated with the [`Store`], aka the `T` in `Store<T>`.
634 type UserState;
635
636 /// Returns the store context that this type provides access to.
637 fn as_context(&self) -> StoreContext<Self::UserState>;
638}
639
640/// A trait used to get exclusive access to a [`Store`] in `wasmi`.
641pub trait AsContextMut: AsContext {
642 /// Returns the store context that this type provides access to.
643 fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState>;
644}
645
646/// A temporary handle to a [`&Store<T>`][`Store`].
647///
648/// This type is suitable for [`AsContext`] trait bounds on methods if desired.
649/// For more information, see [`Store`].
650#[derive(Debug, Copy, Clone)]
651#[repr(transparent)]
652pub struct StoreContext<'a, T> {
653 pub(super) store: &'a Store<T>,
654}
655
656impl<'a, T> StoreContext<'a, T> {
657 /// Returns the underlying [`Engine`] this store is connected to.
658 pub fn engine(&self) -> &Engine {
659 self.store.engine()
660 }
661
662 /// Access the underlying data owned by this store.
663 ///
664 /// Same as [`Store::data`].
665 pub fn data(&self) -> &T {
666 self.store.data()
667 }
668}
669
670impl<'a, T: AsContext> From<&'a T> for StoreContext<'a, T::UserState> {
671 #[inline]
672 fn from(ctx: &'a T) -> Self {
673 ctx.as_context()
674 }
675}
676
677impl<'a, T: AsContext> From<&'a mut T> for StoreContext<'a, T::UserState> {
678 #[inline]
679 fn from(ctx: &'a mut T) -> Self {
680 T::as_context(ctx)
681 }
682}
683
684impl<'a, T: AsContextMut> From<&'a mut T> for StoreContextMut<'a, T::UserState> {
685 #[inline]
686 fn from(ctx: &'a mut T) -> Self {
687 ctx.as_context_mut()
688 }
689}
690
691/// A temporary handle to a [`&mut Store<T>`][`Store`].
692///
693/// This type is suitable for [`AsContextMut`] or [`AsContext`] trait bounds on methods if desired.
694/// For more information, see [`Store`].
695#[derive(Debug)]
696#[repr(transparent)]
697pub struct StoreContextMut<'a, T> {
698 pub(super) store: &'a mut Store<T>,
699}
700
701impl<'a, T> StoreContextMut<'a, T> {
702 /// Returns the underlying [`Engine`] this store is connected to.
703 pub fn engine(&self) -> &Engine {
704 self.store.engine()
705 }
706
707 /// Access the underlying data owned by this store.
708 ///
709 /// Same as [`Store::data`].
710 pub fn data(&self) -> &T {
711 self.store.data()
712 }
713
714 /// Access the underlying data owned by this store.
715 ///
716 /// Same as [`Store::data_mut`].
717 pub fn data_mut(&mut self) -> &mut T {
718 self.store.data_mut()
719 }
720}
721
722impl<T> AsContext for &'_ T
723where
724 T: AsContext,
725{
726 type UserState = T::UserState;
727
728 #[inline]
729 fn as_context(&self) -> StoreContext<'_, T::UserState> {
730 T::as_context(*self)
731 }
732}
733
734impl<T> AsContext for &'_ mut T
735where
736 T: AsContext,
737{
738 type UserState = T::UserState;
739
740 #[inline]
741 fn as_context(&self) -> StoreContext<'_, T::UserState> {
742 T::as_context(*self)
743 }
744}
745
746impl<T> AsContextMut for &'_ mut T
747where
748 T: AsContextMut,
749{
750 #[inline]
751 fn as_context_mut(&mut self) -> StoreContextMut<'_, T::UserState> {
752 T::as_context_mut(*self)
753 }
754}
755
756impl<T> AsContext for StoreContext<'_, T> {
757 type UserState = T;
758
759 #[inline]
760 fn as_context(&self) -> StoreContext<'_, Self::UserState> {
761 StoreContext { store: self.store }
762 }
763}
764
765impl<T> AsContext for StoreContextMut<'_, T> {
766 type UserState = T;
767
768 #[inline]
769 fn as_context(&self) -> StoreContext<'_, Self::UserState> {
770 StoreContext { store: self.store }
771 }
772}
773
774impl<T> AsContextMut for StoreContextMut<'_, T> {
775 #[inline]
776 fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::UserState> {
777 StoreContextMut {
778 store: &mut *self.store,
779 }
780 }
781}
782
783impl<T> AsContext for Store<T> {
784 type UserState = T;
785
786 #[inline]
787 fn as_context(&self) -> StoreContext<'_, Self::UserState> {
788 StoreContext { store: self }
789 }
790}
791
792impl<T> AsContextMut for Store<T> {
793 #[inline]
794 fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::UserState> {
795 StoreContextMut { store: self }
796 }
797}