Skip to content

Instantly share code, notes, and snippets.

@CAD97
Created April 26, 2023 05:40
Show Gist options
  • Save CAD97/a99ecf152d72614ac7da86b0b5aa2515 to your computer and use it in GitHub Desktop.
Save CAD97/a99ecf152d72614ac7da86b0b5aa2515 to your computer and use it in GitHub Desktop.
another coercion sketch
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