xref: /DragonOS/kernel/crates/intertrait/src/lib.rs (revision c635d8a9cfe25bc11779f323ef0c7d7a0f597d4a)
1 //! A library providing direct casting among trait objects implemented by a type.
2 //!
3 //! In Rust, an object of a sub-trait of [`Any`] can be downcast to a concrete type
4 //! at runtime if the type is known. But no direct casting between two trait objects
5 //! (i.e. without involving the concrete type of the backing value) is possible
6 //! (even no coercion from a trait object to that of its super-trait yet).
7 //!
8 //! With this crate, any trait object with [`CastFrom`] as its super-trait can be cast directly
9 //! to another trait object implemented by the underlying type if the target traits are
10 //! registered beforehand with the macros provided by this crate.
11 //!
12 //! # Usage
13 //! ```
14 //! use intertrait::*;
15 //! use intertrait::cast::*;
16 //!
17 //! struct Data;
18 //!
19 //! trait Source: CastFrom {}
20 //!
21 //! trait Greet {
22 //!     fn greet(&self);
23 //! }
24 //!
25 //! #[cast_to]
26 //! impl Greet for Data {
27 //!     fn greet(&self) {
28 //!         println!("Hello");
29 //!     }
30 //! }
31 //!
32 //! impl Source for Data {}
33 //!
34 //! let data = Data;
35 //! let source: &dyn Source = &data;
36 //! let greet = source.cast::<dyn Greet>();
37 //! greet.unwrap().greet();
38 //! ```
39 //!
40 //! Target traits must be explicitly designated beforehand. There are three ways to do it:
41 //!
42 //! * [`#[cast_to]`][cast_to] to `impl` item
43 //! * [`#[cast_to(Trait)]`][cast_to] to type definition
44 //! * [`castable_to!(Type => Trait1, Trait2)`][castable_to]
45 //!
46 //! If the underlying type involved is `Sync + Send` and you want to use it with [`Arc`],
47 //! use [`CastFromSync`] in place of [`CastFrom`] and add `[sync]` flag before the list
48 //! of traits in the macros. Refer to the documents for each of macros for details.
49 //!
50 //! For casting, refer to traits defined in [`cast`] module.
51 //!
52 //! [cast_to]: ./attr.cast_to.html
53 //! [castable_to]: ./macro.castable_to.html
54 //! [`CastFrom`]: ./trait.CastFrom.html
55 //! [`CastFromSync`]: ./trait.CastFromSync.html
56 //! [`cast`]: ./cast/index.html
57 //! [`Any`]: https://doc.rust-lang.org/std/any/trait.Any.html
58 //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
59 
60 #![cfg_attr(target_os = "none", no_std)]
61 
62 extern crate alloc;
63 extern crate core;
64 
65 use core::{
66     any::{Any, TypeId},
67     marker::{Send, Sync},
68 };
69 
70 use alloc::boxed::Box;
71 use alloc::rc::Rc;
72 use alloc::sync::Arc;
73 
74 use hashbrown::HashMap;
75 use linkme::distributed_slice;
76 
77 pub use intertrait_macros::*;
78 
79 use crate::hasher::BuildFastHasher;
80 
81 pub mod cast;
82 mod hasher;
83 
84 #[doc(hidden)]
85 pub type BoxedCaster = Box<dyn Any + Send + Sync>;
86 
87 #[cfg(doctest)]
88 doc_comment::doctest!("../README.md");
89 
90 /// A distributed slice gathering constructor functions for [`Caster<T>`]s.
91 ///
92 /// A constructor function returns `TypeId` of a concrete type involved in the casting
93 /// and a `Box` of a trait object backed by a [`Caster<T>`].
94 ///
95 /// [`Caster<T>`]: ./struct.Caster.html
96 #[doc(hidden)]
97 #[distributed_slice]
98 pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..];
99 
100 /// A `HashMap` mapping `TypeId` of a [`Caster<T>`] to an instance of it.
101 ///
102 /// [`Caster<T>`]: ./struct.Caster.html
103 #[cfg(not(target_os = "none"))]
104 static CASTER_MAP: once_cell::sync::Lazy<HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>> =
105     once_cell::sync::Lazy::new(|| {
106         CASTERS
107             .iter()
108             .map(|f| {
109                 let (type_id, caster) = f();
110                 ((type_id, (*caster).type_id()), caster)
111             })
112             .collect()
113     });
114 
115 /// CasterMap
116 ///
117 /// key.0: type_id of source
118 /// key.1: type_id of target
119 ///
120 /// value: A BoxedCaster which can cast source to target
121 #[cfg(target_os = "none")]
122 static mut CASTER_MAP: Option<HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>> = None;
123 
124 #[cfg(target_os = "none")]
125 pub fn caster_map() -> &'static HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher> {
126     return unsafe {
127         CASTER_MAP.as_ref().unwrap_or_else(|| {
128             panic!("intertrait_caster_map() must be called after CASTER_MAP is initialized")
129         })
130     };
131 }
132 
133 /// Initializes the global [`CASTER_MAP`] with [`CASTERS`].
134 ///
135 /// no_std环境下,需要手动调用此函数初始化CASTER_MAP
136 #[cfg(target_os = "none")]
137 pub fn init_caster_map() {
138     use core::sync::atomic::AtomicBool;
139 
140     let pd = AtomicBool::new(false);
141     let r = pd.compare_exchange(
142         false,
143         true,
144         core::sync::atomic::Ordering::SeqCst,
145         core::sync::atomic::Ordering::SeqCst,
146     );
147 
148     if r.is_err() {
149         panic!("init_caster_map() must be called only once");
150     }
151 
152     let hashmap = CASTERS
153         .iter()
154         .map(|f| {
155             let (type_id, caster) = f();
156             ((type_id, (*caster).type_id()), caster)
157         })
158         .collect();
159 
160     unsafe { CASTER_MAP = Some(hashmap) };
161 }
162 
163 #[cfg(not(target_os = "none"))]
164 pub fn init_caster_map() {}
165 
166 fn cast_arc_panic<T: ?Sized + 'static>(_: Arc<dyn Any + Sync + Send>) -> Arc<T> {
167     panic!("Prepend [sync] to the list of target traits for Sync + Send types")
168 }
169 
170 /// A `Caster` knows how to cast a reference to or `Box` of a trait object for `Any`
171 /// to a trait object of trait `T`. Each `Caster` instance is specific to a concrete type.
172 /// That is, it knows how to cast to single specific trait implemented by single specific type.
173 ///
174 /// An implementation of a trait for a concrete type doesn't need to manually provide
175 /// a `Caster`. Instead attach `#[cast_to]` to the `impl` block.
176 #[doc(hidden)]
177 pub struct Caster<T: ?Sized + 'static> {
178     /// Casts an immutable reference to a trait object for `Any` to a reference
179     /// to a trait object for trait `T`.
180     pub cast_ref: fn(from: &dyn Any) -> &T,
181 
182     /// Casts a mutable reference to a trait object for `Any` to a mutable reference
183     /// to a trait object for trait `T`.
184     pub cast_mut: fn(from: &mut dyn Any) -> &mut T,
185 
186     /// Casts a `Box` holding a trait object for `Any` to another `Box` holding a trait object
187     /// for trait `T`.
188     pub cast_box: fn(from: Box<dyn Any>) -> Box<T>,
189 
190     /// Casts an `Rc` holding a trait object for `Any` to another `Rc` holding a trait object
191     /// for trait `T`.
192     pub cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
193 
194     /// Casts an `Arc` holding a trait object for `Any + Sync + Send + 'static`
195     /// to another `Arc` holding a trait object for trait `T`.
196     pub cast_arc: fn(from: Arc<dyn Any + Sync + Send + 'static>) -> Arc<T>,
197 }
198 
199 impl<T: ?Sized + 'static> Caster<T> {
200     pub fn new(
201         cast_ref: fn(from: &dyn Any) -> &T,
202         cast_mut: fn(from: &mut dyn Any) -> &mut T,
203         cast_box: fn(from: Box<dyn Any>) -> Box<T>,
204         cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
205     ) -> Caster<T> {
206         Caster::<T> {
207             cast_ref,
208             cast_mut,
209             cast_box,
210             cast_rc,
211             cast_arc: cast_arc_panic,
212         }
213     }
214 
215     pub fn new_sync(
216         cast_ref: fn(from: &dyn Any) -> &T,
217         cast_mut: fn(from: &mut dyn Any) -> &mut T,
218         cast_box: fn(from: Box<dyn Any>) -> Box<T>,
219         cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
220         cast_arc: fn(from: Arc<dyn Any + Sync + Send>) -> Arc<T>,
221     ) -> Caster<T> {
222         Caster::<T> {
223             cast_ref,
224             cast_mut,
225             cast_box,
226             cast_rc,
227             cast_arc,
228         }
229     }
230 }
231 
232 /// Returns a `Caster<S, T>` from a concrete type `S` to a trait `T` implemented by it.
233 ///
234 /// ## 参数
235 ///
236 /// - type_id: 源类型的type_id
237 ///
238 /// T: 目标trait
239 fn caster<T: ?Sized + 'static>(type_id: TypeId) -> Option<&'static Caster<T>> {
240     #[cfg(not(target_os = "none"))]
241     {
242         CASTER_MAP
243             .get(&(type_id, TypeId::of::<Caster<T>>()))
244             .and_then(|caster| caster.downcast_ref::<Caster<T>>())
245     }
246 
247     #[cfg(target_os = "none")]
248     {
249         caster_map()
250             .get(&(type_id, TypeId::of::<Caster<T>>()))
251             .and_then(|caster| caster.downcast_ref::<Caster<T>>())
252     }
253 }
254 
255 /// `CastFrom` must be extended by a trait that wants to allow for casting into another trait.
256 ///
257 /// It is used for obtaining a trait object for [`Any`] from a trait object for its sub-trait,
258 /// and blanket implemented for all `Sized + Any + 'static` types.
259 ///
260 /// # Examples
261 /// ```ignore
262 /// trait Source: CastFrom {
263 ///     ...
264 /// }
265 /// ```
266 pub trait CastFrom: Any + 'static {
267     /// Returns a immutable reference to `Any`, which is backed by the type implementing this trait.
268     fn ref_any(&self) -> &dyn Any;
269 
270     /// Returns a mutable reference to `Any`, which is backed by the type implementing this trait.
271     fn mut_any(&mut self) -> &mut dyn Any;
272 
273     /// Returns a `Box` of `Any`, which is backed by the type implementing this trait.
274     fn box_any(self: Box<Self>) -> Box<dyn Any>;
275 
276     /// Returns an `Rc` of `Any`, which is backed by the type implementing this trait.
277     fn rc_any(self: Rc<Self>) -> Rc<dyn Any>;
278 }
279 
280 /// `CastFromSync` must be extended by a trait that is `Any + Sync + Send + 'static`
281 /// and wants to allow for casting into another trait behind references and smart pointers
282 /// especially including `Arc`.
283 ///
284 /// It is used for obtaining a trait object for [`Any + Sync + Send + 'static`] from an object
285 /// for its sub-trait, and blanket implemented for all `Sized + Sync + Send + 'static` types.
286 ///
287 /// # Examples
288 /// ```ignore
289 /// trait Source: CastFromSync {
290 ///     ...
291 /// }
292 /// ```
293 pub trait CastFromSync: CastFrom + Sync + Send + 'static {
294     fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>;
295 }
296 
297 impl<T: Sized + Any + 'static> CastFrom for T {
298     fn ref_any(&self) -> &dyn Any {
299         self
300     }
301 
302     fn mut_any(&mut self) -> &mut dyn Any {
303         self
304     }
305 
306     fn box_any(self: Box<Self>) -> Box<dyn Any> {
307         self
308     }
309 
310     fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
311         self
312     }
313 }
314 
315 impl CastFrom for dyn Any + 'static {
316     fn ref_any(&self) -> &dyn Any {
317         self
318     }
319 
320     fn mut_any(&mut self) -> &mut dyn Any {
321         self
322     }
323 
324     fn box_any(self: Box<Self>) -> Box<dyn Any> {
325         self
326     }
327 
328     fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
329         self
330     }
331 }
332 
333 impl<T: Sized + Sync + Send + 'static> CastFromSync for T {
334     fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> {
335         self
336     }
337 }
338 
339 impl CastFrom for dyn Any + Sync + Send + 'static {
340     fn ref_any(&self) -> &dyn Any {
341         self
342     }
343 
344     fn mut_any(&mut self) -> &mut dyn Any {
345         self
346     }
347 
348     fn box_any(self: Box<Self>) -> Box<dyn Any> {
349         self
350     }
351 
352     fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
353         self
354     }
355 }
356 
357 impl CastFromSync for dyn Any + Sync + Send + 'static {
358     fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> {
359         self
360     }
361 }
362 
363 #[cfg(test)]
364 mod tests {
365     extern crate std;
366     use std::any::{Any, TypeId};
367     use std::fmt::{Debug, Display};
368 
369     use linkme::distributed_slice;
370 
371     use crate::{BoxedCaster, CastFromSync};
372 
373     use super::cast::*;
374     use super::*;
375 
376     #[distributed_slice(super::CASTERS)]
377     static TEST_CASTER: fn() -> (TypeId, BoxedCaster) = create_test_caster;
378 
379     #[derive(Debug)]
380     struct TestStruct;
381 
382     trait SourceTrait: CastFromSync {}
383 
384     impl SourceTrait for TestStruct {}
385 
386     fn create_test_caster() -> (TypeId, BoxedCaster) {
387         let type_id = TypeId::of::<TestStruct>();
388         let caster = Box::new(Caster::<dyn Debug> {
389             cast_ref: |from| from.downcast_ref::<TestStruct>().unwrap(),
390             cast_mut: |from| from.downcast_mut::<TestStruct>().unwrap(),
391             cast_box: |from| from.downcast::<TestStruct>().unwrap(),
392             cast_rc: |from| from.downcast::<TestStruct>().unwrap(),
393             cast_arc: |from| from.downcast::<TestStruct>().unwrap(),
394         });
395         (type_id, caster)
396     }
397 
398     #[test]
399     fn cast_ref() {
400         let ts = TestStruct;
401         let st: &dyn SourceTrait = &ts;
402         let debug = st.cast::<dyn Debug>();
403         assert!(debug.is_some());
404     }
405 
406     #[test]
407     fn cast_mut() {
408         let mut ts = TestStruct;
409         let st: &mut dyn SourceTrait = &mut ts;
410         let debug = st.cast::<dyn Debug>();
411         assert!(debug.is_some());
412     }
413 
414     #[test]
415     fn cast_box() {
416         let ts = Box::new(TestStruct);
417         let st: Box<dyn SourceTrait> = ts;
418         let debug = st.cast::<dyn Debug>();
419         assert!(debug.is_ok());
420     }
421 
422     #[test]
423     fn cast_rc() {
424         let ts = Rc::new(TestStruct);
425         let st: Rc<dyn SourceTrait> = ts;
426         let debug = st.cast::<dyn Debug>();
427         assert!(debug.is_ok());
428     }
429 
430     #[test]
431     fn cast_arc() {
432         let ts = Arc::new(TestStruct);
433         let st: Arc<dyn SourceTrait> = ts;
434         let debug = st.cast::<dyn Debug>();
435         assert!(debug.is_ok());
436     }
437 
438     #[test]
439     fn cast_ref_wrong() {
440         let ts = TestStruct;
441         let st: &dyn SourceTrait = &ts;
442         let display = st.cast::<dyn Display>();
443         assert!(display.is_none());
444     }
445 
446     #[test]
447     fn cast_mut_wrong() {
448         let mut ts = TestStruct;
449         let st: &mut dyn SourceTrait = &mut ts;
450         let display = st.cast::<dyn Display>();
451         assert!(display.is_none());
452     }
453 
454     #[test]
455     fn cast_box_wrong() {
456         let ts = Box::new(TestStruct);
457         let st: Box<dyn SourceTrait> = ts;
458         let display = st.cast::<dyn Display>();
459         assert!(display.is_err());
460     }
461 
462     #[test]
463     fn cast_rc_wrong() {
464         let ts = Rc::new(TestStruct);
465         let st: Rc<dyn SourceTrait> = ts;
466         let display = st.cast::<dyn Display>();
467         assert!(display.is_err());
468     }
469 
470     #[test]
471     fn cast_arc_wrong() {
472         let ts = Arc::new(TestStruct);
473         let st: Arc<dyn SourceTrait> = ts;
474         let display = st.cast::<dyn Display>();
475         assert!(display.is_err());
476     }
477 
478     #[test]
479     fn cast_ref_from_any() {
480         let ts = TestStruct;
481         let st: &dyn Any = &ts;
482         let debug = st.cast::<dyn Debug>();
483         assert!(debug.is_some());
484     }
485 
486     #[test]
487     fn cast_mut_from_any() {
488         let mut ts = TestStruct;
489         let st: &mut dyn Any = &mut ts;
490         let debug = st.cast::<dyn Debug>();
491         assert!(debug.is_some());
492     }
493 
494     #[test]
495     fn cast_box_from_any() {
496         let ts = Box::new(TestStruct);
497         let st: Box<dyn Any> = ts;
498         let debug = st.cast::<dyn Debug>();
499         assert!(debug.is_ok());
500     }
501 
502     #[test]
503     fn cast_rc_from_any() {
504         let ts = Rc::new(TestStruct);
505         let st: Rc<dyn Any> = ts;
506         let debug = st.cast::<dyn Debug>();
507         assert!(debug.is_ok());
508     }
509 
510     #[test]
511     fn cast_arc_from_any() {
512         let ts = Arc::new(TestStruct);
513         let st: Arc<dyn Any + Send + Sync> = ts;
514         let debug = st.cast::<dyn Debug>();
515         assert!(debug.is_ok());
516     }
517 
518     #[test]
519     fn impls_ref() {
520         let ts = TestStruct;
521         let st: &dyn SourceTrait = &ts;
522         assert!(st.impls::<dyn Debug>());
523     }
524 
525     #[test]
526     fn impls_mut() {
527         let mut ts = TestStruct;
528         let st: &mut dyn SourceTrait = &mut ts;
529         assert!((*st).impls::<dyn Debug>());
530     }
531 
532     #[test]
533     fn impls_box() {
534         let ts = Box::new(TestStruct);
535         let st: Box<dyn SourceTrait> = ts;
536         assert!((*st).impls::<dyn Debug>());
537     }
538 
539     #[test]
540     fn impls_rc() {
541         let ts = Rc::new(TestStruct);
542         let st: Rc<dyn SourceTrait> = ts;
543         assert!((*st).impls::<dyn Debug>());
544     }
545 
546     #[test]
547     fn impls_arc() {
548         let ts = Arc::new(TestStruct);
549         let st: Arc<dyn SourceTrait> = ts;
550         assert!((*st).impls::<dyn Debug>());
551     }
552 
553     #[test]
554     fn impls_not_ref() {
555         let ts = TestStruct;
556         let st: &dyn SourceTrait = &ts;
557         assert!(!st.impls::<dyn Display>());
558     }
559 
560     #[test]
561     fn impls_not_mut() {
562         let mut ts = TestStruct;
563         let st: &mut dyn Any = &mut ts;
564         assert!(!(*st).impls::<dyn Display>());
565     }
566 
567     #[test]
568     fn impls_not_box() {
569         let ts = Box::new(TestStruct);
570         let st: Box<dyn SourceTrait> = ts;
571         assert!(!st.impls::<dyn Display>());
572     }
573 
574     #[test]
575     fn impls_not_rc() {
576         let ts = Rc::new(TestStruct);
577         let st: Rc<dyn SourceTrait> = ts;
578         assert!(!(*st).impls::<dyn Display>());
579     }
580 
581     #[test]
582     fn impls_not_arc() {
583         let ts = Arc::new(TestStruct);
584         let st: Arc<dyn SourceTrait> = ts;
585         assert!(!(*st).impls::<dyn Display>());
586     }
587 }
588