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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
//! A pointer type for memory allocation.
use ::core::{
alloc::Layout,
fmt,
mem::ManuallyDrop,
ops::{Deref, DerefMut},
ptr::NonNull,
};
use ::heresy::alloc::Allocator;
#[cfg(feature = "alloc")]
use ::heresy::alloc::Global;
use ::mischief::{Frame, Metadata, Pointer, RegionalAllocator, Within};
use ::ptr_meta::Pointee;
use crate::{
fmt::{DebugRaw, DisplayRaw},
DropRaw,
Mut,
Ref,
};
/// A pointer type for memory allocation.
pub struct OwnedVal<
T: DropRaw + ?Sized,
#[cfg(feature = "alloc")] A: Allocator = Global,
#[cfg(not(feature = "alloc"))] A: Allocator,
> {
ptr: NonNull<T>,
alloc: A,
}
impl<T: DropRaw + ?Sized, A: Allocator> Drop for OwnedVal<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 {
T::drop_raw(self.as_mut());
}
// 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: DropRaw + ?Sized, A: Allocator> OwnedVal<T, A> {
/// Returns a reference to the underlying allocator.
///
/// Note: this is an associated function, which means that you have to call
/// it as `OwnedVal::allocator(&v)` instead of `owned_val.allocator()`. This
/// is so that there is no conflict with a method on the inner type.
pub fn allocator(v: &Self) -> &A {
&v.alloc
}
/// Constructs an owned `Val` from a raw pointer in the given allocator.
///
/// After calling this function, the raw pointer is owned by the resulting
/// `OwnedVal`. Specifically, the `OwnedVal` destructor will call the
/// `DropRaw` 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 `OwnedVal`.
///
/// # 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,
}
}
/// Constructs an owned `Val` from an initialized `Frame`.
///
/// # Safety
///
/// `frame` must be initialized.
pub unsafe fn assume_init(frame: Frame<T, A>) -> Self
where
T: Pointee,
<T as Pointee>::Metadata: Metadata<T>,
{
let (ptr, alloc) = Frame::into_raw_with_allocator(frame);
// SAFETY:
// - `Frame`'s `ptr` is always allocated in its returned `alloc` with
// the layout returned from `Metadata::pointee_layout` (which is
// equivalent to `Layout::for_value`).
// - The caller has guaranteed that `frame`'s pointer is initialized.
unsafe { Self::from_raw_in(ptr, alloc) }
}
/// Consumes the `OwnedVal`, 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 `OwnedVal`. In particular, the caller should
/// properly destroy `T` with `DropRaw` and release the memory, taking into
/// account the memory layout used by `OwnedVal`. The easiest way to do this
/// is to convert the raw pointer back into an `OwnedVal` with the
/// `OwnedVal::from_raw_in` function, allowing the `OwnedVal` destructor to
/// perform the cleanup.
///
/// Note: this is an associated function, which means that you have to call
/// it as `OwnedVal::into_raw(b)` instead of `b.into_raw()`. This is so that
/// there is no conflict with a method on the inner type.
pub fn into_raw_parts(b: Self) -> (*mut T, A) {
let b = ManuallyDrop::new(b);
// SAFETY: `b.alloc` is a valid `A` that is moved into the return value
// and not dropped.
let alloc = unsafe { ::core::ptr::read(&b.alloc) };
(b.ptr.as_ptr(), alloc)
}
/// Returns a `Ref` of the owned value.
pub fn as_ref(&self) -> Ref<'_, T> {
// SAFETY: `self.ptr` is always non-null, properly aligned, and valid
// for reads. Because `self` owns the value and it is borrowed, the
// value pointed to by `self.ptr` may only be aliased by shared
// references. And finally, it's an invariant of `OwnedVal` that the
// value pointed to is initialized.
unsafe { Ref::new_unchecked(self.ptr.as_ptr()) }
}
/// Returns a `Mut` of the owned value.
pub fn as_mut(&mut self) -> Mut<'_, T> {
// SAFETY: `self.ptr` is always non-null, properly aligned, and valid
// for reads. Because `self` owns the value and it is mutably borrowed,
// the value pointed to by `self.ptr` may not be aliased. And finally,
// it's an invariant of `OwnedVal` that the value pointed to is
// initialized.
unsafe { Mut::new_unchecked(self.ptr.as_ptr()) }
}
}
impl<T: DropRaw, A: Allocator> OwnedVal<T, A> {
/// Allocates memory in the given allocator then places `x` into it.
pub fn new_in(x: T, alloc: A) -> OwnedVal<T, A> {
let mut frame = Frame::new_in(alloc);
frame.write(x);
// SAFETY: We initialized `frame` by writing to it.
unsafe { Self::assume_init(frame) }
}
}
#[cfg(feature = "alloc")]
impl<T: DropRaw> OwnedVal<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)
}
}
// SAFETY: `OwnedVal` returns the same value from `target`, `deref`, and
// `deref_mut`.
unsafe impl<T, A> Pointer for OwnedVal<T, A>
where
T: DropRaw + Pointee + ?Sized,
A: Allocator,
{
type Target = T;
fn target(&self) -> *mut Self::Target {
OwnedVal::as_ref(self).as_ptr()
}
}
// SAFETY: The pointee of `OwnedVal<T, A>` is located in `A::Region` because it
// is allocated in `A`.
unsafe impl<T, A> Within<A::Region> for OwnedVal<T, A>
where
T: DropRaw + Pointee + ?Sized,
A: RegionalAllocator,
{
}
impl<T: DropRaw + ?Sized, A: Allocator> Deref for OwnedVal<T, A> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
// SAFETY:
// - `self.ptr` is always properly aligned and dereferenceable.
// - `self.ptr` always points to an initialized value of `T`.
// - Because `OwnedVal<T, A>` is borrowed for `'_`, the returned
// reference is also valid for `'_` and has shared read-only aliasing.
unsafe { &*self.ptr.as_ptr() }
}
}
// Note that `T` must be `Unpin` to avoid violating the immovability invariant
// of `OwnedVal`.
impl<T: DropRaw + Unpin + ?Sized, A: Allocator> DerefMut for OwnedVal<T, A> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
// SAFETY:
// - `self.ptr` is always properly aligned and dereferenceable.
// - `self.ptr` always points to an initialized value of `T`.
// - Because `OwnedVal<T, A>` is mutably borrowed for `'_`, the returned
// reference is also valid for `'_` and has unique read-write
// aliasing.
unsafe { &mut *self.ptr.as_ptr() }
}
}
impl<T, A> fmt::Debug for OwnedVal<T, A>
where
T: DebugRaw + DropRaw + ?Sized,
A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
DebugRaw::fmt_raw(self.as_ref(), f)
}
}
impl<T, A> fmt::Display for OwnedVal<T, A>
where
T: DisplayRaw + DropRaw + ?Sized,
A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
DisplayRaw::fmt_raw(self.as_ref(), f)
}
}