#![cfg_attr(not(any(feature = "std", doc)), no_std)]
#![cfg_attr(any(feature = "global", doc), feature(once_cell))]
#![feature(doc_cfg, generic_associated_types, ptr_metadata, unsize)]
#![deny(missing_docs)]
#[cfg(any(feature = "alloc", doc))]
extern crate alloc;
pub mod container;
pub mod db;
#[doc(hidden)]
#[cfg(feature = "trace")]
pub use tracing;
use container::{Coerced, Coercible, InnermostTypeId, Metadata, Pointer};
use core::ptr;
use db::{
error::{CastError, DatabaseEntryError},
TypeDatabaseEntryExt, TypeDatabaseExt,
};
#[cfg(any(feature = "global", doc))]
use db::hash_map::DB;
#[cfg(feature = "trace")]
use core::any::type_name;
pub trait DynImplements<'a, DB>
where
Self: InnermostTypeId,
DB: TypeDatabaseExt,
{
#[cfg_attr(feature = "trace", tracing::instrument(skip_all, fields(
Self = type_name::<Self>(),
U = type_name::<U>(),
)))]
fn dyn_implements<U>(&'a self, db: &DB) -> Result<bool, DatabaseEntryError<U, &Self>>
where
U: 'static + ?Sized,
{
db.get_db_entry::<U>()?.implements(&self)
}
}
pub trait DynCast<'a, DB>
where
Self: Pointer + InnermostTypeId,
Self::Inner: Coercible,
DB: TypeDatabaseExt,
{
#[cfg_attr(feature = "trace", tracing::instrument(skip_all, fields(
Self = type_name::<Self>(),
U = type_name::<U>(),
)))]
fn dyn_cast<U>(self, db: &DB) -> Result<Self::Coerced<U>, CastError<U, Self>>
where
U: 'static + ?Sized,
Self::Coerced<U>: Sized,
Coerced<Self::Inner, U>: ptr::Pointee<Metadata = Metadata<U>>,
{
match db.get_db_entry() {
Ok(entry) => entry.cast(self),
Err(source) => Err(CastError {
source: source.into(),
pointer: self,
}),
}
}
}
impl<'a, DB, P: ?Sized> DynImplements<'a, DB> for P
where
Self: InnermostTypeId,
DB: TypeDatabaseExt,
{
}
impl<'a, DB, P> DynCast<'a, DB> for P
where
Self: Pointer + InnermostTypeId,
Self::Inner: Coercible,
DB: TypeDatabaseExt,
{
}
#[cfg(any(feature = "global", doc))]
#[doc(cfg(feature = "global"))]
pub trait GlobalDynImplements<'a>
where
Self: InnermostTypeId,
{
#[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
fn dyn_implements<U>(&'a self) -> Result<bool, DatabaseEntryError<U, &Self>>
where
U: 'static + ?Sized,
{
DynImplements::dyn_implements::<U>(self, DB.get().expect("initialized database"))
}
}
#[cfg(any(feature = "global", doc))]
#[doc(cfg(feature = "global"))]
pub trait GlobalDynCast<'a>
where
Self: Pointer + InnermostTypeId,
Self::Inner: Coercible,
{
#[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
fn dyn_cast<U>(self) -> Result<Self::Coerced<U>, CastError<U, Self>>
where
U: 'static + ?Sized,
Self::Coerced<U>: Sized,
Coerced<Self::Inner, U>: ptr::Pointee<Metadata = Metadata<U>>,
{
DynCast::dyn_cast::<U>(self, DB.get().expect("initialized database"))
}
}
#[cfg(any(feature = "global", doc))]
#[doc(cfg(feature = "global"))]
impl<'a, P> GlobalDynImplements<'a> for P where Self: InnermostTypeId {}
#[cfg(any(feature = "global", doc))]
#[doc(cfg(feature = "global"))]
impl<'a, P> GlobalDynCast<'a> for P
where
Self: Pointer + InnermostTypeId,
Self::Inner: Coercible,
{
}