1 use crate::error::OutOfMemory;
2 use crate::prelude::*;
3 use crate::runtime::vm::SendSyncPtr;
4 use core::ptr::NonNull;
5 
6 /// A `Box<T>` lookalike for memory that's stored in a `Store<T>`
7 ///
8 /// This is intended to be quite similar to a `Box<T>` except without the
9 /// `Deref` implementations. The main motivation for this type's existence is to
10 /// appease the aliasing rules in miri to ensure that `StoreBox` can be moved
11 /// around without invalidating pointers to the contents within the box. The
12 /// standard `Box<T>` type does not implement this for example and moving that
13 /// will invalidate derived pointers.
14 pub struct StoreBox<T: ?Sized>(SendSyncPtr<T>);
15 
16 impl<T> StoreBox<T> {
17     /// Allocates space on the heap to store `val` and returns a pointer to it
18     /// living on the heap.
new(val: T) -> Result<StoreBox<T>, OutOfMemory>19     pub fn new(val: T) -> Result<StoreBox<T>, OutOfMemory> {
20         let ptr = Box::into_raw(try_new(val)?);
21         Ok(StoreBox(SendSyncPtr::from(NonNull::new(ptr).unwrap())))
22     }
23 }
24 
25 impl<T: ?Sized> StoreBox<T> {
26     /// Returns the underlying pointer to `T` which is owned by the store.
get(&self) -> NonNull<T>27     pub fn get(&self) -> NonNull<T> {
28         self.0.as_non_null()
29     }
30 }
31 
32 impl<T: ?Sized> Drop for StoreBox<T> {
drop(&mut self)33     fn drop(&mut self) {
34         unsafe {
35             drop(Box::from_raw(self.0.as_ptr()));
36         }
37     }
38 }
39