1 use crate::runtime::vm::VMStore; 2 use crate::{StoreContextMut, store::StoreId}; 3 use core::marker::PhantomData; 4 5 /// Represents a proof that a store with a given `StoreId` has a data type 6 /// parameter `T`. 7 /// 8 /// This may be used to safely convert a `&mut dyn VMStore` into a 9 /// `StoreContextMut<T>` using `StoreToken::as_context_mut` having witnessed 10 /// that the type parameter matches what was seen earlier in `StoreToken::new`. 11 pub struct StoreToken<T> { 12 id: StoreId, 13 _phantom: PhantomData<fn() -> T>, 14 } 15 16 impl<T> Clone for StoreToken<T> { 17 fn clone(&self) -> Self { 18 Self { 19 id: self.id, 20 _phantom: PhantomData, 21 } 22 } 23 } 24 25 impl<T> Copy for StoreToken<T> {} 26 27 impl<T: 'static> StoreToken<T> { 28 /// Create a new `StoreToken`, witnessing that this store has data type 29 /// parameter `T`. 30 pub fn new(store: StoreContextMut<T>) -> Self { 31 Self { 32 id: store.0.id(), 33 _phantom: PhantomData, 34 } 35 } 36 37 /// Convert the specified `&mut dyn VMStore` into a `StoreContextMut<T>`. 38 /// 39 /// This will panic if passed a store with a different `StoreId` than the 40 /// one passed to `StoreToken::new` when creating this object. 41 pub fn as_context_mut<'a>(&self, store: &'a mut dyn VMStore) -> StoreContextMut<'a, T> { 42 assert_eq!(store.store_opaque().id(), self.id); 43 // SAFETY: We know the store with this ID has data type parameter `T` 44 // because we witnessed that in `Self::new`, which is the only way 45 // `self` could have been safely created: 46 unsafe { store.unchecked_context_mut::<T>() } 47 } 48 } 49