//! Originally from Intertrait by CodeChain //! //! //! //! //! Licensed under either of //! //! Apache License, Version 2.0 (LICENSE-APACHE or ) //! MIT license (LICENSE-MIT or ) //! //! at your option. use std::any::type_name; use crate::libs::intertrait::cast::error::CastError; use crate::libs::intertrait::{get_caster, CastFrom}; pub trait CastBox { /// Casts a box to this trait into that of type `OtherTrait`. fn cast( self: Box, ) -> Result, CastError>; } /// A blanket implementation of `CastBox` for traits extending `CastFrom`. impl CastBox for CastFromSelf { fn cast( self: Box, ) -> Result, CastError> { let caster = get_caster::((*self).type_id()) .map_err(CastError::GetCasterFailed)?; (caster.cast_box)(self.box_any()).map_err(|err| CastError::CastFailed { source: err, from: type_name::(), to: type_name::(), }) } } #[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 = concrete_ninja; let debug_ninja_result = abstract_ninja.cast::(); assert!(debug_ninja_result.is_ok()); } #[test] fn cannot_cast_box_wrong() { let concrete_ninja = Box::new(subjects::Ninja); let abstract_ninja: Box = concrete_ninja; let display_ninja_result = abstract_ninja.cast::(); 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 = concrete_ninja; let debug_ninja_result = any_ninja.cast::(); assert!(debug_ninja_result.is_ok()); } }