xref: /DragonOS/kernel/crates/intertrait/src/cast/cast_arc.rs (revision bd70d2d1f490aabd570a5301b858bd5eb04149fa)
1*bd70d2d1SLoGin use alloc::sync::Arc;
2*bd70d2d1SLoGin 
3*bd70d2d1SLoGin use crate::{caster, CastFromSync};
4*bd70d2d1SLoGin 
5*bd70d2d1SLoGin /// A trait that is blanket-implemented for traits extending `CastFrom` to allow for casting
6*bd70d2d1SLoGin /// of a trait object for it behind an `Rc` to a trait object for another trait
7*bd70d2d1SLoGin /// implemented by the underlying value.
8*bd70d2d1SLoGin ///
9*bd70d2d1SLoGin /// # Examples
10*bd70d2d1SLoGin /// ```
11*bd70d2d1SLoGin /// # use std::sync::Arc;
12*bd70d2d1SLoGin /// # use intertrait::*;
13*bd70d2d1SLoGin /// use intertrait::cast::*;
14*bd70d2d1SLoGin ///
15*bd70d2d1SLoGin /// # #[cast_to([sync] Greet)]
16*bd70d2d1SLoGin /// # struct Data;
17*bd70d2d1SLoGin /// # trait Source: CastFrom {}
18*bd70d2d1SLoGin /// # trait Greet {
19*bd70d2d1SLoGin /// #     fn greet(&self);
20*bd70d2d1SLoGin /// # }
21*bd70d2d1SLoGin /// # impl Greet for Data {
22*bd70d2d1SLoGin /// #    fn greet(&self) {
23*bd70d2d1SLoGin /// #        println!("Hello");
24*bd70d2d1SLoGin /// #    }
25*bd70d2d1SLoGin /// # }
26*bd70d2d1SLoGin /// impl Source for Data {}
27*bd70d2d1SLoGin /// let data = Data;
28*bd70d2d1SLoGin /// let source = Arc::new(data);
29*bd70d2d1SLoGin /// let greet = source.cast::<dyn Greet>();
30*bd70d2d1SLoGin /// greet.unwrap_or_else(|_| panic!("must not happen")).greet();
31*bd70d2d1SLoGin /// ```
32*bd70d2d1SLoGin pub trait CastArc {
33*bd70d2d1SLoGin     /// Casts an `Arc` for this trait into that for type `T`.
cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>>34*bd70d2d1SLoGin     fn cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>>;
35*bd70d2d1SLoGin }
36*bd70d2d1SLoGin 
37*bd70d2d1SLoGin /// A blanket implementation of `CastArc` for traits extending `CastFrom`, `Sync`, and `Send`.
38*bd70d2d1SLoGin impl<S: ?Sized + CastFromSync> CastArc for S {
cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>>39*bd70d2d1SLoGin     fn cast<T: ?Sized + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>> {
40*bd70d2d1SLoGin         match caster::<T>((*self).type_id()) {
41*bd70d2d1SLoGin             Some(caster) => Ok((caster.cast_arc)(self.arc_any())),
42*bd70d2d1SLoGin             None => Err(self),
43*bd70d2d1SLoGin         }
44*bd70d2d1SLoGin     }
45*bd70d2d1SLoGin }
46