#! [cfg_attr(not(feature = "std" ), no_std)]
#[ cfg(not(feature = "std" ))]
mod std {
pub use core::*;
}
use std::any::{Any as StdAny, TypeId, type_name};
use std::fmt::{self , Debug, Display};
#[ cfg(feature = "std" )]
use std::{error::Error, rc::Rc, sync::Arc};
// ++++++++++++++++++++ Any ++++++++++++++++++++
pub trait Any: StdAny {
#[ doc(hidden)]
fn as_any(&self ) -> &dyn StdAny;
#[ doc(hidden)]
fn as_any_mut(&mut self ) -> &mut dyn StdAny;
#[ doc(hidden)]
#[ cfg(feature = "std" )]
fn into_any(self : Box <Self >) -> Box <dyn StdAny>;
#[ doc(hidden)]
#[ cfg(feature = "std" )]
fn into_any_rc(self : Rc<Self >) -> Rc<dyn StdAny>;
fn type_name(&self ) -> &'static str;
}
impl <T> Any for T where T: StdAny {
#[ doc(hidden)]
fn as_any(&self ) -> &dyn StdAny { self }
#[ doc(hidden)]
fn as_any_mut(&mut self ) -> &mut dyn StdAny { self }
#[ cfg(feature = "std" )]
fn into_any(self : Box <Self >) -> Box <dyn StdAny> { self }
#[ cfg(feature = "std" )]
fn into_any_rc(self : Rc<Self >) -> Rc<dyn StdAny> { self }
fn type_name(&self ) -> &'static str { type_name::<Self>() }
}
#[ cfg(feature = "std" )]
pub trait AnySync: Any + Send + Sync {
fn into_any_arc(self : Arc<Self >) -> Arc<dyn StdAny + Send + Sync>;
}
#[ cfg(feature = "std" )]
impl <T> AnySync for T where T: Any + Send + Sync {
fn into_any_arc(self : Arc<Self >) -> Arc<dyn StdAny + Send + Sync> { self }
}
// ++++++++++++++++++++ TypeMismatch ++++++++++++++++++++
#[ derive(Debug, Clone, Copy)]
pub struct TypeMismatch {
pub expected: &'static str,
pub found: &'static str,
}
impl TypeMismatch {
pub fn new<T, O>(found_obj: &O) -> Self
where T: Any + ?Sized, O: Any + ?Sized
{
TypeMismatch {
expected: type_name::<T>(),
found: found_obj.type_name(),
}
}
}
impl Display for TypeMismatch {
fn fmt(&self , fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "Type mismatch: Expected '{}', found '{}'!" , self .expected, self .found)
}
}
#[ cfg(feature = "std" )]
impl Error for TypeMismatch {}
// ++++++++++++++++++++ DowncastError ++++++++++++++++++++
pub struct DowncastError<O> {
mismatch: TypeMismatch,
object: O,
}
impl <O> DowncastError<O> {
pub fn new(mismatch: TypeMismatch, object: O) -> Self {
Self { mismatch, object }
}
pub fn type_mismatch(&self ) -> TypeMismatch { self .mismatch }
pub fn into_object(self ) -> O { self .object }
}
impl <O> Debug for DowncastError<O> {
fn fmt(&self , fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("DowncastError" )
.field("mismatch" , &self .mismatch)
.finish()
}
}
impl <O> Display for DowncastError<O> {
fn fmt(&self , fmt: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self .mismatch, fmt)
}
}
#[ cfg(feature = "std" )]
impl <O> Error for DowncastError<O> {}
// ++++++++++++++++++++ Downcast ++++++++++++++++++++
pub trait Downcast<T>: Any
where T: Any
{
fn is_type(&self ) -> bool { self .type_id() == TypeId::of::<T>() }
fn downcast_ref(&self ) -> Result<&T, TypeMismatch> {
if self .is_type() {
Ok(self .as_any().downcast_ref().unwrap())
} else {
Err(TypeMismatch::new::<T, Self >(self ))
}
}
fn downcast_mut(&mut self ) -> Result<&mut T, TypeMismatch> {
if self .is_type() {
Ok(self .as_any_mut().downcast_mut().unwrap())
} else {
Err(TypeMismatch::new::<T, Self >(self ))
}
}
#[ cfg(feature = "std" )]
fn downcast(self : Box <Self >) -> Result<Box <T>, DowncastError<Box <Self >>> {
if self .is_type() {
Ok(self .into_any().downcast().unwrap())
} else {
let mismatch = TypeMismatch::new::<T, Self >(&*self );
Err(DowncastError::new(mismatch, self ))
}
}
#[ cfg(feature = "std" )]
fn downcast_rc(self : Rc<Self >) -> Result<Rc<T>, DowncastError<Rc<Self >>> {
if self .is_type() {
Ok(self .into_any_rc().downcast().unwrap())
} else {
let mismatch = TypeMismatch::new::<T, Self >(&*self );
Err(DowncastError::new(mismatch, self ))
}
}
}
#[ cfg(feature = "std" )]
pub trait DowncastSync<T>: Downcast<T> + AnySync
where T: AnySync
{
fn downcast_arc(self : Arc<Self >) -> Result<Arc<T>, DowncastError<Arc<Self >>> {
if self .is_type() {
Ok(self .into_any_arc().downcast().unwrap())
} else {
let mismatch = TypeMismatch::new::<T, Self >(&*self );
Err(DowncastError::new(mismatch, self ))
}
}
}
// ++++++++++++++++++++ macros ++++++++++++++++++++
#[ doc(hidden)]
pub mod _std {
#[ cfg(feature = "std" )]
pub use std::*;
#[ cfg(not(feature = "std" ))]
pub use core::*;
}
/// Implements [`Downcast`](trait.Downcast.html) for your trait-object-type.
///
/// ```ignore
/// impl_downcast!(Foo);
/// impl_downcast!(<B> Foo<B> where B: Bar);
/// impl_downcast!(<B> Foo<Bar = B>);
/// ```
///
/// expands to
///
/// ```ignore
/// impl<T> Downcast<T> for Foo
/// where T: Any
/// {}
///
/// impl<T, B> Downcast<T> for Foo<B>
/// where T: Any, B: Bar
/// {}
///
/// impl<T, B> Downcast<T> for Foo<Bar = B>
/// where T: Any
/// {}
/// ```
#[ macro_export]
macro_rules! impl_downcast {
(<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
impl <_T, $($params),+> $crate ::Downcast<_T> for $base
where _T: $crate ::Any, $($params: 'static,)* $($($bounds)+)*
{}
};
($base:ty) => {
impl <_T> $crate ::Downcast<_T> for $base
where _T: $crate ::Any
{}
};
}
/// Implements [`Downcast`](trait.Downcast.html) and [`DowncastSync`](trait.DowncastSync.html) for your trait-object-type.
#[ cfg(feature = "std" )]
#[ macro_export]
macro_rules! impl_downcast_sync {
(<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
impl <_T, $($params),+> $crate ::Downcast<_T> for $base
where _T: $crate ::Any, $($params: 'static,)* $($($bounds)+)*
{}
impl <_T, $($params),+> $crate ::DowncastSync<_T> for $base
where _T: $crate ::AnySync, $($params: 'static,)* $($($bounds)+)*
{}
};
($base:ty) => {
impl <_T> $crate ::Downcast<_T> for $base
where _T: $crate ::Any
{}
impl <_T> $crate ::DowncastSync<_T> for $base
where _T: $crate ::AnySync
{}
};
}
#[ doc(hidden)]
#[ macro_export]
macro_rules! downcast_methods_core {
(@items) => {
#[ allow(unused, missing_docs)]
pub fn is<_T>(&self ) -> bool
where _T: $crate ::Any, Self : $crate ::Downcast<_T>
{
$crate ::Downcast::<_T>::is_type(self )
}
#[ allow(unused, missing_docs)]
pub fn downcast_ref<_T>(&self ) -> $crate ::_std::result::Result<&_T, $crate ::TypeMismatch>
where _T: $crate ::Any, Self : $crate ::Downcast<_T>
{
$crate ::Downcast::<_T>::downcast_ref(self )
}
#[ allow(unused, missing_docs)]
pub fn downcast_mut<_T>(&mut self ) -> $crate ::_std::result::Result<&<span style='color:red'>mut _T, $crate ::TypeMismatch>
where _T: $crate ::Any, Self : $crate ::Downcast<_T>
{
$crate ::Downcast::<_T>::downcast_mut(self )
}
};
(<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
impl <$($params),+> $base
where $($params: 'static,)* $($($bounds)+)*
{
$crate ::downcast_methods_core!(@items);
}
};
($base:ty) => {
impl $base {
$crate ::downcast_methods_core!(@items);
}
};
}
#[ doc(hidden)]
#[ macro_export]
macro_rules! downcast_methods_std {
(@items) => {
$crate ::downcast_methods_core!(@items);
#[ allow(unused, missing_docs)]
pub fn downcast<_T>(self : $crate ::_std::boxed::Box <Self >) -> $crate ::_std::result::Result<$crate ::_std::boxed::Box <_T>, $crate ::DowncastError<$crate ::_std::boxed::Box <Self >>>
where _T: $crate ::Any, Self : $crate ::Downcast<_T>
{
$crate ::Downcast::<_T>::downcast(self )
}
#[ allow(unused, missing_docs)]
pub fn downcast_rc<_T>(self : $crate ::_std::rc::Rc<Self >) -> $crate ::_std::result::Result<$crate ::_std::rc::Rc<_T>, $crate ::DowncastError<$crate ::_std::rc::Rc<Self >>>
where _T: $crate ::Any, Self : $crate ::Downcast<_T>
{
$crate ::Downcast::<_T>::downcast_rc(self )
}
};
(<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
impl <$($params),+> $base
$(where $($bounds)+)*
{
$crate ::downcast_methods_std!(@items);
}
};
($base:ty) => {
impl $base {
$crate ::downcast_methods_std!(@items);
}
};
}
#[ doc(hidden)]
#[ cfg(feature = "std" )]
#[ macro_export]
macro_rules! downcast_sync_methods {
(@items) => {
$crate ::downcast_methods_std!(@items);
#[ allow(unused, missing_docs)]
pub fn downcast_arc<_T>(self : $crate ::_std::sync::Arc<Self >) -> $crate ::_std::result::Result<$crate ::_std::sync::Arc<_T>, $crate ::DowncastError<$crate ::_std::sync::Arc<Self >>>
where _T: $crate ::AnySync, Self : $crate ::DowncastSync<_T>
{
$crate ::DowncastSync::<_T>::downcast_arc(self )
}
};
(<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
impl <$($params),+> $base
$(where $($bounds)+)*
{
$crate ::downcast_sync_methods!(@items);
}
};
($base:ty) => {
impl $base {
$crate ::downcast_sync_methods!(@items);
}
};
}
/// Generate `downcast`-methods for your trait-object-type.
///
/// ```ignore
/// downcast_methods!(Foo);
/// downcast_methods!(<B> Foo<B> where B: Bar);
/// downcast_methods!(<B> Foo<Bar = B>);
/// ```
///
/// ```ignore
/// impl dyn Foo {
/// /* impl<B> dyn Foo<B> where B: Bar { */
/// /* impl<B> dyn Foo<Bar = B> { */
///
/// pub fn is<T>(&self) -> bool
/// where T: Any, Self: Downcast<T>
/// { ... }
///
/// pub fn downcast_ref<T>(&self) -> Result<&T, TypeMismatch>
/// where T: Any, Self: Downcast<T>
/// { ... }
///
/// pub fn downcast_mut<T>(&mut self) -> Result<&mut T, TypeMismatch>
/// where T: Any, Self: Downcast<T>
/// { ... }
/// }
/// ```
#[ cfg(not(feature = "std" ))]
#[ macro_export]
macro_rules! downcast_methods {
($($tt:tt)+) => { $crate ::downcast_methods_core!($($tt)+); }
}
/// Generate `downcast`-methods for your trait-object-type.
///
/// ```ignore
/// downcast_methods!(Foo);
/// downcast_methods!(<B> Foo<B> where B: Bar);
/// downcast_methods!(<B> Foo<Bar = B>);
/// ```
///
/// ```ignore
/// impl dyn Foo {
/// /* impl<B> dyn Foo<B> where B: Bar { */
/// /* impl<B> dyn Foo<Bar = B> { */
///
/// pub fn is<T>(&self) -> bool
/// where T: Any, Self: Downcast<T>
/// { ... }
///
/// pub fn downcast_ref<T>(&self) -> Result<&T, TypeMismatch>
/// where T: Any, Self: Downcast<T>
/// { ... }
///
/// pub fn downcast_mut<T>(&mut self) -> Result<&mut T, TypeMismatch>
/// where T: Any, Self: Downcast<T>
/// { ... }
///
/// pub fn downcast<T>(self: Box<Self>) -> Result<Box<T>, DowncastError<Box<T>>>
/// where T: Any, Self: Downcast<T>
/// { ... }
/// }
/// ```
#[ cfg(feature = "std" )]
#[ macro_export]
macro_rules! downcast_methods {
($($tt:tt)+) => { $crate ::downcast_methods_std!($($tt)+); }
}
/// Implements [`Downcast`](trait.Downcast.html) and generates
/// `downcast`-methods for your trait-object-type.
///
/// See [`impl_downcast`](macro.impl_downcast.html),
/// [`downcast_methods`](macro.downcast_methods.html).
#[ macro_export]
macro_rules! downcast {
($($tt:tt)+) => {
$crate ::impl_downcast!($($tt)+);
$crate ::downcast_methods!($($tt)+);
}
}
/// Implements [`DowncastSync`](trait.DowncastSync.html) and generates
/// `downcast`-methods for your trait-object-type.
///
/// See [`impl_downcast_sync`](macro.impl_downcast.html),
/// [`downcast_sync_methods`](macro.downcast_methods.html).
#[ cfg(feature = "std" )]
#[ macro_export]
macro_rules! downcast_sync {
($($tt:tt)+) => {
$crate ::impl_downcast_sync!($($tt)+);
$crate ::downcast_sync_methods!($($tt)+);
}
}
// NOTE: We only implement the trait, because implementing the methods won't
// be possible when we replace downcast::Any by std::any::Any.
downcast!(dyn Any);
downcast!((dyn Any + Send));
downcast!((dyn Any + Sync));
#[ cfg(feature = "std" )]
downcast_sync!(dyn AnySync);
Messung V0.5 in Prozent C=67 H=96 G=82
¤ Dauer der Verarbeitung: 0.7 Sekunden
¤
*© Formatika GbR, Deutschland