use core::{
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
};
#[cfg(feature = "alloc")]
use {
crate::atomic::{PotentialAtomic, PotentialAtomicOption},
alloc::{boxed::Box, rc::Rc, sync::Arc},
};
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! trait_alias {
(
$(#[$attr:meta])*
$vis:vis trait $t:ident = ($($bound:tt)*);
) => {
$(#[$attr])*
$vis trait $t = $($bound)*;
}
}
#[cfg(not(feature = "nightly"))]
macro_rules! trait_alias {
(
$(#[$attr:meta])*
$vis:vis trait $t:ident = ($($bound:tt)*);
) => {
$(#[$attr])*
$vis trait $t: $($bound)* {}
impl<T: $($bound)*> $t for T {}
}
}
trait_alias! {
pub trait WellMut = (DerefMut + Well);
}
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()) }
}
}
pub trait PotentialWell {
type Well<T>: Well<Target = T>;
fn new<T>(data: T) -> Self::Well<T>;
}
#[cfg(any(test, feature = "alloc"))]
impl PotentialWell for Box<()> {
type Well<T> = Box<T>;
#[inline]
fn new<T>(data: T) -> Box<T> {
Box::new(data)
}
}
#[cfg(any(test, feature = "alloc"))]
impl PotentialWell for Pin<Box<()>> {
type Well<T> = Pin<Box<T>>;
#[inline]
fn new<T>(data: T) -> Pin<Box<T>> {
Box::pin(data)
}
}
#[cfg(feature = "alloc")]
impl PotentialWell for Rc<()> {
type Well<T> = Rc<T>;
#[inline]
fn new<T>(data: T) -> Rc<T> {
Rc::new(data)
}
}
#[cfg(feature = "alloc")]
impl PotentialWell for Pin<Rc<()>> {
type Well<T> = Pin<Rc<T>>;
#[inline]
fn new<T>(data: T) -> Pin<Rc<T>> {
Rc::pin(data)
}
}
#[cfg(feature = "alloc")]
impl PotentialWell for Arc<()> {
type Well<T> = Arc<T>;
#[inline]
fn new<T>(data: T) -> Arc<T> {
Arc::new(data)
}
}
#[cfg(feature = "alloc")]
impl PotentialWell for Pin<Arc<()>> {
type Well<T> = Pin<Arc<T>>;
#[inline]
fn new<T>(data: T) -> Pin<Arc<T>> {
Arc::pin(data)
}
}
pub type KineticWell<T, W> = <W as PotentialWell>::Well<T>;
#[cfg(feature = "alloc")]
pub type AtomicBox<T> = PotentialAtomic<T, Box<()>>;
#[cfg(feature = "alloc")]
pub type AtomicPinBox<T> = PotentialAtomic<T, Pin<Box<()>>>;
#[cfg(feature = "alloc")]
pub type AtomicRc<T> = PotentialAtomic<T, Rc<()>>;
#[cfg(feature = "alloc")]
pub type AtomicPinRc<T> = PotentialAtomic<T, Pin<Rc<()>>>;
#[cfg(feature = "alloc")]
pub type AtomicArc<T> = PotentialAtomic<T, Arc<()>>;
#[cfg(feature = "alloc")]
pub type AtomicPinArc<T> = PotentialAtomic<T, Pin<Arc<()>>>;
#[cfg(feature = "alloc")]
pub type AtomicOptionBox<T> = PotentialAtomicOption<T, Box<()>>;
#[cfg(feature = "alloc")]
pub type AtomicOptionPinBox<T> = PotentialAtomicOption<T, Pin<Box<()>>>;
#[cfg(feature = "alloc")]
pub type AtomicOptionRc<T> = PotentialAtomicOption<T, Rc<()>>;
#[cfg(feature = "alloc")]
pub type AtomicOptionPinRc<T> = PotentialAtomicOption<T, Pin<Rc<()>>>;
#[cfg(feature = "alloc")]
pub type AtomicOptionArc<T> = PotentialAtomicOption<T, Arc<()>>;
#[cfg(feature = "alloc")]
pub type AtomicOptionPinArc<T> = PotentialAtomicOption<T, Pin<Arc<()>>>;