intertrait/cast/cast_box.rs
1use alloc::boxed::Box;
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 a `Box` to a trait object for another trait
7/// implemented by the underlying value.
8///
9/// # Examples
10/// ```
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 = Box::new(Data);
27/// let source: Box<dyn Source> = data;
28/// let greet = source.cast::<dyn Greet>();
29/// greet.unwrap_or_else(|_| panic!("casting failed")).greet();
30/// ```
31pub trait CastBox {
32 /// Casts a box to this trait into that of type `T`. If fails, returns the receiver.
33 fn cast<T: ?Sized + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>>;
34}
35
36/// A blanket implementation of `CastBox` for traits extending `CastFrom`.
37impl<S: ?Sized + CastFrom> CastBox for S {
38 fn cast<T: ?Sized + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
39 match caster::<T>((*self).type_id()) {
40 Some(caster) => Ok((caster.cast_box)(self.box_any())),
41 None => Err(self),
42 }
43 }
44}