use alloc::{boxed::Box, rc::Rc};
use core::{any::Any, marker::Unsize};
pub trait AsAny: Any + Unsize<dyn Any> + 'static {
fn type_name(&self) -> &'static str;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn into_any(self: Box<Self>) -> Box<dyn Any>;
fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any>;
}
impl<T: Any + 'static> AsAny for T {
#[inline(always)]
default fn type_name(&self) -> &'static str {
core::any::type_name::<T>()
}
#[inline(always)]
default fn as_any(&self) -> &dyn Any {
self
}
#[inline(always)]
default fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline(always)]
default fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
#[inline(always)]
default fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> {
self
}
}
pub unsafe trait Is<Trait: ?Sized>: Unsize<Trait> {}
unsafe impl<Trait: ?Sized, T> Is<Trait> for T where T: ?Sized + Unsize<Trait> {}
pub trait IsObjOf<T: ?Sized> {}
impl<T, Trait> IsObjOf<T> for Trait
where
T: ?Sized + Is<Trait>,
Trait: ?Sized,
{
}
#[allow(unused)]
pub trait DowncastRef<To: ?Sized>: IsObjOf<To> {
fn downcast_ref(&self) -> Option<&To>;
fn downcast_mut(&mut self) -> Option<&mut To>;
}
impl<From, To> DowncastRef<To> for From
where
From: ?Sized,
To: ?Sized + DowncastFromRef<From>,
{
#[inline(always)]
fn downcast_ref(&self) -> Option<&To> {
To::downcast_from_ref(self)
}
#[inline(always)]
fn downcast_mut(&mut self) -> Option<&mut To> {
To::downcast_from_mut(self)
}
}
pub trait DowncastFromRef<From: ?Sized>: Is<From> {
fn downcast_from_ref(from: &From) -> Option<&Self>;
fn downcast_from_mut(from: &mut From) -> Option<&mut Self>;
}
impl<From, To> DowncastFromRef<From> for To
where
From: ?Sized + AsAny,
To: Is<From> + 'static,
{
#[inline]
fn downcast_from_ref(from: &From) -> Option<&Self> {
from.as_any().downcast_ref()
}
#[inline]
fn downcast_from_mut(from: &mut From) -> Option<&mut Self> {
from.as_any_mut().downcast_mut()
}
}
#[allow(unused)]
pub trait Downcast<To: ?Sized, Obj: ?Sized>: DowncastRef<To> + Is<Obj> {
fn downcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>>;
}
impl<From, To, Obj> Downcast<To, Obj> for From
where
From: ?Sized + DowncastRef<To> + Is<Obj>,
To: ?Sized + DowncastFrom<Self, Obj>,
Obj: ?Sized,
{
#[inline]
fn downcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>> {
To::downcast_from(self)
}
}
pub trait DowncastFrom<From, Obj>: DowncastFromRef<From>
where
From: ?Sized + Is<Obj>,
Obj: ?Sized,
{
#[allow(dead_code)]
fn downcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>>;
}
impl<From, To, Obj> DowncastFrom<From, Obj> for To
where
From: ?Sized + Is<Obj> + AsAny + 'static,
To: DowncastFromRef<From> + 'static,
Obj: ?Sized,
{
fn downcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>> {
if !from.as_any().is::<To>() {
Ok(from.into_any().downcast().unwrap())
} else {
Err(from)
}
}
}
pub trait Upcast<To: ?Sized>: TryUpcastRef<To> {
#[allow(dead_code)]
fn upcast_ref(&self) -> &To;
#[allow(dead_code)]
fn upcast_mut(&mut self) -> &mut To;
#[allow(dead_code)]
fn upcast(self: Box<Self>) -> Box<To>;
}
impl<From, To> Upcast<To> for From
where
From: ?Sized + Is<To>,
To: ?Sized,
{
#[inline(always)]
fn upcast_ref(&self) -> &To {
self
}
#[inline(always)]
fn upcast_mut(&mut self) -> &mut To {
self
}
#[inline(always)]
fn upcast(self: Box<Self>) -> Box<To> {
self
}
}
pub trait TryUpcastRef<To>: Is<To>
where
To: ?Sized,
{
#[allow(unused)]
fn is_of(&self) -> bool;
#[allow(dead_code)]
fn try_upcast_ref(&self) -> Option<&To>;
#[allow(dead_code)]
fn try_upcast_mut(&mut self) -> Option<&mut To>;
}
impl<From, To> TryUpcastRef<To> for From
where
From: Upcast<To> + ?Sized,
To: ?Sized,
{
#[inline(always)]
fn is_of(&self) -> bool {
true
}
#[inline(always)]
fn try_upcast_ref(&self) -> Option<&To> {
Some(self.upcast_ref())
}
#[inline(always)]
fn try_upcast_mut(&mut self) -> Option<&mut To> {
Some(self.upcast_mut())
}
}
pub trait TryUpcast<To, Obj>: Is<Obj> + TryUpcastRef<To>
where
To: ?Sized,
Obj: ?Sized,
{
#[allow(dead_code)]
#[inline(always)]
fn try_upcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>> {
Err(self)
}
}
impl<From, To, Obj> TryUpcast<To, Obj> for From
where
From: Is<Obj> + Upcast<To> + ?Sized,
To: ?Sized,
Obj: ?Sized,
{
#[inline]
fn try_upcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>> {
Ok(self.upcast())
}
}
#[allow(unused)]
pub trait UpcastFrom<From>
where
From: ?Sized,
{
fn upcast_from_ref(from: &From) -> &Self;
fn upcast_from_mut(from: &mut From) -> &mut Self;
fn upcast_from(from: Box<From>) -> Box<Self>;
}
impl<From, To> UpcastFrom<From> for To
where
From: Upcast<To> + ?Sized,
To: ?Sized,
{
#[inline]
fn upcast_from_ref(from: &From) -> &Self {
from.upcast_ref()
}
#[inline]
fn upcast_from_mut(from: &mut From) -> &mut Self {
from.upcast_mut()
}
#[inline]
fn upcast_from(from: Box<From>) -> Box<Self> {
from.upcast()
}
}
#[allow(unused)]
pub trait TryUpcastFromRef<From>: IsObjOf<From>
where
From: ?Sized,
{
fn try_upcast_from_ref(from: &From) -> Option<&Self>;
fn try_upcast_from_mut(from: &mut From) -> Option<&mut Self>;
}
impl<From, To> TryUpcastFromRef<From> for To
where
From: TryUpcastRef<To> + ?Sized,
To: ?Sized,
{
#[inline]
fn try_upcast_from_ref(from: &From) -> Option<&Self> {
from.try_upcast_ref()
}
#[inline]
fn try_upcast_from_mut(from: &mut From) -> Option<&mut Self> {
from.try_upcast_mut()
}
}
#[allow(unused)]
pub trait TryUpcastFrom<From, Obj>: TryUpcastFromRef<From>
where
From: Is<Obj> + ?Sized,
Obj: ?Sized,
{
fn try_upcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>>;
}
impl<From, To, Obj> TryUpcastFrom<From, Obj> for To
where
From: TryUpcast<Self, Obj> + ?Sized,
To: ?Sized,
Obj: ?Sized,
{
#[inline]
fn try_upcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>> {
from.try_upcast()
}
}