use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::ptr::{self, NonNull};
use super::allocator::Arena;
unsafe impl<T: Send> Send for ArenaBox<'_, T> {}
unsafe impl<T: Sync> Sync for ArenaBox<'_, T> {}
#[repr(transparent)]
pub struct ArenaBox<'arena, T: ?Sized> {
ptr: NonNull<T>,
_marker: PhantomData<&'arena mut T>,
}
impl<'arena, T> ArenaBox<'arena, T> {
#[inline]
pub(crate) fn new(arena: &'arena mut Arena, val: T) -> Self {
if mem::size_of::<T>() == 0 {
let ptr = NonNull::<T>::dangling();
unsafe { ptr.as_ptr().write(val) };
return ArenaBox {
ptr,
_marker: PhantomData,
};
}
let raw = arena.alloc_raw(mem::size_of::<T>(), mem::align_of::<T>());
unsafe {
let typed = raw.as_ptr().cast::<T>();
typed.write(val);
ArenaBox {
ptr: NonNull::new_unchecked(typed),
_marker: PhantomData,
}
}
}
#[inline]
#[must_use = "use `drop` to discard the inner value explicitly"]
pub fn into_inner(self) -> T {
let this = ManuallyDrop::new(self);
unsafe { ptr::read(this.ptr.as_ptr()) }
}
#[inline]
pub unsafe fn from_raw(_arena: &'arena mut Arena, ptr: NonNull<T>) -> Self {
ArenaBox {
ptr,
_marker: PhantomData,
}
}
#[inline]
pub fn new_with<F>(arena: &'arena mut Arena, f: F) -> Self
where
F: FnOnce() -> T,
{
Self::new(arena, f())
}
#[inline]
pub fn new_uninit(arena: &'arena mut Arena) -> ArenaBox<'arena, MaybeUninit<T>> {
if mem::size_of::<T>() == 0 {
return ArenaBox {
ptr: NonNull::<MaybeUninit<T>>::dangling(),
_marker: PhantomData,
};
}
let raw = arena.alloc_raw(mem::size_of::<T>(), mem::align_of::<T>());
ArenaBox {
ptr: raw.cast::<MaybeUninit<T>>(),
_marker: PhantomData,
}
}
}
impl<'arena, T> ArenaBox<'arena, MaybeUninit<T>> {
#[inline]
#[must_use]
pub unsafe fn assume_init(self) -> ArenaBox<'arena, T> {
let this = ManuallyDrop::new(self);
ArenaBox {
ptr: this.ptr.cast::<T>(),
_marker: PhantomData,
}
}
}
impl<'arena, T: ?Sized> ArenaBox<'arena, T> {
#[inline]
pub fn as_ptr(&self) -> *const T {
self.ptr.as_ptr()
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.ptr.as_ptr()
}
#[inline]
#[must_use = "discarding the raw pointer leaks T's destructor"]
pub fn into_raw(b: Self) -> NonNull<T> {
let this = ManuallyDrop::new(b);
this.ptr
}
#[inline]
#[must_use = "leak() returns a reference; discarding it abandons the value"]
pub fn leak(b: Self) -> &'arena mut T {
let this = ManuallyDrop::new(b);
unsafe { &mut *this.ptr.as_ptr() }
}
}
impl<'arena, T: ?Sized> Deref for ArenaBox<'arena, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.ptr.as_ref() }
}
}
impl<'arena, T: ?Sized> DerefMut for ArenaBox<'arena, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { self.ptr.as_mut() }
}
}
impl<T: ?Sized> Drop for ArenaBox<'_, T> {
#[inline]
fn drop(&mut self) {
unsafe { ptr::drop_in_place(self.ptr.as_ptr()) };
}
}
impl<T: ?Sized + core::fmt::Debug> core::fmt::Debug for ArenaBox<'_, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(&**self, f)
}
}
impl<T: ?Sized + core::fmt::Display> core::fmt::Display for ArenaBox<'_, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Display::fmt(&**self, f)
}
}
impl<T: ?Sized> core::fmt::Pointer for ArenaBox<'_, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Pointer::fmt(&self.ptr.as_ptr(), f)
}
}
impl<T: ?Sized + PartialEq> PartialEq for ArenaBox<'_, T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&**self, &**other)
}
}
impl<T: ?Sized + Eq> Eq for ArenaBox<'_, T> {}
impl<T: ?Sized + PartialOrd> PartialOrd for ArenaBox<'_, T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<T: ?Sized + Ord> Ord for ArenaBox<'_, T> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<T: ?Sized + Hash> Hash for ArenaBox<'_, T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<T: ?Sized> AsRef<T> for ArenaBox<'_, T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}
impl<T: ?Sized> AsMut<T> for ArenaBox<'_, T> {
#[inline]
fn as_mut(&mut self) -> &mut T {
self
}
}
impl<T: ?Sized> core::borrow::Borrow<T> for ArenaBox<'_, T> {
#[inline]
fn borrow(&self) -> &T {
self
}
}
impl<T: ?Sized> core::borrow::BorrowMut<T> for ArenaBox<'_, T> {
#[inline]
fn borrow_mut(&mut self) -> &mut T {
self
}
}