use core::{marker::PhantomData, mem::offset_of, ptr::NonNull};
use intrusive_collections::{DefaultLinkOps, LinkOps};
use super::{Continuation, Link};
use crate::{
config::Config,
ptr::{IntrusivelyCounted, Irc},
};
pub struct Adapter<C: ?Sized + Config, P = Irc<Continuation<'static, C>>> {
link_ops: <Link as DefaultLinkOps>::Ops,
pointer_ops: PointerOps<Continuation<'static, C>, P>,
}
impl<C: ?Sized + Config, P> Adapter<C, P> {
pub const NEW: Self = Adapter {
link_ops: <Link as DefaultLinkOps>::NEW,
pointer_ops: PointerOps(PhantomData),
};
}
impl<C: ?Sized + Config, P> Default for Adapter<C, P> {
fn default() -> Self {
Self::NEW
}
}
impl<C: ?Sized + Config, P> Clone for Adapter<C, P> {
fn clone(&self) -> Self {
*self
}
}
impl<C: ?Sized + Config, P> Copy for Adapter<C, P> {}
unsafe impl<C, P> intrusive_collections::Adapter for Adapter<C, P>
where
C: ?Sized + Config,
P: From<Irc<Continuation<'static, C>>> + Into<Irc<Continuation<'static, C>>>,
{
type LinkOps = <Link as DefaultLinkOps>::Ops;
type PointerOps = PointerOps<Continuation<'static, C>, P>;
unsafe fn get_value(
&self,
link: <Self::LinkOps as LinkOps>::LinkPtr,
) -> *const Continuation<'static, C> {
intrusive_collections::container_of!(link.as_ptr(), Continuation<'static, C>, hook)
}
unsafe fn get_link(
&self,
value: *const Continuation<'static, C>,
) -> <Self::LinkOps as LinkOps>::LinkPtr {
unsafe {
let ptr = (value as *const u8).add(offset_of!(Continuation<'static, C>, hook));
NonNull::new_unchecked(ptr as *mut _)
}
}
fn link_ops(&self) -> &Self::LinkOps {
&self.link_ops
}
fn link_ops_mut(&mut self) -> &mut Self::LinkOps {
&mut self.link_ops
}
fn pointer_ops(&self) -> &Self::PointerOps {
&self.pointer_ops
}
}
pub struct PointerOps<V, P>(PhantomData<(V, P)>);
impl<V, P> PointerOps<V, P> {
pub const NEW: Self = PointerOps(PhantomData);
}
impl<V, P> Clone for PointerOps<V, P> {
fn clone(&self) -> Self {
*self
}
}
impl<V, P> Copy for PointerOps<V, P> {}
unsafe impl<V, P> intrusive_collections::PointerOps for PointerOps<V, P>
where
V: IntrusivelyCounted,
P: From<Irc<V>> + Into<Irc<V>>,
{
type Value = V;
type Pointer = P;
unsafe fn from_raw(&self, value: *const V) -> P {
unsafe { P::from(Irc::from_raw(NonNull::new_unchecked(value as *mut V))) }
}
fn into_raw(&self, ptr: P) -> *const V {
Irc::into_raw(P::into(ptr)).as_ptr() as *const V
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! intrusive_adapter_newtype {
() => {};
($name:ident) => {
unsafe impl<C: ?Sized + Config> ::intrusive_collections::Adapter for $name<C> {
type LinkOps = <$crate::continuation::Adapter<C, $crate::calendar::IdleOnDrop<C>> as ::intrusive_collections::Adapter>::LinkOps;
type PointerOps = <$crate::continuation::Adapter<C, $crate::calendar::IdleOnDrop<C>> as ::intrusive_collections::Adapter>::PointerOps;
#[inline]
unsafe fn get_value(&self, link: <Self::LinkOps as ::intrusive_collections::LinkOps>::LinkPtr) -> *const <Self::PointerOps as ::intrusive_collections::PointerOps>::Value {
unsafe { self.0.get_value(link) }
}
#[inline]
unsafe fn get_link(&self, value: *const <Self::PointerOps as ::intrusive_collections::PointerOps>::Value) -> <Self::LinkOps as ::intrusive_collections::LinkOps>::LinkPtr {
unsafe { self.0.get_link(value) }
}
#[inline]
fn link_ops(&self) -> &Self::LinkOps {
self.0.link_ops()
}
#[inline]
fn link_ops_mut(&mut self) -> &mut Self::LinkOps {
self.0.link_ops_mut()
}
#[inline]
fn pointer_ops(&self) -> &Self::PointerOps {
self.0.pointer_ops()
}
}
};
($name:ident, $($tail:ident),*) => {
$crate::intrusive_adapter_newtype!($name);
$crate::intrusive_adapter_newtype!($($tail),*);
};
($($name:ident,)+) => {
$crate::intrusive_adapter_newtype!($($name),*);
};
}