#[cfg(feature = "alloc")]
use alloc::{boxed::Box, rc::Rc, sync::Arc};
use core::{
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
};
pub unsafe trait Well: Deref<Target: Sized> {
unsafe fn insert(ptr: NonNull<Self::Target>) -> Self;
fn remove(self) -> NonNull<Self::Target>;
}
#[cfg(feature = "nightly")]
macro_rules! well_mut {
($(#[$attr:meta])*) => {
$(#[$attr])*
pub trait WellMut = DerefMut + Well;
}
}
#[cfg(not(feature = "nightly"))]
macro_rules! well_mut {
($(#[$attr:meta])*) => {
$(#[$attr])*
pub trait WellMut: DerefMut + Well {}
impl<T: DerefMut + Well> WellMut for T {}
}
}
well_mut! {
}
unsafe impl<T> Well for &T {
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { ptr.as_ref() }
}
#[inline]
fn remove(self) -> NonNull<T> {
NonNull::from(self)
}
}
unsafe impl<T> Well for Pin<&T> {
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { Pin::new_unchecked(ptr.as_ref()) }
}
#[inline]
fn remove(self) -> NonNull<T> {
NonNull::from(self.get_ref())
}
}
unsafe impl<T> Well for &mut T {
#[inline]
unsafe fn insert(mut ptr: NonNull<T>) -> Self {
unsafe { ptr.as_mut() }
}
#[inline]
fn remove(self) -> NonNull<T> {
NonNull::from(self)
}
}
unsafe impl<T> Well for Pin<&mut T> {
#[inline]
unsafe fn insert(mut ptr: NonNull<T>) -> Self {
unsafe { Pin::new_unchecked(ptr.as_mut()) }
}
#[inline]
fn remove(self) -> NonNull<T> {
unsafe { NonNull::from(self.get_unchecked_mut()) }
}
}
#[cfg(any(test, feature = "alloc"))]
unsafe impl<T> Well for Box<T> {
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { Box::from_raw(ptr.as_ptr()) }
}
#[inline]
fn remove(self) -> NonNull<T> {
unsafe { NonNull::new_unchecked(Box::into_raw(self)) }
}
}
#[cfg(any(test, feature = "alloc"))]
unsafe impl<T> Well for Pin<Box<T>> {
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { Pin::new_unchecked(Box::from_raw(ptr.as_ptr())) }
}
#[inline]
fn remove(self) -> NonNull<T> {
unsafe { NonNull::new_unchecked(Box::into_raw(Pin::into_inner_unchecked(self))) }
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> Well for Rc<T> {
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { Rc::from_raw(ptr.as_ptr()) }
}
#[inline]
fn remove(self) -> NonNull<T> {
unsafe { NonNull::new_unchecked(Rc::into_raw(self).cast_mut()) }
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> Well for Pin<Rc<T>> {
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { Pin::new_unchecked(Rc::from_raw(ptr.as_ptr())) }
}
#[inline]
fn remove(self) -> NonNull<T> {
unsafe { NonNull::new_unchecked(Rc::into_raw(Pin::into_inner_unchecked(self)).cast_mut()) }
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> Well for Arc<T> {
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { Arc::from_raw(ptr.as_ptr()) }
}
#[inline]
fn remove(self) -> NonNull<T> {
unsafe { NonNull::new_unchecked(Arc::into_raw(self).cast_mut()) }
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> Well for Pin<Arc<T>> {
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { Pin::new_unchecked(Arc::from_raw(ptr.as_ptr())) }
}
#[inline]
fn remove(self) -> NonNull<T> {
unsafe { NonNull::new_unchecked(Arc::into_raw(Pin::into_inner_unchecked(self)).cast_mut()) }
}
}