use crate::{
alloc::{handle_alloc_error, AllocErr, AllocInit, AllocRef, Global, Layout},
clone::CloneIn,
collections::TryReserveError::{self, AllocError},
handle_reserve_error,
ptr::Unique,
raw_vec::RawVec,
};
use core::{
any::Any,
borrow,
cmp::Ordering,
fmt,
future::Future,
hash::{Hash, Hasher},
iter::FusedIterator,
mem,
mem::MaybeUninit,
ops::{Deref, DerefMut},
pin::Pin,
ptr::{self, NonNull},
task::{Context, Poll},
};
pub struct Box<T: ?Sized, A: AllocRef = Global> {
ptr: Unique<T>,
alloc: A,
}
#[allow(clippy::use_self)]
impl<T> Box<T> {
#[allow(clippy::inline_always)]
#[inline(always)]
#[must_use]
pub fn new(x: T) -> Self {
Self::new_in(x, Global)
}
#[allow(clippy::inline_always)]
#[inline(always)]
#[must_use]
pub fn new_uninit() -> Box<MaybeUninit<T>> {
Self::new_uninit_in(Global)
}
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn pin(x: T) -> Pin<Self> {
Self::pin_in(x, Global)
}
}
#[allow(clippy::use_self)]
impl<T, A: AllocRef> Box<T, A> {
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn new_in(x: T, a: A) -> Self {
match Self::try_new_in(x, a) {
Err(_) => handle_alloc_error(Layout::new::<T>()),
Ok(b) => b,
}
}
pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocErr> {
let mut boxed = Self::try_new_uninit_in(alloc)?;
unsafe {
boxed.ptr.as_mut().write(x);
Ok(boxed.assume_init())
}
}
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn new_uninit_in(a: A) -> Box<MaybeUninit<T>, A> {
match Self::try_new_uninit_in(a) {
Ok(b) => b,
Err(_) => handle_alloc_error(Layout::new::<T>()),
}
}
pub fn try_new_uninit_in(mut alloc: A) -> Result<Box<MaybeUninit<T>, A>, AllocErr> {
let memory = alloc.alloc(Layout::new::<MaybeUninit<T>>(), AllocInit::Uninitialized)?;
let ptr = memory.ptr;
unsafe { Ok(Box::from_raw_in(ptr.cast().as_ptr(), alloc)) }
}
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn pin_in(x: T, a: A) -> Pin<Self> {
Pin::from(Self::new_in(x, a))
}
#[inline]
pub fn try_pin_in(x: T, a: A) -> Result<Pin<Self>, AllocErr> {
Self::try_new_in(x, a).map(Pin::from)
}
}
#[allow(clippy::use_self)]
impl<T> Box<[T]> {
#[allow(clippy::inline_always)]
#[inline(always)]
#[must_use]
pub fn new_uninit_slice(len: usize) -> Box<[MaybeUninit<T>]> {
Self::new_uninit_slice_in(len, Global)
}
}
#[allow(clippy::use_self)]
impl<T, A: AllocRef> Box<[T], A> {
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn new_uninit_slice_in(len: usize, a: A) -> Box<[MaybeUninit<T>], A> {
handle_reserve_error(Self::try_new_uninit_slice_in(len, a))
}
pub fn try_new_uninit_slice_in(
len: usize,
a: A,
) -> Result<Box<[MaybeUninit<T>], A>, TryReserveError> {
unsafe { Ok(RawVec::try_with_capacity_in(len, a)?.into_box(len)) }
}
}
#[allow(clippy::use_self)]
impl<T, A: AllocRef> Box<MaybeUninit<T>, A> {
#[inline]
pub unsafe fn assume_init(self) -> Box<T, A> {
let (ptr, alloc) = Self::into_raw_alloc(self);
Box::from_raw_in((*ptr).as_mut_ptr(), alloc)
}
}
#[allow(clippy::use_self)]
impl<T, A: AllocRef> Box<[MaybeUninit<T>], A> {
#[inline]
pub unsafe fn assume_init(self) -> Box<[T], A> {
let (ptr, b) = Self::into_raw_alloc(self);
Box::from_raw_in(ptr as *mut [T], b)
}
}
impl<T: ?Sized> Box<T> {
#[allow(clippy::inline_always)]
#[inline(always)]
pub unsafe fn from_raw(raw: *mut T) -> Self {
Self::from_raw_in(raw, Global)
}
}
impl<T: ?Sized, A: AllocRef> Box<T, A> {
#[inline]
pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
Self {
ptr: Unique::new_unchecked(raw),
alloc,
}
}
pub fn build_alloc(&self) -> &A {
&self.alloc
}
pub fn build_alloc_mut(&mut self) -> &mut A {
&mut self.alloc
}
pub fn alloc_ref(&self) -> &A {
&self.alloc
}
pub fn alloc_ref_mut(&mut self) -> &mut A {
&mut self.alloc
}
#[inline]
pub fn into_raw(b: Self) -> *mut T {
Self::into_raw_alloc(b).0
}
#[inline]
pub fn into_raw_alloc(b: Self) -> (*mut T, A) {
let (p, b) = Self::into_raw_non_null_alloc(b);
(p.as_ptr(), b)
}
#[inline]
pub fn into_raw_non_null(b: Self) -> NonNull<T> {
Self::into_raw_non_null_alloc(b).0
}
#[inline]
pub fn into_raw_non_null_alloc(b: Self) -> (NonNull<T>, A) {
let (unique, alloc) = Self::into_unique_alloc(b);
(unique.into(), alloc)
}
#[inline]
#[doc(hidden)]
pub fn into_unique(b: Self) -> Unique<T> {
Self::into_unique_alloc(b).0
}
#[inline]
#[doc(hidden)]
pub fn into_unique_alloc(mut b: Self) -> (Unique<T>, A) {
let ptr = b.ptr;
let alloc = unsafe { ptr::read(b.alloc_ref_mut()) };
mem::forget(b);
(ptr, alloc)
}
#[inline]
pub fn leak<'a>(b: Self) -> &'a mut T
where
T: 'a, {
unsafe { &mut *Self::into_raw(b) }
}
pub fn into_pin(boxed: Self) -> Pin<Self> {
unsafe { Pin::new_unchecked(boxed) }
}
}
fn drop_box<T: ?Sized, A: AllocRef>(boxed: &mut Box<T, A>) {
unsafe {
let layout = Layout::for_value(boxed.as_ref());
let ptr = boxed.ptr;
ptr::drop_in_place(ptr.as_ptr());
boxed.alloc.dealloc(ptr.cast().into(), layout);
}
}
unsafe impl<#[may_dangle] T: ?Sized, A: AllocRef> Drop for Box<T, A> {
fn drop(&mut self) {
drop_box(self);
}
}
impl<T, A> Default for Box<T, A>
where
T: Default,
A: Default + AllocRef,
{
#[must_use]
fn default() -> Self {
Self::new_in(T::default(), A::default())
}
}
#[allow(clippy::use_self)]
impl<T, A: AllocRef> Default for Box<[T], A>
where
A: Default,
{
#[must_use]
fn default() -> Self {
Box::<[T; 0], A>::new_in([], A::default())
}
}
#[inline]
unsafe fn from_boxed_utf8_unchecked<A: AllocRef>(v: Box<[u8], A>) -> Box<str, A> {
let (ptr, b) = Box::into_raw_alloc(v);
Box::from_raw_in(ptr as *mut str, b)
}
#[allow(clippy::use_self)]
impl<A> Default for Box<str, A>
where
A: Default + AllocRef,
{
#[must_use]
fn default() -> Self {
unsafe { from_boxed_utf8_unchecked(Box::default()) }
}
}
impl<T: Clone, A: AllocRef + Clone> Clone for Box<T, A> {
#[inline]
fn clone(&self) -> Self {
self.clone_in(self.alloc.clone())
}
#[inline]
fn clone_from(&mut self, source: &Self) {
(**self).clone_from(&(**source));
}
}
#[allow(clippy::use_self)]
impl<T: Clone, A: AllocRef, B: AllocRef> CloneIn<B> for Box<T, A> {
type Cloned = Box<T, B>;
fn clone_in(&self, a: B) -> Self::Cloned {
Box::new_in(self.as_ref().clone(), a)
}
fn try_clone_in(&self, a: B) -> Result<Self::Cloned, TryReserveError> {
Box::try_new_in(self.as_ref().clone(), a).map_err(|_| AllocError {
layout: Layout::new::<T>(),
})
}
}
impl<T: ?Sized + PartialEq, A: AllocRef> PartialEq for Box<T, A> {
#[inline]
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&**self, &**other)
}
#[allow(clippy::partialeq_ne_impl)]
#[inline]
fn ne(&self, other: &Self) -> bool {
PartialEq::ne(&**self, &**other)
}
}
impl<T: ?Sized + PartialOrd, A: AllocRef> PartialOrd for Box<T, A> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
#[inline]
fn lt(&self, other: &Self) -> bool {
PartialOrd::lt(&**self, &**other)
}
#[inline]
fn le(&self, other: &Self) -> bool {
PartialOrd::le(&**self, &**other)
}
#[inline]
fn gt(&self, other: &Self) -> bool {
PartialOrd::gt(&**self, &**other)
}
#[inline]
fn ge(&self, other: &Self) -> bool {
PartialOrd::ge(&**self, &**other)
}
}
impl<T: ?Sized + Ord, A: AllocRef> Ord for Box<T, A> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<T: ?Sized + Eq, A: AllocRef> Eq for Box<T, A> {}
impl<T: ?Sized + Hash, A: AllocRef> Hash for Box<T, A> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
impl<T: ?Sized + Hasher, A: AllocRef> Hasher for Box<T, A> {
fn finish(&self) -> u64 {
(**self).finish()
}
fn write(&mut self, bytes: &[u8]) {
(**self).write(bytes)
}
fn write_u8(&mut self, i: u8) {
(**self).write_u8(i)
}
fn write_u16(&mut self, i: u16) {
(**self).write_u16(i)
}
fn write_u32(&mut self, i: u32) {
(**self).write_u32(i)
}
fn write_u64(&mut self, i: u64) {
(**self).write_u64(i)
}
fn write_u128(&mut self, i: u128) {
(**self).write_u128(i)
}
fn write_usize(&mut self, i: usize) {
(**self).write_usize(i)
}
fn write_i8(&mut self, i: i8) {
(**self).write_i8(i)
}
fn write_i16(&mut self, i: i16) {
(**self).write_i16(i)
}
fn write_i32(&mut self, i: i32) {
(**self).write_i32(i)
}
fn write_i64(&mut self, i: i64) {
(**self).write_i64(i)
}
fn write_i128(&mut self, i: i128) {
(**self).write_i128(i)
}
fn write_isize(&mut self, i: isize) {
(**self).write_isize(i)
}
}
impl<T, A> From<T> for Box<T, A>
where
A: Default + AllocRef,
{
fn from(t: T) -> Self {
Self::new_in(t, A::default())
}
}
impl<T: ?Sized, A: AllocRef> From<Box<T, A>> for Pin<Box<T, A>> {
fn from(boxed: Box<T, A>) -> Self {
Box::into_pin(boxed)
}
}
#[allow(clippy::use_self)]
impl<T: Copy, A: AllocRef> From<&[T]> for Box<[T], A>
where
A: Default,
{
fn from(slice: &[T]) -> Self {
let len = slice.len();
let buf = RawVec::with_capacity_in(len, A::default());
unsafe {
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
buf.into_box(slice.len()).assume_init()
}
}
}
#[allow(clippy::use_self)]
impl<A: AllocRef> From<&str> for Box<str, A>
where
A: Default,
{
#[inline]
#[must_use]
fn from(s: &str) -> Self {
unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) }
}
}
#[allow(clippy::use_self)]
impl<A: AllocRef> From<Box<str, A>> for Box<[u8], A> {
#[inline]
fn from(s: Box<str, A>) -> Self {
let (ptr, b) = Box::into_raw_alloc(s);
unsafe { Self::from_raw_in(ptr as *mut [u8], b) }
}
}
#[allow(clippy::use_self)]
impl<T, const N: usize> core::convert::TryFrom<Box<[T]>> for Box<[T; N]>
where
[T; N]: core::array::LengthAtMost32,
{
type Error = Box<[T]>;
fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
if boxed_slice.len() == N {
Ok(unsafe { Self::from_raw(Box::into_raw(boxed_slice) as *mut [T; N]) })
} else {
Err(boxed_slice)
}
}
}
#[allow(clippy::use_self)]
impl<A: AllocRef> Box<dyn Any, A> {
#[inline]
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Box<dyn Any, A>> {
if self.is::<T>() {
unsafe {
let (raw, b): (*mut dyn Any, _) = Self::into_raw_alloc(self);
Ok(Box::from_raw_in(raw as *mut T, b))
}
} else {
Err(self)
}
}
}
#[allow(clippy::use_self)]
impl<A: AllocRef> Box<dyn Any + Send, A> {
#[inline]
pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Box<dyn Any + Send, A>> {
if self.is::<T>() {
unsafe {
let (raw, b): (*mut (dyn Any + Send), _) = Self::into_raw_alloc(self);
Ok(Box::from_raw_in(raw as *mut T, b))
}
} else {
Err(self)
}
}
}
impl<T: fmt::Display + ?Sized, A: AllocRef> fmt::Display for Box<T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: fmt::Debug + ?Sized, A: AllocRef> fmt::Debug for Box<T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: ?Sized, A: AllocRef> fmt::Pointer for Box<T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ptr: *const T = &**self;
fmt::Pointer::fmt(&ptr, f)
}
}
impl<T: ?Sized, A: AllocRef> Deref for Box<T, A> {
type Target = T;
fn deref(&self) -> &T {
unsafe { self.ptr.as_ref() }
}
}
impl<T: ?Sized, A: AllocRef> DerefMut for Box<T, A> {
fn deref_mut(&mut self) -> &mut T {
unsafe { self.ptr.as_mut() }
}
}
impl<T: ?Sized, A: AllocRef> core::ops::Receiver for Box<T, A> {}
impl<I: Iterator + ?Sized, A: AllocRef> Iterator for Box<I, A> {
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
(**self).next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
fn last(self) -> Option<I::Item> {
BoxIter::last(self)
}
fn nth(&mut self, n: usize) -> Option<I::Item> {
(**self).nth(n)
}
}
trait BoxIter {
type Item;
fn last(self) -> Option<Self::Item>;
}
impl<I: Iterator + ?Sized, A: AllocRef> BoxIter for Box<I, A> {
type Item = I::Item;
fn last(self) -> Option<I::Item> {
#[inline]
#[allow(clippy::missing_const_for_fn)]
fn some<T>(_: Option<T>, x: T) -> Option<T> {
Some(x)
}
self.fold(None, some)
}
}
impl<I: DoubleEndedIterator + ?Sized, A: AllocRef> DoubleEndedIterator for Box<I, A> {
fn next_back(&mut self) -> Option<I::Item> {
(**self).next_back()
}
fn nth_back(&mut self, n: usize) -> Option<I::Item> {
(**self).nth_back(n)
}
}
impl<I: ExactSizeIterator + ?Sized, A: AllocRef> ExactSizeIterator for Box<I, A> {
fn len(&self) -> usize {
(**self).len()
}
fn is_empty(&self) -> bool {
(**self).is_empty()
}
}
impl<I: FusedIterator + ?Sized, A: AllocRef> FusedIterator for Box<I, A> {}
impl<Args, F: FnOnce<Args> + Copy + ?Sized, A: AllocRef> FnOnce<Args> for Box<F, A> {
type Output = <F as FnOnce<Args>>::Output;
extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
<F as FnOnce<Args>>::call_once(*self, args)
}
}
impl<Args, F: FnMut<Args> + Copy + ?Sized, A: AllocRef> FnMut<Args> for Box<F, A> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
<F as FnMut<Args>>::call_mut(self, args)
}
}
impl<Args, F: Fn<Args> + Copy + ?Sized, A: AllocRef> Fn<Args> for Box<F, A> {
extern "rust-call" fn call(&self, args: Args) -> Self::Output {
<F as Fn<Args>>::call(self, args)
}
}
impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized, A: AllocRef>
core::ops::CoerceUnsized<Box<U, A>> for Box<T, A>
{
}
macro_rules! impl_dispatch_from_dyn {
($alloc:ty) => {
impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized>
core::ops::DispatchFromDyn<Box<U, $alloc>> for Box<T, $alloc>
{
}
};
}
impl_dispatch_from_dyn!(Global);
#[cfg(feature = "std")]
impl_dispatch_from_dyn!(std::alloc::System);
#[allow(clippy::items_after_statements)]
impl<T: Clone, A: Clone> Clone for Box<[T], A>
where
A: AllocRef,
{
fn clone(&self) -> Self {
let mut new = BoxBuilder {
data: RawVec::with_capacity_in(self.len(), self.alloc_ref().clone()),
len: 0,
};
let mut target = new.data.ptr();
for item in self.iter() {
unsafe {
ptr::write(target, item.clone());
target = target.offset(1);
};
new.len += 1;
}
return unsafe { new.into_box() };
struct BoxBuilder<T, A: AllocRef> {
data: RawVec<T, A>,
len: usize,
}
impl<T, A: AllocRef> BoxBuilder<T, A> {
unsafe fn into_box(self) -> Box<[T], A> {
let raw = ptr::read(&self.data);
let len = self.len;
mem::forget(self);
raw.into_box(len).assume_init()
}
}
impl<T, A: AllocRef> Drop for BoxBuilder<T, A> {
fn drop(&mut self) {
let mut data = self.data.ptr();
let max = unsafe { data.add(self.len) };
while data != max {
unsafe {
ptr::read(data);
data = data.offset(1);
}
}
}
}
}
}
impl<T: ?Sized, A: AllocRef> borrow::Borrow<T> for Box<T, A> {
fn borrow(&self) -> &T {
&**self
}
}
impl<T: ?Sized, A: AllocRef> borrow::BorrowMut<T> for Box<T, A> {
fn borrow_mut(&mut self) -> &mut T {
&mut **self
}
}
impl<T: ?Sized, A: AllocRef> AsRef<T> for Box<T, A> {
fn as_ref(&self) -> &T {
&**self
}
}
impl<T: ?Sized, A: AllocRef> AsMut<T> for Box<T, A> {
fn as_mut(&mut self) -> &mut T {
&mut **self
}
}
impl<T: ?Sized, A: AllocRef> Unpin for Box<T, A> {}
impl<F: ?Sized + Future + Unpin, A: AllocRef> Future for Box<F, A> {
type Output = F::Output;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
F::poll(Pin::new(&mut *self), cx)
}
}