1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
//! A pointer type for memory allocation.
use ::core::{
alloc::Layout,
fmt::{Debug, Display},
mem::ManuallyDrop,
ops::{Deref, DerefMut},
ptr::{read, NonNull},
};
use crate::alloc::Allocator;
#[cfg(feature = "alloc")]
use crate::alloc::Global;
/// A pointer type for memory allocation.
pub struct Box<
T: ?Sized,
#[cfg(feature = "alloc")] A: Allocator = Global,
#[cfg(not(feature = "alloc"))] A: Allocator,
> {
ptr: NonNull<T>,
alloc: A,
}
impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
fn drop(&mut self) {
let layout = Layout::for_value(&**self);
// SAFETY: `self.ptr` is always valid for reads and writes, properly
// aligned, and valid for dropping.
unsafe {
self.ptr.as_ptr().drop_in_place();
}
// SAFETY: `self.ptr` is always allocated via `self.alloc` and `layout`
// is guaranteed to fit it.
unsafe {
self.alloc.deallocate(self.ptr.cast(), layout);
}
}
}
impl<T: ?Sized, A: Allocator> Box<T, A> {
/// Constructs a box from a raw pointer in the given allocator.
///
/// After calling this function, the raw pointer is owned by the resulting
/// `Box`. Specifically, the `Box` destructor will call the destructor of
/// `T` and free the allocated memory. For this to be safe, the memory must
/// have been allocated in accordance with the memory layout used by `Box`.
///
/// # Safety
///
/// - `ptr` must point to a memory block currently allocated by `alloc`.
/// - The layout used to allocate `ptr` must exactly match the return value
/// of `Layout::for_value`.
/// - `ptr` must point to an initialized `T`.
pub unsafe fn from_raw_in(ptr: *mut T, alloc: A) -> Self {
Self {
// SAFETY: `ptr` is allocated by `alloc`, and so must not be null.
ptr: unsafe { NonNull::new_unchecked(ptr) },
alloc,
}
}
/// Consumes the `Box`, returning a wrapped raw pointer and the allocator.
///
/// The pointer will be properly aligned and non-null.
///
/// After calling this function, the caller is responsible for the memory
/// previously managed by the `Box`. In particular, the caller should
/// properly destroy `T` and release the memory, taking into account the
/// memory layout used by `Box`. The easiest way to do this is to convert
/// the raw pointer back into a `Box` with the `Box::from_raw_in` function,
/// allowing the `Box` destructor to perform the cleanup.
///
/// Note: this is an associated function, which means that you have to call
/// it as `Box::into_raw_with_allocator(b)` instead of
/// `b.into_raw_with_allocator()`. This is so that there is no conflict with
/// a method on the inner type.
pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
let b = ManuallyDrop::new(b);
// SAFETY: Because it is a reference, `b.alloc` is valid for reads,
// properly aligned, and points to a properly initialized `A`. The
// original will never be accessed or dropped.
(b.ptr.as_ptr(), unsafe { read(&b.alloc) })
}
}
impl<T, A: Allocator> Box<T, A> {
/// Allocates memory in the given allocator then places `x` into it.
pub fn new_in(x: T, alloc: A) -> Box<T, A> {
let ptr = alloc
.allocate(Layout::new::<T>())
.unwrap()
.as_ptr()
.cast::<T>();
// SAFETY: `ptr` is guaranteed to be properly aligned for a `T` and
// valid for writes because we just allocated it.
unsafe {
ptr.write(x);
}
// SAFETY: We allocated `ptr` in `alloc` with the layout of `T` and
// initialized it by writing `x`.
unsafe { Self::from_raw_in(ptr, alloc) }
}
}
#[cfg(feature = "alloc")]
impl<T> Box<T, Global> {
/// Allocates memory in the `Global` allocator and then places `x` into it.
pub fn new(x: T) -> Self {
Self::new_in(x, Global)
}
}
impl<T: Debug + ?Sized, A: Allocator> Debug for Box<T, A> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
T::fmt(self, f)
}
}
impl<T: Display + ?Sized, A: Allocator> Display for Box<T, A> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
T::fmt(self, f)
}
}
impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
// SAFETY:
// - `self.ptr` is always valid for reads, properly aligned, and always
// points to an initialized `T`.
// - The underlying `T` has the same aliasing as `self`.
unsafe { &*self.ptr.as_ptr() }
}
}
impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
// SAFETY:
// - `self.ptr` is always valid for reads, properly aligned, and always
// points to an intialized `T`.
// - The underlying `T` has the same aliasing as `self`.
unsafe { &mut *self.ptr.as_ptr() }
}
}