xref: /DragonOS/kernel/crates/intertrait/src/cast/cast_ref.rs (revision 86ee1395de7c614865236ee15071c3603b794e44)
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