use core::{
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
};
#[cfg(feature = "alloc")]
use {
crate::atomic::{PotentialAtomic, PotentialAtomicOption},
alloc::{
boxed::Box,
rc::{self, Rc},
sync::{self as arc, Arc},
},
};
pub unsafe trait Well {
type Target;
unsafe fn insert(ptr: NonNull<Self::Target>) -> Self;
fn remove(self) -> NonNull<Self::Target>;
}
pub type Bucket<W> = <W as Well>::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 {}
}
}
pub unsafe trait WeakWell: Well {
type Access: StrongWell + Deref<Target = Self::Target>;
fn access(&self) -> Option<Self::Access>;
}
pub unsafe trait StrongWell:
Deref<Target: Sized> + Well<Target = <Self as Deref>::Target>
{
}
unsafe impl<W: StrongWell> Well for Pin<W> {
type Target = Bucket<W>;
#[inline]
unsafe fn insert(ptr: NonNull<Bucket<W>>) -> Pin<W> {
unsafe { Pin::new_unchecked(W::insert(ptr)) }
}
#[inline]
fn remove(self) -> NonNull<Bucket<W>> {
unsafe { Pin::into_inner_unchecked(self).remove() }
}
}
unsafe impl<W: StrongWell> StrongWell for Pin<W> {}
trait_alias! {
pub trait StrongWellMut = (StrongWell + DerefMut);
}
unsafe impl<'w, T> Well for &'w T {
type Target = T;
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> &'w T {
unsafe { ptr.as_ref() }
}
#[inline]
fn remove(self) -> NonNull<T> {
NonNull::from(self)
}
}
unsafe impl<T> StrongWell for &T {}
unsafe impl<T> Well for &mut T {
type Target = 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> StrongWell for &mut T {}
#[cfg(any(test, feature = "alloc"))]
unsafe impl<T> Well for Box<T> {
type Target = 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(feature = "alloc")]
unsafe impl<T> StrongWell for Box<T> {}
#[cfg(feature = "alloc")]
unsafe impl<T> Well for Rc<T> {
type Target = 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> StrongWell for Rc<T> {}
#[cfg(feature = "alloc")]
unsafe impl<T> Well for rc::Weak<T> {
type Target = T;
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { rc::Weak::from_raw(ptr.as_ptr()) }
}
#[inline]
fn remove(self) -> NonNull<T> {
unsafe { NonNull::new_unchecked(rc::Weak::into_raw(self).cast_mut()) }
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> WeakWell for rc::Weak<T> {
type Access = Rc<T>;
#[inline]
fn access(&self) -> Option<Rc<T>> {
self.upgrade()
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> Well for Arc<T> {
type Target = 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> StrongWell for Arc<T> {}
#[cfg(feature = "alloc")]
unsafe impl<T> Well for arc::Weak<T> {
type Target = T;
#[inline]
unsafe fn insert(ptr: NonNull<T>) -> Self {
unsafe { arc::Weak::from_raw(ptr.as_ptr()) }
}
#[inline]
fn remove(self) -> NonNull<T> {
unsafe { NonNull::new_unchecked(arc::Weak::into_raw(self).cast_mut()) }
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> WeakWell for arc::Weak<T> {
type Access = Arc<T>;
#[inline]
fn access(&self) -> Option<Arc<T>> {
self.upgrade()
}
}
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 rc::Weak<()> {
type Well<T> = rc::Weak<T>;
#[inline]
fn new<T>(_: T) -> rc::Weak<T> {
rc::Weak::default()
}
}
#[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)
}
}
#[cfg(feature = "alloc")]
impl PotentialWell for arc::Weak<()> {
type Well<T> = arc::Weak<T>;
#[inline]
fn new<T>(_: T) -> arc::Weak<T> {
arc::Weak::default()
}
}
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<()>>>;