intertrait/cast/
cast_rc.rs

1use crate::{caster, CastFrom};
2use std::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/// ```
31pub 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`.
37impl<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}