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