use core::{borrow, cmp, fmt, hash, mem, ops, ptr};
use crate::uninit::Uninit;
use unsize::CoerciblePtr;
pub struct Box<'a, T: ?Sized> {
inner: Uninit<'a, T>,
}
unsafe impl<'a, T, U: ?Sized> CoerciblePtr<U> for Box<'a, T> {
type Pointee = T;
type Output = Box<'a, U>;
fn as_sized_ptr(&mut self) -> *mut T {
self.inner.as_ptr()
}
unsafe fn replace_ptr(self, new: *mut U) -> Box<'a, U> {
let inner = Box::into_raw(self);
let inner = inner.replace_ptr(new);
Box::from_raw(inner)
}
}
impl<'a, T> Box<'a, T> {
pub fn new(val: T, mut into: Uninit<'a, T>) -> Self {
into.borrow_mut().init(val);
Box {
inner: into,
}
}
pub fn take(b: Self) -> (T, Uninit<'a, T>) {
let val = unsafe { b.inner.read() };
(val, Self::into_raw(b))
}
}
impl<'a, T: ?Sized> Box<'a, T> {
pub unsafe fn from_raw(init: Uninit<'a, T>) -> Self {
Box {
inner: init,
}
}
pub fn into_raw(b: Self) -> Uninit<'a, T> {
let ptr = b.inner.as_non_null();
let len = b.inner.size();
mem::forget(b);
unsafe {
Uninit::new(ptr, len)
}
}
pub fn leak(b: Self) -> &'a mut T {
let raw = Self::into_raw(b);
unsafe { raw.into_mut() }
}
}
impl<T: ?Sized> Drop for Box<'_, T> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(self.inner.as_ptr())
}
}
}
impl<T: ?Sized> ops::Deref for Box<'_, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
self.inner.as_ref()
}
}
}
impl<T: ?Sized> ops::DerefMut for Box<'_, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
self.inner.as_mut()
}
}
}
impl<'a, 'b, T: PartialEq> PartialEq<Box<'b, T>> for Box<'a, T> {
#[inline]
fn eq(&self, other: &Box<T>) -> bool {
PartialEq::eq(&**self, &**other)
}
#[inline]
fn ne(&self, other: &Box<T>) -> bool {
PartialEq::ne(&**self, &**other)
}
}
impl<'a, 'b, T: PartialOrd> PartialOrd<Box<'b, T>> for Box<'a, T> {
#[inline]
fn partial_cmp(&self, other: &Box<T>) -> Option<cmp::Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
#[inline]
fn lt(&self, other: &Box<T>) -> bool {
PartialOrd::lt(&**self, &**other)
}
#[inline]
fn le(&self, other: &Box<T>) -> bool {
PartialOrd::le(&**self, &**other)
}
#[inline]
fn ge(&self, other: &Box<T>) -> bool {
PartialOrd::ge(&**self, &**other)
}
#[inline]
fn gt(&self, other: &Box<T>) -> bool {
PartialOrd::gt(&**self, &**other)
}
}
impl<T: Ord> Ord for Box<'_, T> {
#[inline]
fn cmp(&self, other: &Box<T>) -> cmp::Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<T: Eq> Eq for Box<'_, T> { }
impl<T: hash::Hash> hash::Hash for Box<'_, T> {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<T: fmt::Debug> fmt::Debug for Box<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T> fmt::Pointer for Box<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.inner.as_ptr(), f)
}
}
impl<T> borrow::Borrow<T> for Box<'_, T> {
fn borrow(&self) -> &T {
&**self
}
}
impl<T> borrow::BorrowMut<T> for Box<'_, T> {
fn borrow_mut(&mut self) -> &mut T {
&mut **self
}
}
impl<T> AsRef<T> for Box<'_, T> {
fn as_ref(&self) -> &T {
&**self
}
}
impl<T> AsMut<T> for Box<'_, T> {
fn as_mut(&mut self) -> &mut T {
&mut **self
}
}
#[cfg(test)]
mod tests {
use super::Box;
use crate::alloc::LocalAllocLeakExt;
use static_alloc::Bump;
#[test]
fn leak_with_smaller_lifetime() {
static SLAB: Bump<[usize; 1]> = Bump::uninit();
let local = 0;
let boxed: Box<'static, _> = SLAB.boxed(&local).unwrap();
let _: & mut _ = Box::leak(boxed);
let _ = local;
}
}