#[allow(unused_imports)] use super::allocator::{KVmalloc, Kmalloc, Vmalloc, VmallocPageIter};
use super::{AllocError, Allocator, Flags, NumaNode};
use core::alloc::Layout;
use core::borrow::{Borrow, BorrowMut};
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::mem::MaybeUninit;
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::ptr::NonNull;
use core::result::Result;
use crate::ffi::c_void;
use crate::fmt;
use crate::init::InPlaceInit;
use crate::page::AsPageIter;
use crate::types::ForeignOwnable;
use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption};
#[repr(transparent)]
#[derive(core::marker::CoercePointee)]
pub struct Box<#[pointee] T: ?Sized, A: Allocator>(NonNull<T>, PhantomData<A>);
pub type KBox<T> = Box<T, super::allocator::Kmalloc>;
pub type VBox<T> = Box<T, super::allocator::Vmalloc>;
pub type KVBox<T> = Box<T, super::allocator::KVmalloc>;
unsafe impl<T, A: Allocator> ZeroableOption for Box<T, A> {}
unsafe impl<T, A> Send for Box<T, A>
where
T: Send + ?Sized,
A: Allocator,
{
}
unsafe impl<T, A> Sync for Box<T, A>
where
T: Sync + ?Sized,
A: Allocator,
{
}
impl<T, A> Box<T, A>
where
T: ?Sized,
A: Allocator,
{
#[inline]
pub const unsafe fn from_raw(raw: *mut T) -> Self {
Self(unsafe { NonNull::new_unchecked(raw) }, PhantomData)
}
#[inline]
pub fn into_raw(b: Self) -> *mut T {
ManuallyDrop::new(b).0.as_ptr()
}
#[inline]
pub fn leak<'a>(b: Self) -> &'a mut T {
unsafe { &mut *Box::into_raw(b) }
}
}
impl<T, A> Box<MaybeUninit<T>, A>
where
A: Allocator,
{
pub unsafe fn assume_init(self) -> Box<T, A> {
let raw = Self::into_raw(self);
unsafe { Box::from_raw(raw.cast()) }
}
pub fn write(mut self, value: T) -> Box<T, A> {
(*self).write(value);
unsafe { self.assume_init() }
}
}
impl<T, A> Box<T, A>
where
A: Allocator,
{
pub fn new(x: T, flags: Flags) -> Result<Self, AllocError> {
let b = Self::new_uninit(flags)?;
Ok(Box::write(b, x))
}
pub fn new_uninit(flags: Flags) -> Result<Box<MaybeUninit<T>, A>, AllocError> {
let layout = Layout::new::<MaybeUninit<T>>();
let ptr = A::alloc(layout, flags, NumaNode::NO_NODE)?;
Ok(Box(ptr.cast(), PhantomData))
}
#[inline]
pub fn pin(x: T, flags: Flags) -> Result<Pin<Box<T, A>>, AllocError>
where
A: 'static,
{
Ok(Self::new(x, flags)?.into())
}
pub fn pin_slice<Func, Item, E>(
mut init: Func,
len: usize,
flags: Flags,
) -> Result<Pin<Box<[T], A>>, E>
where
Func: FnMut(usize) -> Item,
Item: PinInit<T, E>,
E: From<AllocError>,
{
let mut buffer = super::Vec::<T, A>::with_capacity(len, flags)?;
for i in 0..len {
let ptr = buffer.spare_capacity_mut().as_mut_ptr().cast();
unsafe { init(i).__pinned_init(ptr)? };
unsafe { buffer.inc_len(1) };
}
let (ptr, _, _) = buffer.into_raw_parts();
let slice = core::ptr::slice_from_raw_parts_mut(ptr, len);
Ok(Pin::from(unsafe { Box::from_raw(slice) }))
}
pub fn into_pin(this: Self) -> Pin<Self> {
this.into()
}
fn forget_contents(this: Self) -> Box<MaybeUninit<T>, A> {
let ptr = Self::into_raw(this);
unsafe { Box::from_raw(ptr.cast()) }
}
pub fn drop_contents(this: Self) -> Box<MaybeUninit<T>, A> {
let ptr = this.0.as_ptr();
unsafe { core::ptr::drop_in_place(ptr) };
Self::forget_contents(this)
}
pub fn into_inner(b: Self) -> T {
let value = unsafe { core::ptr::read(&*b) };
let _ = Self::forget_contents(b);
value
}
}
impl<T, A> From<Box<T, A>> for Pin<Box<T, A>>
where
T: ?Sized,
A: Allocator,
{
fn from(b: Box<T, A>) -> Self {
unsafe { Pin::new_unchecked(b) }
}
}
impl<T, A> InPlaceWrite<T> for Box<MaybeUninit<T>, A>
where
A: Allocator + 'static,
{
type Initialized = Box<T, A>;
fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
let slot = self.as_mut_ptr();
unsafe { init.__init(slot)? };
Ok(unsafe { Box::assume_init(self) })
}
fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
let slot = self.as_mut_ptr();
unsafe { init.__pinned_init(slot)? };
Ok(unsafe { Box::assume_init(self) }.into())
}
}
impl<T, A> InPlaceInit<T> for Box<T, A>
where
A: Allocator + 'static,
{
type PinnedSelf = Pin<Self>;
#[inline]
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E>
where
E: From<AllocError>,
{
Box::<_, A>::new_uninit(flags)?.write_pin_init(init)
}
#[inline]
fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
where
E: From<AllocError>,
{
Box::<_, A>::new_uninit(flags)?.write_init(init)
}
}
unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A>
where
A: Allocator,
{
const FOREIGN_ALIGN: usize = if core::mem::align_of::<T>() < A::MIN_ALIGN {
A::MIN_ALIGN
} else {
core::mem::align_of::<T>()
};
type Borrowed<'a> = &'a T;
type BorrowedMut<'a> = &'a mut T;
fn into_foreign(self) -> *mut c_void {
Box::into_raw(self).cast()
}
unsafe fn from_foreign(ptr: *mut c_void) -> Self {
unsafe { Box::from_raw(ptr.cast()) }
}
unsafe fn borrow<'a>(ptr: *mut c_void) -> &'a T {
unsafe { &*ptr.cast() }
}
unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> &'a mut T {
let ptr = ptr.cast();
unsafe { &mut *ptr }
}
}
unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
where
A: Allocator,
{
const FOREIGN_ALIGN: usize = <Box<T, A> as ForeignOwnable>::FOREIGN_ALIGN;
type Borrowed<'a> = Pin<&'a T>;
type BorrowedMut<'a> = Pin<&'a mut T>;
fn into_foreign(self) -> *mut c_void {
Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }).cast()
}
unsafe fn from_foreign(ptr: *mut c_void) -> Self {
unsafe { Pin::new_unchecked(Box::from_raw(ptr.cast())) }
}
unsafe fn borrow<'a>(ptr: *mut c_void) -> Pin<&'a T> {
let r = unsafe { &*ptr.cast() };
unsafe { Pin::new_unchecked(r) }
}
unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> Pin<&'a mut T> {
let ptr = ptr.cast();
let r = unsafe { &mut *ptr };
unsafe { Pin::new_unchecked(r) }
}
}
impl<T, A> Deref for Box<T, A>
where
T: ?Sized,
A: Allocator,
{
type Target = T;
fn deref(&self) -> &T {
unsafe { self.0.as_ref() }
}
}
impl<T, A> DerefMut for Box<T, A>
where
T: ?Sized,
A: Allocator,
{
fn deref_mut(&mut self) -> &mut T {
unsafe { self.0.as_mut() }
}
}
impl<T, A> Borrow<T> for Box<T, A>
where
T: ?Sized,
A: Allocator,
{
fn borrow(&self) -> &T {
self.deref()
}
}
impl<T, A> BorrowMut<T> for Box<T, A>
where
T: ?Sized,
A: Allocator,
{
fn borrow_mut(&mut self) -> &mut T {
self.deref_mut()
}
}
impl<T, A> fmt::Display for Box<T, A>
where
T: ?Sized + fmt::Display,
A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as fmt::Display>::fmt(&**self, f)
}
}
impl<T, A> fmt::Debug for Box<T, A>
where
T: ?Sized + fmt::Debug,
A: Allocator,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as fmt::Debug>::fmt(&**self, f)
}
}
impl<T, A> Drop for Box<T, A>
where
T: ?Sized,
A: Allocator,
{
fn drop(&mut self) {
let layout = Layout::for_value::<T>(self);
unsafe { core::ptr::drop_in_place::<T>(self.deref_mut()) };
unsafe { A::free(self.0.cast(), layout) };
}
}
impl<T> AsPageIter for VBox<T> {
type Iter<'a>
= VmallocPageIter<'a>
where
T: 'a;
fn page_iter(&mut self) -> Self::Iter<'_> {
let ptr = self.0.cast();
let size = core::mem::size_of::<T>();
unsafe { VmallocPageIter::new(ptr, size) }
}
}