xref: /DragonOS/kernel/crates/intertrait/src/cast/cast_rc.rs (revision 28fe4ad2a0b0d8b5abf1f0cb402b1c3204b42242)
1 use crate::{caster, CastFrom};
2 use alloc::rc::Rc;
3 
4 /// A trait that is blanket-implemented for traits extending `CastFrom` to allow for casting
5 /// of a trait object for it behind an `Rc` to a trait object for another trait
6 /// implemented by the underlying value.
7 ///
8 /// # Examples
9 /// ```
10 /// # use std::rc::Rc;
11 /// # use intertrait::*;
12 /// use intertrait::cast::*;
13 ///
14 /// # #[cast_to(Greet)]
15 /// # struct Data;
16 /// # trait Source: CastFrom {}
17 /// # trait Greet {
18 /// #     fn greet(&self);
19 /// # }
20 /// # impl Greet for Data {
21 /// #    fn greet(&self) {
22 /// #        println!("Hello");
23 /// #    }
24 /// # }
25 /// impl Source for Data {}
26 /// let data = Data;
27 /// let source = Rc::new(data);
28 /// let greet = source.cast::<dyn Greet>();
29 /// greet.unwrap_or_else(|_| panic!("must not happen")).greet();
30 /// ```
31 pub trait CastRc {
32     /// Casts an `Rc` for this trait into that for type `T`.
33     fn cast<T: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>>;
34 }
35 
36 /// A blanket implementation of `CastRc` for traits extending `CastFrom`.
37 impl<S: ?Sized + CastFrom> CastRc for S {
38     fn cast<T: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>> {
39         match caster::<T>((*self).type_id()) {
40             Some(caster) => Ok((caster.cast_rc)(self.rc_any())),
41             None => Err(self),
42         }
43     }
44 }
45