use std::cell::Cell;
use std::marker::PhantomData;
use std::mem::{transmute_copy, ManuallyDrop, MaybeUninit};
use std::ops::{Deref, DerefMut};
use std::pin::Pin;
use std::{mem, ptr};
#[doc(hidden)]
pub unsafe trait Preprocess {
type Output;
fn preprocess(&self) -> Self::Output;
}
pub unsafe trait MarkerNonOwned {}
#[doc(hidden)]
#[repr(transparent)]
pub struct Owned<T>(ManuallyDrop<T>);
unsafe impl<T> Preprocess for ManuallyDrop<T> {
type Output = Owned<T>;
fn preprocess(&self) -> Self::Output {
unsafe { transmute_copy(self) }
}
}
unsafe impl<T: MarkerNonOwned> Preprocess for &ManuallyDrop<T> {
type Output = T;
fn preprocess(&self) -> Self::Output {
unsafe { transmute_copy(self) }
}
}
#[doc(hidden)]
#[repr(transparent)]
pub struct Helper<T>(T);
unsafe impl<'a, T> Preprocess for &&ManuallyDrop<&'a T> {
type Output = Helper<&'a T>;
fn preprocess(&self) -> Self::Output {
unsafe { transmute_copy(**self) }
}
}
unsafe impl<'a, T> Preprocess for &&ManuallyDrop<&'a mut T> {
type Output = Helper<&'a mut T>;
fn preprocess(&self) -> Self::Output {
unsafe { transmute_copy(**self) }
}
}
pub unsafe trait CustomWrapper {
type Output;
}
unsafe impl<T: CustomWrapper> Preprocess for &&&ManuallyDrop<T> {
type Output = T::Output;
fn preprocess(&self) -> Self::Output {
unsafe { transmute_copy(self) }
}
}
pub unsafe trait Projectable {
type Target;
type Marker;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker);
}
pub trait ProjectableMarker<T> {
type Output;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output;
}
#[doc(hidden)]
pub struct DerefMarkerWrapper<T>(PhantomData<T>);
impl<T> DerefMarkerWrapper<T> {
#[doc(hidden)]
pub unsafe fn new(value: &T) -> Self {
Self(PhantomData)
}
}
#[doc(hidden)]
pub struct MaybeDerefMarkerWrapper<'a, T>(&'a T);
impl<'a, T> MaybeDerefMarkerWrapper<'a, T> {
#[doc(hidden)]
pub unsafe fn new(value: &'a T) -> Self {
Self(value)
}
}
impl<T, M: ProjectableMarker<T>> ProjectableMarker<T> for MaybeDerefMarkerWrapper<'_, M> {
type Output = M::Output;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
self.0.from_raw(raw)
}
}
impl<T, M> ProjectableMarker<T> for &MaybeDerefMarkerWrapper<'_, M>
where
DerefMarkerWrapper<M>: ProjectableMarker<T>,
{
type Output = <DerefMarkerWrapper<M> as ProjectableMarker<T>>::Output;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
DerefMarkerWrapper::new(self.0).from_raw(raw)
}
}
unsafe impl<T> Projectable for Owned<T> {
type Target = T;
type Marker = [(); 0];
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
(self as *const Self as *mut Self as *mut T, [])
}
}
impl<T> ProjectableMarker<T> for [(); 0] {
type Output = T;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
ptr::read(raw as *const T as *const _)
}
}
pub trait Unwrap {
type Target;
fn unwrap(self) -> Self::Target;
}
impl<T> Unwrap for Box<T> {
type Target = T;
fn unwrap(self) -> Self::Target {
*self
}
}
impl<T: Unwrap> ProjectableMarker<T> for DerefMarkerWrapper<[(); 0]> {
type Output = T::Target;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
ptr::read(raw as *const T).unwrap()
}
}
unsafe impl<'a, T> Projectable for Helper<&'a mut T> {
type Target = T;
type Marker = &'a mut ();
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
(
unsafe { ptr::read(self as *const _ as *const *mut Self::Target) },
Box::leak(Box::new(())),
)
}
}
impl<'a, T: 'a> ProjectableMarker<T> for &'a mut () {
type Output = &'a mut T;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
&mut *raw
}
}
impl<'a, T: DerefMut + 'a> ProjectableMarker<T> for DerefMarkerWrapper<&'a mut ()> {
type Output = &'a mut T::Target;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
&mut **raw
}
}
unsafe impl<'a, T> Projectable for Helper<&'a T> {
type Target = T;
type Marker = &'a ();
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
(self.0 as *const _ as _, Box::leak(Box::new(())))
}
}
impl<'a, T: 'a> ProjectableMarker<T> for &'a () {
type Output = &'a T;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
&*raw
}
}
impl<'a, T: Deref + 'a> ProjectableMarker<T> for DerefMarkerWrapper<&'a ()> {
type Output = &'a T::Target;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
&**raw
}
}
unsafe impl<'a, T> Projectable for &Helper<&'a Cell<T>> {
type Target = T;
type Marker = &'a Cell<()>;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
(
unsafe { transmute_copy(*self) },
Box::leak(Box::new(Cell::new(()))),
)
}
}
impl<'a, T: 'a> ProjectableMarker<T> for &'a Cell<()> {
type Output = &'a Cell<T>;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
&*(raw as *mut Cell<T>)
}
}
unsafe impl<'a, T> Projectable for &Helper<&'a mut MaybeUninit<T>> {
type Target = T;
type Marker = &'a mut MaybeUninit<()>;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
(
unsafe { ptr::read(*self as *const _ as *const *mut Self::Target) },
Box::leak(Box::new(MaybeUninit::new(()))),
)
}
}
impl<'a, T: 'a> ProjectableMarker<T> for &'a mut MaybeUninit<()> {
type Output = &'a mut MaybeUninit<T>;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
&mut *(raw as *mut MaybeUninit<T>)
}
}
unsafe impl<T> MarkerNonOwned for Pin<T> {}
macro_rules! impl_pin {
($($maybe_mut:tt)?) => {
unsafe impl<'a, T> Projectable for Pin<&'a $($maybe_mut)? T> {
type Target = T;
type Marker = Pin<&'a $($maybe_mut)? ()>;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
(
unsafe { ptr::read(self as *const _ as *const *mut Self::Target) },
Pin::new(Box::leak(Box::new(()))),
)
}
}
impl<'a, T: 'a> ProjectableMarker<T> for 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 + DerefMut + 'a> ProjectableMarker<T> for DerefMarkerWrapper<Pin<&'a $($maybe_mut)? ()>> {
type Output = &'a $($maybe_mut)? T::Target;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
&$($maybe_mut)? **raw
}
}
#[allow(drop_bounds)]
unsafe impl<'a, T: Drop> Projectable for &Pin<&'a $($maybe_mut)? T> {
type Target = T;
type Marker = Pin<&'a $($maybe_mut)? ()>;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
panic!("struct must also implement PinDrop")
}
}
#[allow(drop_bounds)]
unsafe impl<'a, T: Drop + PinDrop> Projectable for &&Pin<&'a $($maybe_mut)? T> {
type Target = T;
type Marker = Pin<&'a $($maybe_mut)? ()>;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
(
unsafe { ptr::read(self as *const _ as *const *mut Self::Target) },
Pin::new(Box::leak(Box::new(()))),
)
}
}
#[cfg(feature = "pin-project")]
unsafe impl<'a, T: pin_project::__private::PinnedDrop> Projectable for &&&Pin<&'a $($maybe_mut)? T> {
type Target = T;
type Marker = Pin<&'a $($maybe_mut)? ()>;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
panic!("this crate is incompatible with pin-project when both are used on the same struct")
}
}
};
}
impl_pin! {}
impl_pin! { mut }
pub trait PinDrop {
unsafe fn drop(self: Pin<&mut Self>);
}
#[macro_export]
macro_rules! pin_drop {
(impl PinDrop for $name:ident {}) => {};
}
pub trait FinalizeProjection {
type Output;
unsafe fn finalize(&self) -> Self::Output;
}
impl<'a, T: Unpin> FinalizeProjection for Pin<&'a mut T> {
type Output = &'a mut 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)
}
}
#[doc(hidden)]
pub trait Finalizer {
type Output;
unsafe fn call_finalize(&self) -> Self::Output;
}
impl<T> Finalizer for ManuallyDrop<T> {
type Output = T;
unsafe fn call_finalize(&self) -> Self::Output {
transmute_copy(self)
}
}
impl<T: FinalizeProjection> Finalizer for &ManuallyDrop<T> {
type Output = T::Output;
unsafe fn call_finalize(&self) -> Self::Output {
self.finalize()
}
}
impl<'a, T> Finalizer for &&'a ManuallyDrop<T>
where
&'a T: FinalizeProjection,
{
type Output = <&'a T as FinalizeProjection>::Output;
unsafe fn call_finalize(&self) -> Self::Output {
transmute_copy::<_, &T>(*self).finalize()
}
}
impl<'a, 'b, T> Finalizer for &&'a &'b ManuallyDrop<T>
where
&'a &'b T: FinalizeProjection,
{
type Output = <&'a &'b T as FinalizeProjection>::Output;
unsafe fn call_finalize(&self) -> Self::Output {
transmute_copy::<_, &&T>(*self).finalize()
}
}
impl<'a, 'b, 'c, T> Finalizer for &&'a &'b &'c ManuallyDrop<T>
where
&'a &'b &'c T: FinalizeProjection,
{
type Output = <&'a &'b &'c T as FinalizeProjection>::Output;
unsafe fn call_finalize(&self) -> Self::Output {
transmute_copy::<_, &&&T>(*self).finalize()
}
}
#[repr(transparent)]
pub struct Unpinned<T>(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
}
}
#[macro_export]
macro_rules! project {
(let $struct:ident { $($fields:tt)+ } = $val: expr) => {
let var = core::mem::ManuallyDrop::new($val);
let var = {
use $crate::Preprocess;
(&&&var).preprocess()
};
let (ptr,marker) = {
use $crate::Projectable;
(&&&&&&& var).get_raw()
};
if false{
let $struct { .. } = unsafe { &*ptr };
}
$crate::project_fields_inner! { [ptr marker] $($fields)+ }
};
(let $struct:ident ( $($fields:tt)+ ) = $val: expr) => {
let var = core::mem::ManuallyDrop::new($val);
let var = {
use $crate::Preprocess;
(&&&var).preprocess()
};
let (ptr,marker) = {
use $crate::Projectable;
(&&&&&&& var).get_raw()
};
if false{
let $struct { .. } = unsafe{ &*ptr };
}
$crate::project_tuple_fields! { [ptr marker] [] [] $($fields)+ }
};
( $var:ident -> $field:tt) => { $crate::project! { ($var) -> $field} };
(( $var:expr ) -> $field:tt) => {
{
let var = core::mem::ManuallyDrop::new($var);
let var = {
use $crate::Preprocess;
(&&&var).preprocess()
};
let (ptr,marker) = {
use $crate::Projectable;
(&&&&&&& var).get_raw()
};
$crate::project_fields_inner! { [ptr marker] $field : temp_name }
temp_name
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! project_tuple_fields {
([$ptr:ident $marker:ident] [$($idx:tt)*] [$($pattern:tt)*] , $($tail:tt)* ) => {
$crate::project_fields_inner! { [$ptr $marker] { $($idx)* } : $($pattern)* }
$crate::project_tuple_fields! { [$ptr $marker] [$($idx)* !] [] $($tail)* }
};
([$ptr:ident $marker:ident] [$($idx:tt)*] [$($pattern:tt)*] $next:tt $($tail:tt)* ) => {
$crate::project_tuple_fields! { [$ptr $marker] [$($idx)*] [$($pattern)* $next] $($tail)* }
};
([$ptr:ident $marker:ident] [$($idx:tt)*] [$($pattern:tt)*] ) => {
$crate::project_fields_inner! { [$ptr $marker] { $($idx)* } : $($pattern)* }
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! field_addr {
((*$ptr:ident).) => {
core::ptr::addr_of_mut!((*$ptr).1)
};
((*$ptr:ident).!) => {
core::ptr::addr_of_mut!((*$ptr).1)
};
((*$ptr:ident).!!) => {
core::ptr::addr_of_mut!((*$ptr).2)
};
((*$ptr:ident).!!!) => {
core::ptr::addr_of_mut!((*$ptr).3)
};
((*$ptr:ident).!!!!) => {
core::ptr::addr_of_mut!((*$ptr).4)
};
((*$ptr:ident).!!!!!) => {
core::ptr::addr_of_mut!((*$ptr).5)
};
((*$ptr:ident).!!!!!!) => {
core::ptr::addr_of_mut!((*$ptr).6)
};
((*$ptr:ident).!!!!!!!) => {
core::ptr::addr_of_mut!((*$ptr).7)
};
((*$ptr:ident).!!!!!!!!) => {
core::ptr::addr_of_mut!((*$ptr).8)
};
((*$ptr:ident).!!!!!!!!!) => {
core::ptr::addr_of_mut!((*$ptr).9)
};
((*$ptr:ident).!!!!!!!!!!) => {
core::ptr::addr_of_mut!((*$ptr).10)
};
((*$ptr:ident).$field:tt) => {
core::ptr::addr_of_mut!((*$ptr).$field)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! project_fields_inner {
( [$ptr:tt $marker:ident] $field:tt : $new_name:ident) => { $crate::project_fields_inner! { [$ptr $marker] $field : $new_name , } };
( [$ptr:tt $marker:ident] $field:tt : * $new_name:ident) => { $crate::project_fields_inner! {[$ptr $marker] $field : * $new_name , }};
( [$ptr:tt $marker:ident] { $($field:tt)* } : $new_name:ident , $($tail:tt)*) => {
let $new_name = unsafe {
use $crate::{ProjectableMarker,Finalizer};
let tmp = core::mem::ManuallyDrop::new($marker.from_raw($crate::field_addr!((*$ptr). $($field)* )));
(&&&& tmp).call_finalize()
};
$crate::project_fields_inner!{ [$ptr $marker] $($tail)* }
};
( [$ptr:tt $marker:ident] { $($field:tt)* } : * $new_name:ident , $($tail:tt)*) => {
let $new_name = unsafe {
use $crate::{ProjectableMarker,Finalizer};
let deref_marker = $crate::DerefMarkerWrapper::new(&$marker);
let tmp = core::mem::ManuallyDrop::new(deref_marker.from_raw($crate::field_addr!((*$ptr). $($field)* )));
(&&&& tmp).call_finalize()
};
$crate::project_fields_inner!{ [$ptr $marker] $($tail)* }
};
( [$ptr:tt $marker:ident] $field:tt : $($tail:tt)* ) => { $crate::project_fields_inner! {[$ptr $marker] { $field } : $($tail)* }};
( [$ptr:tt $marker:ident] * $field:tt $($tail:tt)*) => { $crate::project_fields_inner! { [$ptr $marker] $field : * $field $($tail)* } };
( [$ptr:tt $marker:ident] $field:tt $($tail:tt)*) => { $crate::project_fields_inner! { [$ptr $marker] $field : $field $($tail)* } };
( [$ptr:tt $marker:ident] ) => {};
}