use crate::{
lifetime_free::LifetimeFree,
utils::{transmute_unchecked, type_eq, type_eq_non_static},
};
use core::marker::PhantomData;
pub struct CastToken<T: ?Sized>(PhantomData<T>);
impl<T: ?Sized> CastToken<T> {
pub const fn of_val(_value: &T) -> Self {
Self::of()
}
pub const fn of() -> Self {
Self(PhantomData)
}
}
pub trait TryCastMutLifetimeFree<'a, T: ?Sized, U: LifetimeFree + ?Sized> {
#[inline(always)]
fn try_cast(&self, value: &'a mut T) -> Result<&'a mut U, &'a mut T> {
if type_eq_non_static::<T, U>() {
Ok(unsafe { transmute_unchecked::<&mut T, &mut U>(value) })
} else {
Err(value)
}
}
}
impl<'a, T: ?Sized, U: LifetimeFree + ?Sized> TryCastMutLifetimeFree<'a, T, U>
for &&&&&&&(CastToken<&'a mut T>, CastToken<&'a mut U>)
{
}
pub trait TryCastRefLifetimeFree<'a, T: ?Sized, U: LifetimeFree + ?Sized> {
#[inline(always)]
fn try_cast(&self, value: &'a T) -> Result<&'a U, &'a T> {
if type_eq_non_static::<T, U>() {
Ok(unsafe { transmute_unchecked::<&T, &U>(value) })
} else {
Err(value)
}
}
}
impl<'a, T: ?Sized, U: LifetimeFree + ?Sized> TryCastRefLifetimeFree<'a, T, U>
for &&&&&&(CastToken<&'a T>, CastToken<&'a U>)
{
}
pub trait TryCastOwnedLifetimeFree<T, U: LifetimeFree> {
#[inline(always)]
fn try_cast(&self, value: T) -> Result<U, T> {
if type_eq_non_static::<T, U>() {
Ok(unsafe { transmute_unchecked::<T, U>(value) })
} else {
Err(value)
}
}
}
impl<T, U: LifetimeFree> TryCastOwnedLifetimeFree<T, U> for &&&&&(CastToken<T>, CastToken<U>) {}
pub trait TryCastSliceMut<'a, T: 'static, U: 'static> {
#[inline(always)]
fn try_cast(&self, value: &'a mut [T]) -> Result<&'a mut [U], &'a mut [T]> {
if type_eq::<T, U>() {
Ok(unsafe { &mut *(value as *mut [T] as *mut [U]) })
} else {
Err(value)
}
}
}
impl<'a, T: 'static, U: 'static> TryCastSliceMut<'a, T, U>
for &&&&(CastToken<&'a mut [T]>, CastToken<&'a mut [U]>)
{
}
pub trait TryCastSliceRef<'a, T: 'static, U: 'static> {
#[inline(always)]
fn try_cast(&self, value: &'a [T]) -> Result<&'a [U], &'a [T]> {
if type_eq::<T, U>() {
Ok(unsafe { &*(value as *const [T] as *const [U]) })
} else {
Err(value)
}
}
}
impl<'a, T: 'static, U: 'static> TryCastSliceRef<'a, T, U>
for &&&(CastToken<&'a [T]>, CastToken<&'a [U]>)
{
}
pub trait TryCastMut<'a, T: 'static, U: 'static> {
#[inline(always)]
fn try_cast(&self, value: &'a mut T) -> Result<&'a mut U, &'a mut T> {
if type_eq::<T, U>() {
Ok(unsafe { &mut *(value as *mut T as *mut U) })
} else {
Err(value)
}
}
}
impl<'a, T: 'static, U: 'static> TryCastMut<'a, T, U>
for &&(CastToken<&'a mut T>, CastToken<&'a mut U>)
{
}
pub trait TryCastRef<'a, T: 'static, U: 'static> {
#[inline(always)]
fn try_cast(&self, value: &'a T) -> Result<&'a U, &'a T> {
if type_eq::<T, U>() {
Ok(unsafe { &*(value as *const T as *const U) })
} else {
Err(value)
}
}
}
impl<'a, T: 'static, U: 'static> TryCastRef<'a, T, U> for &(CastToken<&'a T>, CastToken<&'a U>) {}
pub trait TryCastOwned<T: 'static, U: 'static> {
#[inline(always)]
fn try_cast(&self, value: T) -> Result<U, T> {
if type_eq::<T, U>() {
Ok(unsafe { transmute_unchecked::<T, U>(value) })
} else {
Err(value)
}
}
}
impl<T: 'static, U: 'static> TryCastOwned<T, U> for (CastToken<T>, CastToken<U>) {}