use crate::{
project, CustomWrapper, DropLeftovers, Marker, Owned, OwningMarker, Projectable,
ProjectableMarker,
};
use alloc::boxed::Box;
use core::marker::PhantomData;
use core::mem::{align_of, size_of, transmute_copy, ManuallyDrop};
use core::ops::{Deref, DerefMut};
pub struct GenericPointer<T: ?Sized, M> {
ptr: *mut (),
ty: PhantomData<*mut T>,
marker: M,
}
impl<T, M: ProjectableMarker<T>> GenericPointer<T, M> {
pub fn into_concrete(self) -> M::Output {
unsafe { self.marker.from_raw(self.ptr as _) }
}
#[doc(hidden)]
pub unsafe fn new(ptr: *mut T, marker: M) -> Self {
Self {
ptr: ptr as _,
ty: PhantomData,
marker,
}
}
}
unsafe impl<T, M> CustomWrapper for GenericPointer<T, M> {
type Output = GenericPointer<T, M>;
}
unsafe impl<T, M> Projectable for GenericPointer<T, M> {
type Target = T;
type Marker = GenericMarker<M>;
fn get_raw(&self) -> (*mut Self::Target, Self::Marker) {
unsafe { (self.ptr as _, GenericMarker(transmute_copy(&self.marker))) }
}
}
pub struct GenericMarker<M>(M);
impl<T, M> ProjectableMarker<T> for GenericMarker<M>
where
M: ProjectableMarker<T> + Clone,
{
type Output = GenericPointer<T, M>;
unsafe fn from_raw(&self, raw: *mut T) -> Self::Output {
GenericPointer {
ptr: raw as _,
ty: PhantomData,
marker: self.0.clone(),
}
}
}
#[macro_export]
macro_rules! generic_ptr {
($val:expr) => {
unsafe {
let var = core::mem::ManuallyDrop::new($val);
let var = {
use $crate::Preprocess;
core::mem::ManuallyDrop::new((&&&&&var).preprocess())
};
let (ptr, marker) = {
use $crate::Projectable;
(&&&&&&&*var).get_raw()
};
$crate::generic::GenericPointer::new(ptr, marker)
}
};
(let $name:ident = $val:expr) => {
let var = core::mem::ManuallyDrop::new($val);
let var = unsafe {
use $crate::Preprocess;
core::mem::ManuallyDrop::new((&&&&&var).preprocess())
};
let $name = unsafe {
use $crate::Projectable;
let (ptr, marker) = (&&&&&&&*var).get_raw();
$crate::generic::GenericPointer::new(ptr, marker)
};
};
($name:ident[$idx:expr] = $val:expr) => {};
($name:ident[$idx:expr]) => {};
}
pub trait GenericDeref<M>: DerefTarget {
fn deref_generic(_self: GenericPointer<Self, M>) -> GenericPointer<Self::Target, M>
where
M: DropLeftoversOf<Self>;
}
pub trait DerefTarget {
type Target: ?Sized;
}
impl<X, T: ?Sized + DerefTarget> DerefTarget for GenericPointer<T, X> {
type Target = T::Target;
}
pub trait DropLeftoversOf<X: ?Sized, Idx = DerefOperation>: Sized {
unsafe fn drop_leftovers(_self: ManuallyDrop<GenericPointer<X, Self>>, idx: Idx) {}
}
pub struct DerefOperation;
#[cfg(feature = "std")]
impl<T> DropLeftoversOf<Box<T>> for OwningMarker<'_, Box<T>> {
unsafe fn drop_leftovers(
_self: ManuallyDrop<GenericPointer<Box<T>, Self>>,
idx: DerefOperation,
) {
let mut b = ManuallyDrop::new(ManuallyDrop::into_inner(_self).into_concrete());
unsafe {
crate::DerefOwned::drop_leftovers(&mut b);
}
}
}
impl<T> DropLeftoversOf<Owned<T>> for OwningMarker<'_, Owned<T>> {
unsafe fn drop_leftovers(
_self: ManuallyDrop<GenericPointer<Owned<T>, Self>>,
idx: DerefOperation,
) {
}
}
impl<T, I> DropLeftoversOf<T, I> for Marker<&'_ ()> {}
impl<T, I> DropLeftoversOf<T, I> for Marker<&'_ mut ()> {}
pub struct DropLeftoversGeneric<'a, T, M>(
ManuallyDrop<GenericPointer<T, M>>,
PhantomData<fn(&'a ()) -> &'a ()>,
);
pub trait DropV2<M> {
fn drop(_self: ManuallyDrop<GenericPointer<Self, M>>);
}
#[doc(hidden)]
pub trait FnV2<M, Args> {
type Output;
fn call(_self: GenericPointer<Self, M>, args: Args) -> Self::Output;
}
pub trait IndexV2<M, I> {
type Output;
fn index(_self: GenericPointer<Self, M>, idx: I) -> GenericPointer<Self::Output, M>
where
M: DropLeftoversOf<Self, I>;
}