xref: /DragonOS/kernel/crates/intertrait/src/cast/cast_box.rs (revision bd70d2d1f490aabd570a5301b858bd5eb04149fa)
1 use alloc::boxed::Box;
2 
3 use 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 /// ```
31 pub trait CastBox {
32     /// Casts a box to this trait into that of type `T`. If fails, returns the receiver.
cast<T: ?Sized + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>>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`.
37 impl<S: ?Sized + CastFrom> CastBox for S {
cast<T: ?Sized + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>>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 }
45