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