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}