xref: /DragonOS/kernel/crates/intertrait/src/cast/cast_arc.rs (revision bd70d2d1f490aabd570a5301b858bd5eb04149fa)
1 use alloc::sync::Arc;
2 
3 use crate::{caster, CastFromSync};
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::sync::Arc;
12 /// # use intertrait::*;
13 /// use intertrait::cast::*;
14 ///
15 /// # #[cast_to([sync] 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 = Arc::new(data);
29 /// let greet = source.cast::<dyn Greet>();
30 /// greet.unwrap_or_else(|_| panic!("must not happen")).greet();
31 /// ```
32 pub trait CastArc {
33     /// Casts an `Arc` for this trait into that for type `T`.
cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>>34     fn cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>>;
35 }
36 
37 /// A blanket implementation of `CastArc` for traits extending `CastFrom`, `Sync`, and `Send`.
38 impl<S: ?Sized + CastFromSync> CastArc for S {
cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>>39     fn cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>> {
40         match caster::<T>((*self).type_id()) {
41             Some(caster) => Ok((caster.cast_arc)(self.arc_any())),
42             None => Err(self),
43         }
44     }
45 }
46