aboutsummaryrefslogtreecommitdiff
path: root/src/private/cast
diff options
context:
space:
mode:
Diffstat (limited to 'src/private/cast')
-rw-r--r--src/private/cast/arc.rs93
-rw-r--r--src/private/cast/boxed.rs87
-rw-r--r--src/private/cast/error.rs20
-rw-r--r--src/private/cast/mod.rs273
-rw-r--r--src/private/cast/rc.rs87
5 files changed, 0 insertions, 560 deletions
diff --git a/src/private/cast/arc.rs b/src/private/cast/arc.rs
deleted file mode 100644
index 1fbdf8b..0000000
--- a/src/private/cast/arc.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-//! Originally from Intertrait by CodeChain
-//!
-//! <https://github.com/CodeChain-io/intertrait>
-//! <https://crates.io/crates/intertrait/0.2.2>
-//!
-//! Licensed under either of
-//!
-//! Apache License, Version 2.0 (LICENSE-APACHE or <http://www.apache.org/licenses/LICENSE-2.0>)
-//! MIT license (LICENSE-MIT or <http://opensource.org/licenses/MIT>)
-//!
-//! at your option.
-use std::any::type_name;
-use std::sync::Arc;
-
-use crate::private::cast::error::CastError;
-use crate::private::cast::{get_caster, CastFromArc};
-
-pub trait CastArc
-{
- /// Casts an `Arc` with `Self` into an `Arc` with `Dest`.
- fn cast<Dest: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<Dest>, CastError>;
-}
-
-/// A blanket implementation of `CastArc` for traits extending `CastFrom`, `Sync`, and
-/// `Send`.
-impl<CastFromSelf: ?Sized + CastFromArc> CastArc for CastFromSelf
-{
- fn cast<Dest: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<Dest>, CastError>
- {
- let caster =
- get_caster::<Dest>((*self).type_id()).map_err(CastError::GetCasterFailed)?;
-
- let cast_arc = caster
- .opt_cast_arc
- .ok_or(CastError::NotArcCastable(type_name::<Dest>()))?;
-
- cast_arc(self.arc_any()).map_err(|err| CastError::CastFailed {
- source: err,
- from: type_name::<Self>(),
- to: type_name::<Dest>(),
- })
- }
-}
-
-#[cfg(test)]
-mod tests
-{
- use std::any::Any;
- use std::fmt::{Debug, Display};
- use std::sync::Arc;
-
- use super::*;
- use crate::test_utils::subjects;
-
- #[test]
- fn can_cast_arc()
- {
- let concrete_ninja = Arc::new(subjects::Ninja);
-
- let abstract_ninja: Arc<dyn subjects::INinja> = concrete_ninja;
-
- let debug_ninja_result = abstract_ninja.cast::<dyn Debug>();
-
- assert!(debug_ninja_result.is_ok());
- }
-
- #[test]
- fn cannot_cast_arc_wrong()
- {
- let concrete_ninja = Arc::new(subjects::Ninja);
-
- let abstract_ninja: Arc<dyn subjects::INinja> = concrete_ninja;
-
- let display_ninja_result = abstract_ninja.cast::<dyn Display>();
-
- assert!(matches!(
- display_ninja_result,
- Err(CastError::GetCasterFailed(_))
- ));
- }
-
- #[test]
- fn can_cast_arc_from_any()
- {
- let concrete_ninja = Arc::new(subjects::Ninja);
-
- let any_ninja: Arc<dyn Any + Send + Sync> = concrete_ninja;
-
- let debug_ninja_result = any_ninja.cast::<dyn Debug>();
-
- assert!(debug_ninja_result.is_ok());
- }
-}
diff --git a/src/private/cast/boxed.rs b/src/private/cast/boxed.rs
deleted file mode 100644
index 074346c..0000000
--- a/src/private/cast/boxed.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-//! Originally from Intertrait by CodeChain
-//!
-//! <https://github.com/CodeChain-io/intertrait>
-//! <https://crates.io/crates/intertrait/0.2.2>
-//!
-//! Licensed under either of
-//!
-//! Apache License, Version 2.0 (LICENSE-APACHE or <http://www.apache.org/licenses/LICENSE-2.0>)
-//! MIT license (LICENSE-MIT or <http://opensource.org/licenses/MIT>)
-//!
-//! at your option.
-
-use std::any::type_name;
-
-use crate::private::cast::error::CastError;
-use crate::private::cast::{get_caster, CastFrom};
-
-pub trait CastBox
-{
- /// Casts a `Box` with `Self` into a `Box` with `Dest`.
- fn cast<Dest: ?Sized + 'static>(self: Box<Self>) -> Result<Box<Dest>, CastError>;
-}
-
-/// A blanket implementation of `CastBox` for traits extending `CastFrom`.
-impl<CastFromSelf: ?Sized + CastFrom> CastBox for CastFromSelf
-{
- fn cast<Dest: ?Sized + 'static>(self: Box<Self>) -> Result<Box<Dest>, CastError>
- {
- let caster =
- get_caster::<Dest>((*self).type_id()).map_err(CastError::GetCasterFailed)?;
-
- (caster.cast_box)(self.box_any()).map_err(|err| CastError::CastFailed {
- source: err,
- from: type_name::<Self>(),
- to: type_name::<Dest>(),
- })
- }
-}
-
-#[cfg(test)]
-mod tests
-{
- use std::any::Any;
- use std::fmt::{Debug, Display};
-
- use super::*;
- use crate::test_utils::subjects;
-
- #[test]
- fn can_cast_box()
- {
- let concrete_ninja = Box::new(subjects::Ninja);
-
- let abstract_ninja: Box<dyn subjects::INinja> = concrete_ninja;
-
- let debug_ninja_result = abstract_ninja.cast::<dyn Debug>();
-
- assert!(debug_ninja_result.is_ok());
- }
-
- #[test]
- fn cannot_cast_box_wrong()
- {
- let concrete_ninja = Box::new(subjects::Ninja);
-
- let abstract_ninja: Box<dyn subjects::INinja> = concrete_ninja;
-
- let display_ninja_result = abstract_ninja.cast::<dyn Display>();
-
- assert!(matches!(
- display_ninja_result,
- Err(CastError::GetCasterFailed(_))
- ));
- }
-
- #[test]
- fn can_cast_box_from_any()
- {
- let concrete_ninja = Box::new(subjects::Ninja);
-
- let any_ninja: Box<dyn Any> = concrete_ninja;
-
- let debug_ninja_result = any_ninja.cast::<dyn Debug>();
-
- assert!(debug_ninja_result.is_ok());
- }
-}
diff --git a/src/private/cast/error.rs b/src/private/cast/error.rs
deleted file mode 100644
index c6ed01d..0000000
--- a/src/private/cast/error.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use crate::private::cast::{CasterError, GetCasterError};
-
-#[derive(thiserror::Error, Debug)]
-pub enum CastError
-{
- #[error("Failed to get caster")]
- GetCasterFailed(#[from] GetCasterError),
-
- #[error("Failed to cast from {from} to {to}")]
- CastFailed
- {
- #[source]
- source: CasterError,
- from: &'static str,
- to: &'static str,
- },
-
- #[error("'{0}' can't be cast to an Arc")]
- NotArcCastable(&'static str),
-}
diff --git a/src/private/cast/mod.rs b/src/private/cast/mod.rs
deleted file mode 100644
index ddff2a4..0000000
--- a/src/private/cast/mod.rs
+++ /dev/null
@@ -1,273 +0,0 @@
-//! Originally from Intertrait by CodeChain
-//!
-//! <https://github.com/CodeChain-io/intertrait>
-//! <https://crates.io/crates/intertrait/0.2.2>
-//!
-//! Licensed under either of
-//!
-//! Apache License, Version 2.0 (LICENSE-APACHE or <http://www.apache.org/licenses/LICENSE-2.0>)
-//! MIT license (LICENSE-MIT or <http://opensource.org/licenses/MIT>)
-//!
-//! at your option.
-use std::any::{Any, TypeId};
-use std::rc::Rc;
-use std::sync::Arc;
-
-use ahash::AHashMap;
-use linkme::distributed_slice;
-use once_cell::sync::Lazy;
-
-pub mod arc;
-pub mod boxed;
-pub mod error;
-pub mod rc;
-
-pub type BoxedCaster = Box<dyn Any + Send + Sync>;
-
-/// A distributed slice gathering constructor functions for [`Caster`]s.
-///
-/// A constructor function returns `TypeId` of a concrete type involved in the casting
-/// and a `Box` of a type or trait backed by a [`Caster`].
-#[distributed_slice]
-pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..];
-
-/// A `HashMap` mapping `TypeId` of a [`Caster`] to an instance of it.
-static CASTER_MAP: Lazy<AHashMap<(TypeId, TypeId), BoxedCaster>> = Lazy::new(|| {
- CASTERS
- .iter()
- .map(|caster_fn| {
- let (type_id, caster) = caster_fn();
-
- ((type_id, (*caster).type_id()), caster)
- })
- .collect()
-});
-
-type CastBoxFn<Dest> = fn(from: Box<dyn Any>) -> Result<Box<Dest>, CasterError>;
-
-type CastRcFn<Dest> = fn(from: Rc<dyn Any>) -> Result<Rc<Dest>, CasterError>;
-
-type CastArcFn<Dest> =
- fn(from: Arc<dyn Any + Sync + Send + 'static>) -> Result<Arc<Dest>, CasterError>;
-
-/// A `Caster` knows how to cast a type or trait to the type or trait `Dest`. Each
-/// `Caster` instance is specific to a concrete type. That is, it knows how to cast to
-/// single specific type or trait implemented by single specific type.
-pub struct Caster<Dest: ?Sized + 'static>
-{
- /// Casts a `Box` holding a type or trait object for `Any` to another `Box` holding a
- /// type or trait `Dest`.
- pub cast_box: CastBoxFn<Dest>,
-
- /// Casts an `Rc` holding a type or trait for `Any` to another `Rc` holding a type or
- /// trait `Dest`.
- pub cast_rc: CastRcFn<Dest>,
-
- /// Casts an `Arc` holding a type or trait for `Any + Sync + Send + 'static` to
- /// another `Arc` holding a type or trait for `Dest`.
- pub opt_cast_arc: Option<CastArcFn<Dest>>,
-}
-
-impl<Dest: ?Sized + 'static> Caster<Dest>
-{
- pub fn new(cast_box: CastBoxFn<Dest>, cast_rc: CastRcFn<Dest>) -> Caster<Dest>
- {
- Caster::<Dest> {
- cast_box,
- cast_rc,
- opt_cast_arc: None,
- }
- }
-
- #[allow(clippy::similar_names)]
- pub fn new_sync(
- cast_box: CastBoxFn<Dest>,
- cast_rc: CastRcFn<Dest>,
- cast_arc: CastArcFn<Dest>,
- ) -> Caster<Dest>
- {
- Caster::<Dest> {
- cast_box,
- cast_rc,
- opt_cast_arc: Some(cast_arc),
- }
- }
-}
-
-#[derive(Debug, thiserror::Error)]
-pub enum CasterError
-{
- #[error("Failed to cast Box")]
- CastBoxFailed,
-
- #[error("Failed to cast Rc")]
- CastRcFailed,
-
- #[error("Failed to cast Arc")]
- CastArcFailed,
-}
-
-/// Returns a `Caster<Dest>` from a concrete type with the id `type_id` to a type or trait
-/// `Dest`.
-fn get_caster<Dest: ?Sized + 'static>(
- type_id: TypeId,
-) -> Result<&'static Caster<Dest>, GetCasterError>
-{
- let any_caster = CASTER_MAP
- .get(&(type_id, TypeId::of::<Caster<Dest>>()))
- .ok_or(GetCasterError::NotFound)?;
-
- any_caster
- .downcast_ref::<Caster<Dest>>()
- .ok_or(GetCasterError::DowncastFailed)
-}
-
-#[derive(Debug, thiserror::Error)]
-pub enum GetCasterError
-{
- #[error("Caster not found")]
- NotFound,
-
- #[error("Failed to downcast caster")]
- DowncastFailed,
-}
-
-/// `CastFrom` must be extended by a trait that wants to allow for casting into another
-/// trait.
-///
-/// It is used for obtaining a trait object for [`Any`] from a trait object for its
-/// sub-trait, and blanket implemented for all `Sized + Any + 'static` types.
-///
-/// # Examples
-/// ```ignore
-/// trait Source: CastFrom {
-/// ...
-/// }
-/// ```
-pub trait CastFrom: Any + 'static
-{
- /// Returns a `Box` of `Any`, which is backed by the type implementing this trait.
- fn box_any(self: Box<Self>) -> Box<dyn Any>;
-
- /// Returns an `Rc` of `Any`, which is backed by the type implementing this trait.
- fn rc_any(self: Rc<Self>) -> Rc<dyn Any>;
-}
-
-/// This trait must be extended by a trait that is `Any + Sync + Send + 'static`
-/// and wants to allow for casting into another trait behind references and smart pointers
-/// especially including `Arc`.
-///
-/// It is used for obtaining a trait object for [`Any + Sync + Send + 'static`] from an
-/// object for its sub-trait, and blanket implemented for all `Sized + Sync + Send +
-/// 'static` types.
-///
-/// # Examples
-/// ```ignore
-/// trait Source: CastFromArc {
-/// ...
-/// }
-/// ```
-pub trait CastFromArc: CastFrom + Sync + Send + 'static
-{
- fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>;
-}
-
-impl<Source: Sized + Any + 'static> CastFrom for Source
-{
- fn box_any(self: Box<Self>) -> Box<dyn Any>
- {
- self
- }
-
- fn rc_any(self: Rc<Self>) -> Rc<dyn Any>
- {
- self
- }
-}
-
-impl CastFrom for dyn Any + 'static
-{
- fn box_any(self: Box<Self>) -> Box<dyn Any>
- {
- self
- }
-
- fn rc_any(self: Rc<Self>) -> Rc<dyn Any>
- {
- self
- }
-}
-
-impl<Source: Sized + Sync + Send + 'static> CastFromArc for Source
-{
- fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>
- {
- self
- }
-}
-
-impl CastFrom for dyn Any + Sync + Send + 'static
-{
- fn box_any(self: Box<Self>) -> Box<dyn Any>
- {
- self
- }
-
- fn rc_any(self: Rc<Self>) -> Rc<dyn Any>
- {
- self
- }
-}
-
-impl CastFromArc for dyn Any + Sync + Send + 'static
-{
- fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>
- {
- self
- }
-}
-
-#[cfg(test)]
-mod tests
-{
- use std::any::TypeId;
- use std::fmt::Debug;
-
- use linkme::distributed_slice;
-
- use super::*;
- use crate::test_utils::subjects;
-
- #[distributed_slice(super::CASTERS)]
- static TEST_CASTER: fn() -> (TypeId, BoxedCaster) = create_test_caster;
-
- fn create_test_caster() -> (TypeId, BoxedCaster)
- {
- let type_id = TypeId::of::<subjects::Ninja>();
-
- let caster = Box::new(Caster::<dyn Debug> {
- cast_box: |from| {
- let concrete = from
- .downcast::<subjects::Ninja>()
- .map_err(|_| CasterError::CastBoxFailed)?;
-
- Ok(concrete as Box<dyn Debug>)
- },
- cast_rc: |from| {
- let concrete = from
- .downcast::<subjects::Ninja>()
- .map_err(|_| CasterError::CastRcFailed)?;
-
- Ok(concrete as Rc<dyn Debug>)
- },
- opt_cast_arc: Some(|from| {
- let concrete = from
- .downcast::<subjects::Ninja>()
- .map_err(|_| CasterError::CastArcFailed)?;
-
- Ok(concrete as Arc<dyn Debug>)
- }),
- });
- (type_id, caster)
- }
-}
diff --git a/src/private/cast/rc.rs b/src/private/cast/rc.rs
deleted file mode 100644
index 11d137a..0000000
--- a/src/private/cast/rc.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-//! Originally from Intertrait by CodeChain
-//!
-//! <https://github.com/CodeChain-io/intertrait>
-//! <https://crates.io/crates/intertrait/0.2.2>
-//!
-//! Licensed under either of
-//!
-//! Apache License, Version 2.0 (LICENSE-APACHE or <http://www.apache.org/licenses/LICENSE-2.0>)
-//! MIT license (LICENSE-MIT or <http://opensource.org/licenses/MIT>)
-//!
-//! at your option.
-use std::any::type_name;
-use std::rc::Rc;
-
-use crate::private::cast::error::CastError;
-use crate::private::cast::{get_caster, CastFrom};
-
-pub trait CastRc
-{
- /// Casts an `Rc` with `Self `into a `Rc` with `Dest`.
- fn cast<Dest: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<Dest>, CastError>;
-}
-
-/// A blanket implementation of `CastRc` for traits extending `CastFrom`.
-impl<CastFromSelf: ?Sized + CastFrom> CastRc for CastFromSelf
-{
- fn cast<Dest: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<Dest>, CastError>
- {
- let caster =
- get_caster::<Dest>((*self).type_id()).map_err(CastError::GetCasterFailed)?;
-
- (caster.cast_rc)(self.rc_any()).map_err(|err| CastError::CastFailed {
- source: err,
- from: type_name::<Self>(),
- to: type_name::<Dest>(),
- })
- }
-}
-
-#[cfg(test)]
-mod tests
-{
- use std::any::Any;
- use std::fmt::{Debug, Display};
-
- use super::*;
- use crate::test_utils::subjects;
-
- #[test]
- fn can_cast_rc()
- {
- let concrete_ninja = Rc::new(subjects::Ninja);
-
- let abstract_ninja: Rc<dyn subjects::INinja> = concrete_ninja;
-
- let debug_ninja_result = abstract_ninja.cast::<dyn Debug>();
-
- assert!(debug_ninja_result.is_ok());
- }
-
- #[test]
- fn cannot_cast_rc_wrong()
- {
- let concrete_ninja = Rc::new(subjects::Ninja);
-
- let abstract_ninja: Rc<dyn subjects::INinja> = concrete_ninja;
-
- let display_ninja_result = abstract_ninja.cast::<dyn Display>();
-
- assert!(matches!(
- display_ninja_result,
- Err(CastError::GetCasterFailed(_))
- ));
- }
-
- #[test]
- fn can_cast_rc_from_any()
- {
- let concrete_ninja = Rc::new(subjects::Ninja);
-
- let any_ninja: Rc<dyn Any> = concrete_ninja;
-
- let debug_ninja_result = any_ninja.cast::<dyn Debug>();
-
- assert!(debug_ninja_result.is_ok());
- }
-}