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