#[cfg(any(test, feature = "alloc"))]
use alloc::{
boxed::Box,
sync::{self as arc, Arc},
};
use core::{
mem,
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
};
#[cfg(feature = "alloc")]
use {
crate::atomic::{PotentialAtomic, PotentialAtomicOption},
alloc::rc::{self, Rc},
};
pub unsafe trait Well {
type Target;
unsafe fn insert(ptr: NonNull<Self::Target>) -> Self;
fn remove(self) -> NonNull<Self::Target>;
}
pub type Target<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 Strong: StrongWell + Deref<Target = Self::Target>;
fn access(&self) -> Option<Self::Strong>;
fn weaken(access: &Self::Strong) -> Self;
}
pub unsafe trait StrongWell:
Deref<Target: Sized> + Well<Target = <Self as Deref>::Target>
{
}
unsafe impl<W: StrongWell> Well for Pin<W> {
type Target = Target<W>;
#[inline]
unsafe fn insert(ptr: NonNull<Target<W>>) -> Pin<W> {
unsafe { Pin::new_unchecked(W::insert(ptr)) }
}
#[inline]
fn remove(self) -> NonNull<Target<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(any(test, 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 Strong = Rc<T>;
#[inline]
fn access(&self) -> Option<Rc<T>> {
self.upgrade()
}
#[inline]
fn weaken(access: &Rc<T>) -> rc::Weak<T> {
Rc::downgrade(access)
}
}
#[cfg(any(test, 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(any(test, feature = "alloc"))]
unsafe impl<T> StrongWell for Arc<T> {}
#[cfg(any(test, 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(any(test, feature = "alloc"))]
unsafe impl<T> WeakWell for arc::Weak<T> {
type Strong = Arc<T>;
#[inline]
fn access(&self) -> Option<Arc<T>> {
self.upgrade()
}
#[inline]
fn weaken(access: &Arc<T>) -> arc::Weak<T> {
Arc::downgrade(access)
}
}
pub trait PotentialWell {
type Well<T>: KineticWell<Target = T>;
fn new<T>(data: T) -> Self::Well<T>;
}
pub trait StrongPotentialWell: PotentialWell {
type StrongWell<T>: StrongWell
+ Deref<Target = T>
+ KineticWell<Potential: PotentialWell<Well<T> = Self::StrongWell<T>>>
+ KineticWell<Potential = Self>;
}
impl<W: StrongPotentialWell> StrongPotentialWell for Pin<W> {
type StrongWell<T> = Pin<W::StrongWell<T>>;
}
impl<W: StrongPotentialWell> PotentialWell for Pin<W> {
type Well<T> = Pin<W::StrongWell<T>>;
fn new<T>(data: T) -> Self::Well<T> {
let well = mem::ManuallyDrop::new(W::new(data));
let well = unsafe { mem::transmute_copy(&well) };
unsafe { Pin::new_unchecked(well) }
}
}
impl<W: StrongWell + KineticWell<Potential: StrongPotentialWell<StrongWell<Target<W>> = W>>>
KineticWell for Pin<W>
{
type Potential = Pin<W::Potential>;
}
pub trait WeakPotentialWell: PotentialWell {
type Strong: StrongPotentialWell;
type WeakWell<T>: WeakWell<Target = T, Strong: KineticWell<Potential = Self::Strong>>
+ KineticWell<Potential: PotentialWell<Well<T> = Self::WeakWell<T>>>;
}
pub trait KineticWell: Well {
type Potential: PotentialWell<Well<Target<Self>> = Self>;
}
#[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 StrongPotentialWell for Box<()> {
type StrongWell<T> = Box<T>;
}
#[cfg(any(test, feature = "alloc"))]
impl<T> KineticWell for Box<T> {
type Potential = Box<()>;
}
#[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 StrongPotentialWell for Rc<()> {
type StrongWell<T> = Rc<T>;
}
#[cfg(feature = "alloc")]
impl<T> KineticWell for Rc<T> {
type Potential = Rc<()>;
}
#[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 WeakPotentialWell for rc::Weak<()> {
type Strong = Rc<()>;
type WeakWell<T> = rc::Weak<T>;
}
#[cfg(feature = "alloc")]
impl<T> KineticWell for rc::Weak<T> {
type Potential = rc::Weak<()>;
}
#[cfg(any(test, feature = "alloc"))]
impl PotentialWell for Arc<()> {
type Well<T> = Arc<T>;
#[inline]
fn new<T>(data: T) -> Arc<T> {
Arc::new(data)
}
}
#[cfg(any(test, feature = "alloc"))]
impl StrongPotentialWell for Arc<()> {
type StrongWell<T> = Arc<T>;
}
#[cfg(any(test, feature = "alloc"))]
impl<T> KineticWell for Arc<T> {
type Potential = Arc<()>;
}
#[cfg(any(test, feature = "alloc"))]
impl PotentialWell for arc::Weak<()> {
type Well<T> = arc::Weak<T>;
#[inline]
fn new<T>(_: T) -> arc::Weak<T> {
arc::Weak::default()
}
}
#[cfg(any(test, feature = "alloc"))]
impl WeakPotentialWell for arc::Weak<()> {
type Strong = Arc<()>;
type WeakWell<T> = arc::Weak<T>;
}
#[cfg(any(test, feature = "alloc"))]
impl<T> KineticWell for arc::Weak<T> {
type Potential = arc::Weak<()>;
}
#[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<()>>>;