use super::*;
use core::pin::Pin;
unsafe impl<T> CustomWrapper for Pin<T> {
type Output = Pin<T>;
}
unsafe impl<'a, T> CustomWrapper for &Pin<&'a T> {
type Output = Pin<Helper<&'a T>>;
}
unsafe impl<'a, T> CustomWrapper for &Pin<&'a mut T> {
type Output = Pin<Helper<&'a mut T>>;
}
unsafe impl<T: CustomWrapper> CustomWrapper for &&Pin<T> {
type Output = Pin<T::Output>;
}
macro_rules! impl_pin {
($($maybe_mut:tt)?) => {
unsafe impl<'a, T:PinProjectable> Projectable for Pin<&'a $($maybe_mut)? T> {
type Target = T;
type Marker = Marker<Pin<&'a $($maybe_mut)? ()>>;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
(
unsafe { transmute_copy(self) },
Marker::new()
)
}
}
impl<'a, T: 'a> ProjectableMarker<T> for Marker<Pin<&'a $($maybe_mut)? ()>> {
type Output = Pin<&'a $($maybe_mut)? T>;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
Pin::new_unchecked(&$($maybe_mut)? *raw)
}
}
impl<'a, T: Unpin> FinalizeProjection for Pin<&'a $($maybe_mut)? T> {
type Output = &'a $($maybe_mut)? T;
unsafe fn finalize(&self) -> Self::Output {
transmute_copy(self)
}
}
impl<'a, T> FinalizeProjection for &Pin<&'a $($maybe_mut)? Unpinned<T>> {
type Output = &'a $($maybe_mut)? T;
unsafe fn finalize(&self) -> Self::Output {
transmute_copy(*self)
}
}
};
}
unsafe impl<'a, P: Deref<Target = T> + Projectable<Target = T>, T: PinProjectable> Projectable
for Pin<P>
{
type Target = T;
type Marker = PinMarker<P::Marker>;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
let res = unsafe { transmute_copy::<_, P>(self) }.get_raw();
(res.0, PinMarker(res.1))
}
}
pub struct PinMarker<T>(pub T);
impl<'a, T: 'a, P: ProjectableMarker<T>> ProjectableMarker<T> for PinMarker<P>
where
P::Output: Deref,
{
type Output = Pin<P::Output>;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
Pin::new_unchecked(self.0.from_raw(raw))
}
}
impl<'a, P> FinalizeProjection for Pin<P>
where
P: Deref,
P::Target: Unpin,
{
type Output = P;
unsafe fn finalize(&self) -> Self::Output {
transmute_copy(self)
}
}
impl<'a, T> FinalizeProjection for &Pin<&'a Unpinned<T>> {
type Output = &'a T;
unsafe fn finalize(&self) -> Self::Output {
transmute_copy(*self)
}
}
impl<'a, T> FinalizeProjection for &Pin<&'a mut Unpinned<T>> {
type Output = &'a mut T;
unsafe fn finalize(&self) -> Self::Output {
transmute_copy(*self)
}
}
impl<'a, T> FinalizeProjection for &Pin<OwningRef<'a, Unpinned<T>>> {
type Output = OwningRef<'a, T>;
unsafe fn finalize(&self) -> Self::Output {
transmute_copy(*self)
}
}
#[repr(transparent)]
pub struct Unpinned<T>(pub T);
impl<T> Unpin for Unpinned<T> {}
impl<T> Deref for Unpinned<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Unpinned<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> DerefOwned for Unpinned<T> {}
#[doc(hidden)]
pub struct PinnedMarker<'a>(&'a (), PhantomPinned);
pub unsafe trait PinProjectable {}
pub trait PinDrop {
fn drop(_self: CallGuard<Pin<&mut Self>>);
}
pub struct CallGuard<T>(T);
impl<T> CallGuard<T> {
pub unsafe fn new(from: T) -> Self {
CallGuard(from)
}
pub fn into_inner(self) -> T {
self.0
}
}
#[macro_export]
macro_rules! pin_projectable {
([ ! $($generics:tt)*] [$($type:tt)*] [] < $($tail:tt)* ) => { $crate::pin_projectable!{[ !! $($generics)* <] [ $($type)*] [] $($tail)*} };
([ ! $($generics:tt)*] [$($type:tt)*] [] << $($tail:tt)* ) => { $crate::pin_projectable!{[ !! $($generics)* <] [ $($type)*] [] < $($tail)*} };
([ !! $($generics:tt)*] [$($type:tt)*] [] > $($tail:tt)* ) => { $crate::pin_projectable!{[ ! $($generics)* >] [ $($type)*] [] $($tail)*} };
([ !! $($generics:tt)*] [$($type:tt)*] [] >> $($tail:tt)* ) => { $crate::pin_projectable!{[ ! $($generics)* >] [ $($type)*] [] > $($tail)*} };
([ !! $($generics:tt)*] [$($type:tt)*] [] $token:tt $($tail:tt)* ) => { $crate::pin_projectable!{[!! $($generics)* $token] [$($type)*] [] $($tail)*} };
([ ! $($generics:tt)*] [$($type:tt)*] [] , $generic:tt $($tail:tt)* ) => { $crate::pin_projectable!{[ ! $($generics)* , $generic] [ $($type)* , $generic] [] $($tail)*} };
([ ! $($generics:tt)*] [$($type:tt)*] [] > ) => { $crate::pin_projectable!{ [ $($generics)*] [ $($type)* > ] [] } };
([ ! $($generics:tt)*] [$($type:tt)*] [] > where $($tail:tt)* ) => { $crate::pin_projectable!{[ $($generics)*] [ $($type)* >] [$($tail)*] } };
([ ! $($generics:tt)*] [$($type:tt)*] [] $token:tt $($tail:tt)* ) => { $crate::pin_projectable!{[! $($generics)* $token] [$($type)*] [] $($tail)*} };
([$($generics:tt)*] [! $($type:tt)*] [] < $generic:tt $($tail:tt)* ) => { $crate::pin_projectable!{ [ ! $($generics)* $generic] [$($type)* < $generic] [] $($tail)*} };
([$($generics:tt)*] [! $($type:tt)*] [] $name_part:tt $($tail:tt)* ) => { $crate::pin_projectable!{ [ $($generics)* ] [! $($type)* $name_part] [] $($tail)*} };
([$($generics:tt)*] [! $($type:tt)*] [] ) => { $crate::pin_projectable!{ [ $($generics)* ] [ $($type)* ] [] } };
([$($generics:tt)*] [$($type:tt)+] [$($where:tt)*] ) => {
impl<'__inner,$($generics)*> core::marker::Unpin for $($type)+ where $crate::pin::PinnedMarker<'__inner>:Unpin,$($where)*{}
unsafe impl<$($generics)*> $crate::pin::PinProjectable for $($type)+ where $($where)*{}
impl<$($generics)*> core::ops::Drop for $($type)+ where $($where)*{
fn drop(&mut self){
unsafe {
let mut helper = &mut *(self as *mut _ as *mut $crate::Helper<$($type)+>);
use $crate::pin::PinDropDelegator;
(&mut &mut helper).delegate()
}
}
}
};
( $($tail:tt)* ) => { $crate::pin_projectable!{ [] [!] [] $($tail)* } };
}
#[macro_export]
#[allow(non_snake_case)]
macro_rules! PinProjectable {
( [struct $($head:tt)*] { $($inner:tt)* } ) => {
$crate::pin_projectable!{ $($head)* }
};
( [enum $($head:tt)*] { $($inner:tt)* } ) => {
$crate::pin_projectable!{ $($head)* }
};
( [struct $($head:tt)*] ($($inner:tt)*) ; ) => {
$crate::pin_projectable!{ $($head)* }
};
( [enum $($head:tt)*] ($($inner:tt)*) ; ) => {
$crate::pin_projectable!{ $($head)* }
};
( [$($head:tt)*] $token:tt $($tail:tt)* ) => { $crate::PinProjectable!{ [$($head)* $token] $($tail)* } };
( $($tail:tt)* ) => { $crate::PinProjectable!{ [] $($tail)* } };
}
#[doc(hidden)]
pub unsafe trait PinDropDelegator {
unsafe fn delegate(&mut self);
}
unsafe impl<T> PinDropDelegator for &mut Helper<T> {
unsafe fn delegate(&mut self) {}
}
unsafe impl<T: PinDrop> PinDropDelegator for Helper<T> {
unsafe fn delegate(&mut self) {
PinDrop::drop(CallGuard::new(Pin::new_unchecked(&mut self.0)))
}
}