Skip to main content

intertrait/cast/
cast_rc.rs

1use alloc::rc::Rc;
2
3use crate::{caster, CastFrom};
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 `Rc` to a trait object for another trait
7/// implemented by the underlying value.
8///
9/// # Examples
10/// ```
11/// # use std::rc::Rc;
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 = Rc::new(data);
29/// let greet = source.cast::<dyn Greet>();
30/// greet.unwrap_or_else(|_| panic!("must not happen")).greet();
31/// ```
32pub trait CastRc {
33    /// Casts an `Rc` for this trait into that for type `T`.
34    fn cast<T: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>>;
35}
36
37/// A blanket implementation of `CastRc` for traits extending `CastFrom`.
38impl<S: ?Sized + CastFrom> CastRc for S {
39    fn cast<T: ?Sized + 'static>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>> {
40        match caster::<T>((*self).type_id()) {
41            Some(caster) => Ok((caster.cast_rc)(self.rc_any())),
42            None => Err(self),
43        }
44    }
45}