use core::{mem, fmt, ptr, marker};
use crate::Deleter;
#[cfg(feature = "alloc")]
pub type Global<T> = Unique<'static, T, crate::GlobalDeleter>;
#[cfg(feature = "alloc")]
impl<T> Global<T> {
#[inline]
pub fn boxed(val: T) -> Self {
alloc::boxed::Box::new(val).into()
}
}
#[cfg(feature = "alloc")]
impl<T: ?Sized> Global<T> {
#[inline]
pub fn into_boxed(self) -> alloc::boxed::Box<T> {
let ptr = self.release().as_ptr();
unsafe {
alloc::boxed::Box::from_raw(ptr)
}
}
}
#[repr(transparent)]
pub struct Unique<'a, T: ?Sized, D: Deleter> {
inner: ptr::NonNull<T>,
_traits: marker::PhantomData<&'a D>,
}
impl<'a, T: ?Sized, D: Deleter> Unique<'a, T, D> {
#[inline]
pub unsafe fn new(ptr: *mut T) -> Self {
assert!(!ptr.is_null());
Self::from_ptr_unchecked(ptr)
}
#[inline]
pub unsafe fn from_ptr(ptr: *mut T) -> Option<Self> {
match ptr.is_null() {
true => None,
false => Some(Self::from_ptr_unchecked(ptr)),
}
}
#[inline]
pub unsafe fn from_ptr_unchecked(ptr: *mut T) -> Self {
Self {
inner: ptr::NonNull::new_unchecked(ptr),
_traits: marker::PhantomData,
}
}
#[inline(always)]
pub fn get(&self) -> *mut T {
self.inner.as_ptr()
}
#[inline(always)]
pub fn as_ref(&self) -> &T {
self
}
#[inline(always)]
pub fn as_mut(&mut self) -> &mut T {
self
}
#[inline(always)]
pub fn cast<N>(&self) -> *mut N {
self.inner.as_ptr() as *mut N
}
#[inline(always)]
pub fn const_cast<N>(&self) -> *const N {
self.inner.as_ptr() as *mut N as *const N
}
#[inline(always)]
pub fn swap(&mut self, other: &mut Self) {
mem::swap(&mut self.inner, &mut other.inner);
}
#[inline]
pub fn release(self) -> ptr::NonNull<T> {
let result = self.inner;
mem::forget(self);
result
}
}
impl<'a, T: ?Sized, D: Deleter> Drop for Unique<'a, T, D> {
#[inline(always)]
fn drop(&mut self) {
unsafe {
D::delete::<T>(self.inner.as_ptr())
}
}
}
impl<'a, T: ?Sized, D: Deleter> fmt::Pointer for Unique<'a, T, D> {
#[inline(always)]
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.inner, fmt)
}
}
impl<'a, T: ?Sized + fmt::Debug, D: Deleter> fmt::Debug for Unique<'a, T, D> {
#[inline(always)]
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.as_ref(), fmt)
}
}
impl<'a, T: ?Sized + fmt::Display, D: Deleter> fmt::Display for Unique<'a, T, D> {
#[inline(always)]
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.as_ref(), fmt)
}
}
impl<'a, T: ?Sized + Unpin, D: Deleter> Unpin for Unique<'a, T, D> {}
unsafe impl<'a, T: ?Sized + Send, D: Deleter> Send for Unique<'a, T, D> {}
unsafe impl<'a, T: ?Sized + Sync, D: Deleter> Sync for Unique<'a, T, D> {}
impl<'a, T: ?Sized, D: Deleter> core::ops::Deref for Unique<'a, T, D> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe {
&*self.inner.as_ptr()
}
}
}
impl<'a, T: ?Sized, D: Deleter> core::ops::DerefMut for Unique<'a, T, D> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe {
&mut *self.inner.as_ptr()
}
}
}
impl<'a, T: ?Sized + core::hash::Hash, D: Deleter> core::hash::Hash for Unique<'a, T, D> {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.as_ref().hash(state);
}
}
impl<'a, T: ?Sized + PartialOrd, D: Deleter> PartialOrd<Self> for Unique<'a, T, D> {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
PartialOrd::partial_cmp(self.as_ref(), other.as_ref())
}
}
impl<'a, T: ?Sized + PartialEq, D: Deleter> PartialEq<Self> for Unique<'a, T, D> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(self.as_ref(), other.as_ref())
}
#[allow(clippy::partialeq_ne_impl)]
#[inline(always)]
fn ne(&self, other: &Self) -> bool {
PartialEq::ne(self.as_ref(), other.as_ref())
}
}
impl<'a, T: ?Sized + Eq, D: Deleter> Eq for Unique<'a, T, D> {
}
impl<'a, T: ?Sized + core::panic::RefUnwindSafe, D: Deleter> core::panic::UnwindSafe for Unique<'a, T, D> {
}
#[cfg(feature = "alloc")]
impl<T: ?Sized> From<alloc::boxed::Box<T>> for Global<T> {
#[inline]
fn from(ptr: alloc::boxed::Box<T>) -> Self {
let ptr = alloc::boxed::Box::into_raw(ptr);
unsafe {
Self::from_ptr_unchecked(ptr)
}
}
}
#[cfg(feature = "alloc")]
impl<T: ?Sized + Clone> Clone for Global<T> {
fn clone(&self) -> Self {
let val = unsafe {
core::mem::ManuallyDrop::new(
alloc::boxed::Box::from_raw(self.get())
)
};
let result = core::mem::ManuallyDrop::into_inner(val.clone());
result.into()
}
}
impl<'a, T: ?Sized> From<&'a mut T> for Unique<'a, T, ()> {
#[inline]
fn from(ptr: &'a mut T) -> Self {
unsafe {
Self::from_ptr_unchecked(ptr)
}
}
}