use core::alloc::Layout;
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::mem;
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use crate::alloc::{AllocError, Allocator, Global};
use crate::clone::TryClone;
use crate::error::Error;
use crate::iter::TryFromIteratorIn;
use crate::path::Path;
use crate::ptr::{self, Unique};
use crate::raw_vec::RawVec;
use crate::vec::Vec;
#[test]
fn ensure_niche_size() {
assert_eq!(
core::mem::size_of::<Option<Box<u32>>>(),
core::mem::size_of::<Box<u32>>()
);
}
pub struct Box<T: ?Sized, A: Allocator = Global> {
ptr: Unique<T>,
alloc: A,
}
impl<T> Box<T, Global> {
pub fn try_new(value: T) -> Result<Self, AllocError> {
Self::try_new_in(value, Global)
}
#[inline(always)]
pub fn try_pin(x: T) -> Result<Pin<Box<T>>, AllocError> {
Ok(Box::try_new(x)?.into())
}
}
impl<T: ?Sized> Box<T> {
#[cfg(feature = "alloc")]
pub fn from_std(b: ::rust_alloc::boxed::Box<T>) -> Result<Self, Error> {
unsafe {
Global.take(Layout::for_value(b.as_ref()))?;
let raw = ::rust_alloc::boxed::Box::into_raw(b);
Ok(Box::from_raw_in(raw, Global))
}
}
}
impl<T, A: Allocator> Box<T, A> {
#[inline]
pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> {
let mut boxed = Self::try_new_uninit_in(alloc)?;
unsafe {
boxed.as_mut_ptr().write(x);
Ok(boxed.assume_init())
}
}
pub fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
where
A: Allocator,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
let ptr = alloc.allocate(layout)?.cast();
unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) }
}
#[inline]
pub fn into_inner(boxed: Self) -> T {
let this = mem::ManuallyDrop::new(boxed);
let value = unsafe { ptr::read(this.ptr.as_ptr()) };
unsafe {
let layout = for_value_raw(this.ptr.as_ptr());
if layout.size() != 0 {
this.alloc.deallocate(From::from(this.ptr.cast()), layout);
}
}
value
}
}
impl<T: ?Sized, A: Allocator> Box<T, A> {
#[inline]
pub fn leak<'a>(b: Self) -> &'a mut T
where
A: 'a,
{
unsafe { &mut *mem::ManuallyDrop::new(b).ptr.as_ptr() }
}
pub fn into_pin(boxed: Self) -> Pin<Self>
where
A: 'static,
{
unsafe { Pin::new_unchecked(boxed) }
}
#[inline]
pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
Self {
ptr: unsafe { Unique::new_unchecked(raw) },
alloc,
}
}
#[inline]
pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
let leaked = mem::ManuallyDrop::new(b);
let alloc = unsafe { ptr::read(&leaked.alloc) };
(leaked.ptr.as_ptr(), alloc)
}
}
impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
#[inline]
pub unsafe fn assume_init(self) -> Box<T, A> {
let (raw, alloc) = Box::into_raw_with_allocator(self);
unsafe { Box::from_raw_in(raw as *mut T, alloc) }
}
}
impl<T, A: Allocator> Box<[T], A> {
#[inline]
pub fn try_new_uninit_slice_in(
len: usize,
alloc: A,
) -> Result<Box<[mem::MaybeUninit<T>], A>, Error> {
unsafe {
let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
Ok(l) => l,
Err(_) => return Err(Error::LayoutError),
};
let ptr = alloc.allocate(layout)?;
Ok(RawVec::from_raw_parts_in(ptr.as_ptr() as *mut _, len, alloc).into_box(len))
}
}
}
impl<T, A: Allocator> Box<[mem::MaybeUninit<T>], A> {
#[inline]
pub unsafe fn assume_init(self) -> Box<[T], A> {
let (raw, alloc) = Box::into_raw_with_allocator(self);
unsafe { Box::from_raw_in(raw as *mut [T], alloc) }
}
}
impl<T, A: Allocator + Clone> TryClone for Box<T, A>
where
T: TryClone,
{
#[inline]
fn try_clone(&self) -> Result<Self, Error> {
let value = (**self).try_clone()?;
let alloc = self.alloc.clone();
Ok(Box::try_new_in(value, alloc)?)
}
}
impl<T, A: Allocator + Clone> TryClone for Box<[T], A>
where
T: TryClone,
{
#[inline]
fn try_clone(&self) -> Result<Self, Error> {
let alloc = self.alloc.clone();
let vec = crate::slice::to_vec(self, alloc)?;
vec.try_into_boxed_slice()
}
}
impl<A: Allocator + Clone> TryClone for Box<str, A> {
#[inline]
fn try_clone(&self) -> Result<Self, Error> {
let alloc = self.alloc.clone();
Box::try_from_string_in(self.as_ref(), alloc)
}
}
impl<T: ?Sized, A: Allocator> Borrow<T> for Box<T, A> {
fn borrow(&self) -> &T {
self
}
}
impl<T: ?Sized, A: Allocator> BorrowMut<T> for Box<T, A> {
fn borrow_mut(&mut self) -> &mut T {
self
}
}
impl<T: ?Sized, A: Allocator> AsRef<T> for Box<T, A> {
fn as_ref(&self) -> &T {
self
}
}
impl<T: ?Sized, A: Allocator> AsMut<T> for Box<T, A> {
fn as_mut(&mut self) -> &mut T {
self
}
}
impl<T: ?Sized, A: Allocator> Unpin for Box<T, A> where A: 'static {}
impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.ptr.as_ref() }
}
}
impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { self.ptr.as_mut() }
}
}
impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
#[inline]
fn drop(&mut self) {
unsafe {
let ptr = self.ptr;
if mem::needs_drop::<T>() {
ptr::drop_in_place(ptr.as_ptr());
}
let layout = for_value_raw(ptr.as_ptr());
if layout.size() != 0 {
self.alloc.deallocate(From::from(ptr.cast()), layout);
}
}
}
}
impl Default for Box<str, Global> {
fn default() -> Self {
unsafe {
let b = Box::<[u8]>::default();
let (ptr, alloc) = Box::into_raw_with_allocator(b);
Box::from_raw_in(ptr as *mut str, alloc)
}
}
}
impl<T> Default for Box<[T], Global> {
fn default() -> Self {
Box {
ptr: Unique::dangling_empty_slice(),
alloc: Global,
}
}
}
impl<T: ?Sized, A: Allocator> fmt::Display for Box<T, A>
where
T: fmt::Display,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: ?Sized, A: Allocator> fmt::Debug for Box<T, A>
where
T: fmt::Debug,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<A: Allocator> From<Box<str, A>> for Box<[u8], A> {
fn from(value: Box<str, A>) -> Self {
unsafe {
let (ptr, alloc) = Box::into_raw_with_allocator(value);
Box::from_raw_in(ptr as *mut [u8], alloc)
}
}
}
#[cfg(feature = "alloc")]
impl<T> TryFrom<::rust_alloc::boxed::Box<[T]>> for Box<[T]> {
type Error = Error;
#[inline]
fn try_from(values: ::rust_alloc::boxed::Box<[T]>) -> Result<Self, Error> {
let mut vec = Vec::try_with_capacity(values.len())?;
for value in ::rust_alloc::vec::Vec::from(values) {
vec.try_push(value)?;
}
vec.try_into_boxed_slice()
}
}
impl<T, const N: usize> TryFrom<[T; N]> for Box<[T]> {
type Error = Error;
#[inline]
fn try_from(values: [T; N]) -> Result<Self, Error> {
let mut vec = Vec::try_with_capacity(values.len())?;
for value in values {
vec.try_push(value)?;
}
vec.try_into_boxed_slice()
}
}
unsafe fn boxed_slice_as_array_unchecked<T, A: Allocator, const N: usize>(
boxed_slice: Box<[T], A>,
) -> Box<[T; N], A> {
debug_assert_eq!(boxed_slice.len(), N);
let (ptr, alloc) = Box::into_raw_with_allocator(boxed_slice);
unsafe { Box::from_raw_in(ptr as *mut [T; N], alloc) }
}
impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
type Error = Box<[T]>;
fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
if boxed_slice.len() == N {
Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
} else {
Err(boxed_slice)
}
}
}
impl<T, A: Allocator> TryFrom<Vec<T, A>> for Box<[T], A> {
type Error = Error;
#[inline]
fn try_from(vec: Vec<T, A>) -> Result<Self, Error> {
vec.try_into_boxed_slice()
}
}
impl<A: Allocator> Box<[u8], A> {
pub(crate) fn try_from_bytes_in(bytes: &[u8], alloc: A) -> Result<Self, Error> {
let mut vec = Vec::<u8, A>::try_with_capacity_in(bytes.len(), alloc)?;
unsafe {
ptr::copy_nonoverlapping(bytes.as_ptr(), vec.as_mut_ptr(), bytes.len());
vec.set_len(bytes.len());
vec.try_into_boxed_slice()
}
}
}
impl<A: Allocator> Box<str, A> {
pub(crate) fn try_from_string_in(string: &str, alloc: A) -> Result<Self, Error> {
unsafe {
let b = Box::try_from_bytes_in(string.as_bytes(), alloc)?;
let (raw, alloc) = Box::into_raw_with_allocator(b);
Ok(Box::from_raw_in(raw as *mut str, alloc))
}
}
}
impl<A: Allocator> Box<Path, A> {
pub(crate) fn try_from_path_in(path: &Path, alloc: A) -> Result<Self, Error> {
unsafe {
const _: () = assert!(mem::size_of::<&Path>() == mem::size_of::<&[u8]>());
let bytes = &*(path as *const _ as *const [u8]);
let b = Box::try_from_bytes_in(bytes, alloc)?;
let (raw, alloc) = Box::into_raw_with_allocator(b);
Ok(Box::from_raw_in(raw as *mut Path, alloc))
}
}
}
impl<A: Allocator + Clone> TryClone for Box<Path, A> {
#[inline]
fn try_clone(&self) -> Result<Self, Error> {
let alloc = self.alloc.clone();
Box::try_from_path_in(self.as_ref(), alloc)
}
}
impl TryFrom<&str> for Box<str> {
type Error = Error;
#[inline]
fn try_from(values: &str) -> Result<Self, Error> {
Box::try_from_string_in(values, Global)
}
}
#[cfg(feature = "alloc")]
impl TryFrom<::rust_alloc::string::String> for Box<str> {
type Error = Error;
#[inline]
fn try_from(string: ::rust_alloc::string::String) -> Result<Self, Error> {
Box::from_std(string.into_boxed_str())
}
}
impl TryFrom<&[u8]> for Box<[u8]> {
type Error = Error;
#[inline]
fn try_from(values: &[u8]) -> Result<Self, Error> {
Box::try_from_bytes_in(values, Global)
}
}
impl TryFrom<&Path> for Box<Path> {
type Error = Error;
#[inline]
fn try_from(path: &Path) -> Result<Self, Error> {
Box::try_from_path_in(path, Global)
}
}
impl<T, A: Allocator> TryFromIteratorIn<T, A> for Box<[T], A> {
fn try_from_iter_in<I>(iter: I, alloc: A) -> Result<Self, Error>
where
I: IntoIterator<Item = T>,
{
Vec::<T, A>::try_from_iter_in(iter, alloc)?.try_into_boxed_slice()
}
}
unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Layout {
let (size, align) = (mem::size_of_val(&*t), mem::align_of_val(&*t));
Layout::from_size_align_unchecked(size, align)
}
impl<T: ?Sized, A: Allocator> Hash for Box<T, A>
where
T: Hash,
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Pin<Box<T, A>>
where
A: 'static,
{
fn from(boxed: Box<T, A>) -> Self {
Box::into_pin(boxed)
}
}
impl<T: ?Sized, A: Allocator> PartialEq for Box<T, A>
where
T: PartialEq,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
(**self).eq(other)
}
}
impl<T: ?Sized, A: Allocator> Eq for Box<T, A> where T: Eq {}
impl<T: ?Sized, A: Allocator> PartialOrd for Box<T, A>
where
T: PartialOrd,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(**self).partial_cmp(other)
}
}
impl<T: ?Sized, A: Allocator> Ord for Box<T, A>
where
T: Ord,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
(**self).cmp(other)
}
}