use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::ptr::NonNull;
use core::{fmt, mem};
pub use alloc::boxed::Box as UniqueBox;
pub struct AliasableBox<T: ?Sized>(NonNull<T>);
impl<T: ?Sized> AliasableBox<T> {
pub fn from_unique(ptr: UniqueBox<T>) -> Self {
let ptr = unsafe { NonNull::new_unchecked(UniqueBox::into_raw(ptr)) };
Self(ptr)
}
#[inline]
pub fn into_unique(mut ptr: AliasableBox<T>) -> UniqueBox<T> {
let unique = unsafe { ptr.reclaim_as_unique_box() };
mem::forget(ptr);
unique
}
pub fn into_unique_pin(pin: Pin<AliasableBox<T>>) -> Pin<UniqueBox<T>> {
unsafe {
let aliasable = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(AliasableBox::into_unique(aliasable))
}
}
pub fn from_unique_pin(pin: Pin<UniqueBox<T>>) -> Pin<AliasableBox<T>> {
unsafe {
let unique = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(AliasableBox::from(unique))
}
}
#[inline]
unsafe fn reclaim_as_unique_box(&mut self) -> UniqueBox<T> {
UniqueBox::from_raw(self.0.as_ptr())
}
}
impl<T: ?Sized> From<UniqueBox<T>> for AliasableBox<T> {
fn from(ptr: UniqueBox<T>) -> Self {
Self::from_unique(ptr)
}
}
impl<T: ?Sized> Drop for AliasableBox<T> {
fn drop(&mut self) {
let _ = unsafe { self.reclaim_as_unique_box() };
}
}
impl<T: ?Sized> Deref for AliasableBox<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.0.as_ref() }
}
}
impl<T: ?Sized> DerefMut for AliasableBox<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { self.0.as_mut() }
}
}
impl<T: ?Sized> AsRef<T> for AliasableBox<T> {
#[inline]
fn as_ref(&self) -> &T {
&*self
}
}
impl<T: ?Sized> AsMut<T> for AliasableBox<T> {
fn as_mut(&mut self) -> &mut T {
&mut *self
}
}
impl<T: ?Sized> fmt::Debug for AliasableBox<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.as_ref(), f)
}
}
unsafe impl<T: ?Sized> Send for AliasableBox<T> where T: Send {}
unsafe impl<T: ?Sized> Sync for AliasableBox<T> where T: Sync {}
#[cfg(feature = "traits")]
unsafe impl<T: ?Sized> crate::StableDeref for AliasableBox<T> {}
#[cfg(feature = "traits")]
unsafe impl<T: ?Sized> crate::AliasableDeref for AliasableBox<T> {}
#[cfg(test)]
mod tests {
use super::{AliasableBox, UniqueBox};
use alloc::format;
#[test]
fn test_new() {
let aliasable = AliasableBox::from_unique(UniqueBox::new(10));
assert_eq!(*aliasable, 10);
let unique = AliasableBox::into_unique(aliasable);
assert_eq!(*unique, 10);
}
#[test]
fn test_new_pin() {
let aliasable = AliasableBox::from_unique_pin(UniqueBox::pin(10));
assert_eq!(*aliasable, 10);
let unique = AliasableBox::into_unique_pin(aliasable);
assert_eq!(*unique, 10);
}
#[test]
fn test_refs() {
let mut aliasable = AliasableBox::from_unique(UniqueBox::new(10));
let ptr: *const u8 = &*aliasable;
let as_mut_ptr: *const u8 = aliasable.as_mut();
let as_ref_ptr: *const u8 = aliasable.as_ref();
assert_eq!(ptr, as_mut_ptr);
assert_eq!(ptr, as_ref_ptr);
}
#[test]
fn test_debug() {
let aliasable = AliasableBox::from_unique(UniqueBox::new(10));
assert_eq!(format!("{:?}", aliasable), "10");
}
}