Created
April 26, 2023 05:40
-
-
Save CAD97/a99ecf152d72614ac7da86b0b5aa2515 to your computer and use it in GitHub Desktop.
another coercion sketch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::future::Future; | |
use std::convert::Infallible; | |
#[derive(Debug, Copy, Clone)] | |
pub struct Coercion<T: ?Sized, U: ?Sized>(fn(*mut T) -> *mut U); | |
impl<T: ?Sized, U: ?Sized> Coercion<T, U> { | |
#[inline] | |
pub unsafe fn new(f: fn(*mut T) -> *mut U) -> Self { | |
Coercion(f) | |
} | |
#[inline] | |
pub fn apply(self, ptr: *mut T) -> *mut U { | |
(self.0)(ptr) | |
} | |
} | |
pub unsafe trait Pointer: Sized { | |
type Pointee: ?Sized; | |
type Smarts; | |
fn into_split_ptr(this: Self) -> (*mut Self::Pointee, Self::Smarts); | |
unsafe fn from_split_ptr(ptr: *mut Self::Pointee, smarts: Self::Smarts) -> Self; | |
#[inline] | |
fn into_raw_ptr(this: Self) -> *mut Self::Pointee | |
where | |
Self: Pointer<Smarts = ()>, | |
{ | |
let (ptr, ()) = Self::into_split_ptr(this); | |
ptr | |
} | |
#[inline] | |
unsafe fn from_raw_ptr(ptr: *mut Self::Pointee) -> Self | |
where | |
Self::Smarts: Default, | |
{ | |
Self::from_split_ptr(ptr, Default::default()) | |
} | |
} | |
pub unsafe trait Coerce<Output>: Pointer | |
where | |
Output: Coerce<Output> + Pointer<Smarts = Self::Smarts>, | |
{ | |
#[inline] | |
fn coerce(self) -> Output | |
where | |
Coercion<Self::Pointee, Output::Pointee>: Default, | |
{ | |
self.coerce_with(Coercion::default()) | |
} | |
#[inline] | |
fn coerce_with(self, f: Coercion<Self::Pointee, Output::Pointee>) -> Output { | |
unsafe { | |
let (ptr, smarts) = Self::into_split_ptr(self); | |
let ptr = f.apply(ptr); | |
Pointer::from_split_ptr(ptr, smarts) | |
} | |
} | |
} | |
#[macro_export] | |
macro_rules! Coercion { | |
($T:ty as $U:ty) => { | |
unsafe { $crate::Coercion::<$T, $U>::new(|ptr| ptr) } | |
}; | |
(as $Ty:ty) => { | |
$crate::Coercion! { _ as $Ty } | |
}; | |
() => { | |
$crate::Coercion! { as _ } | |
}; | |
} | |
#[macro_export] | |
macro_rules! make_coercible { | |
(for[$($For:tt)*] $T:ty as $U:ty $(where $($Where:tt)*)?) => { | |
impl <$($For)*> | |
::core::default::Default | |
for $crate::Coercion<$T, $U> | |
$(where $($Where)*)? | |
{ | |
fn default() -> Self { | |
$crate::Coercion!($T as $U) | |
} | |
} | |
}; | |
($T:ty as $U:ty $(where $($Where:tt)*)?) => { | |
$crate::make_coercible! { for[] $T as $U $(where $($Where)*)? } | |
}; | |
} | |
make_coercible!(for[T: ?Sized] T as T); | |
make_coercible!(for[T, const N: usize] [T; N] as [T]); | |
make_coercible!(for['a, F] F as dyn Future<Output = F::Output> + 'a where F: Future + 'a); | |
unsafe impl<T: ?Sized> Pointer for Box<T> { | |
type Pointee = T; | |
type Smarts = WithoutPtr<Box<Infallible>>; | |
#[inline] | |
fn into_split_ptr(this: Self) -> (*mut Self::Pointee, Self::Smarts) { | |
(Box::into_raw(this), WithoutPtr(())) | |
} | |
#[inline] | |
unsafe fn from_split_ptr(ptr: *mut Self::Pointee, WithoutPtr(()): Self::Smarts) -> Self { | |
Box::from_raw(ptr) | |
} | |
} | |
impl<T: ?Sized> sealed::WithoutPtr for Box<T> { | |
type WithoutPtr = (); | |
} | |
mod sealed { | |
pub trait WithoutPtr { | |
type WithoutPtr; | |
} | |
} | |
pub struct WithoutPtr<P: sealed::WithoutPtr>(P::WithoutPtr); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment