1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
use std::any::TypeId; use crate::{caster, CastFrom, Caster, CASTER_MAP}; /// A trait that is blanket-implemented for traits extending `CastFrom` to allow for casting /// of a trait object for it behind an immutable reference to a trait object for another trait /// implemented by the underlying value. /// /// # Examples /// ## Casting an immutable reference /// ``` /// # use intertrait::*; /// use intertrait::cast::*; /// /// # #[cast_to(Greet)] /// # struct Data; /// # trait Source: CastFrom {} /// # trait Greet { /// # fn greet(&self); /// # } /// # impl Greet for Data { /// # fn greet(&self) { /// # println!("Hello"); /// # } /// # } /// impl Source for Data {} /// let data = Data; /// let source: &dyn Source = &data; /// let greet = source.cast::<dyn Greet>(); /// greet.unwrap().greet(); /// ``` /// /// ## Testing if a cast is possible /// ``` /// # use intertrait::*; /// use intertrait::cast::*; /// /// # #[cast_to(Greet)] /// # struct Data; /// # trait Source: CastFrom {} /// # trait Greet { /// # fn greet(&self); /// # } /// # impl Greet for Data { /// # fn greet(&self) { /// # println!("Hello"); /// # } /// # } /// impl Source for Data {} /// let data = Data; /// let source: &dyn Source = &data; /// assert!(source.impls::<dyn Greet>()); /// assert!(!source.impls::<dyn std::fmt::Debug>()); /// ``` pub trait CastRef { /// Casts a reference to this trait into that of type `T`. fn cast<T: ?Sized + 'static>(&self) -> Option<&T>; /// Tests if this trait object can be cast into `T`. fn impls<T: ?Sized + 'static>(&self) -> bool; } /// A blanket implementation of `CastRef` for traits extending `CastFrom`. impl<S: ?Sized + CastFrom> CastRef for S { fn cast<T: ?Sized + 'static>(&self) -> Option<&T> { let any = self.ref_any(); let caster = caster::<T>(any.type_id())?; (caster.cast_ref)(any).into() } fn impls<T: ?Sized + 'static>(&self) -> bool { CASTER_MAP.contains_key(&(self.type_id(), TypeId::of::<Caster<T>>())) } }