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")]
caster_map() -> &'static HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>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")]
init_caster_map()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"))]
init_caster_map()164 pub fn init_caster_map() {}
165
cast_arc_panic<T: ?Sized + 'static>(_: Arc<dyn Any + Sync + Send>) -> Arc<T>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> {
new( cast_ref: fn(from: &dyn Any) -> &T, cast_mut: fn(from: &mut dyn Any) -> &mut T, cast_box: fn(from: Box<dyn Any>) -> Box<T>, cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>, ) -> 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
new_sync( cast_ref: fn(from: &dyn Any) -> &T, cast_mut: fn(from: &mut dyn Any) -> &mut T, cast_box: fn(from: Box<dyn Any>) -> Box<T>, cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>, cast_arc: fn(from: Arc<dyn Any + Sync + Send>) -> Arc<T>, ) -> Caster<T>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
caster<T: ?Sized + 'static>(type_id: TypeId) -> Option<&'static Caster<T>>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.
ref_any(&self) -> &dyn Any268 fn ref_any(&self) -> &dyn Any;
269
270 /// Returns a mutable reference to `Any`, which is backed by the type implementing this trait.
mut_any(&mut self) -> &mut dyn Any271 fn mut_any(&mut self) -> &mut dyn Any;
272
273 /// Returns a `Box` of `Any`, which is backed by the type implementing this trait.
box_any(self: Box<Self>) -> Box<dyn Any>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.
rc_any(self: Rc<Self>) -> Rc<dyn Any>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 {
arc_any(self: Arc<Self>) -> Arc<dyn Any + 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 {
ref_any(&self) -> &dyn Any298 fn ref_any(&self) -> &dyn Any {
299 self
300 }
301
mut_any(&mut self) -> &mut dyn Any302 fn mut_any(&mut self) -> &mut dyn Any {
303 self
304 }
305
box_any(self: Box<Self>) -> Box<dyn Any>306 fn box_any(self: Box<Self>) -> Box<dyn Any> {
307 self
308 }
309
rc_any(self: Rc<Self>) -> Rc<dyn Any>310 fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
311 self
312 }
313 }
314
315 impl CastFrom for dyn Any + 'static {
ref_any(&self) -> &dyn Any316 fn ref_any(&self) -> &dyn Any {
317 self
318 }
319
mut_any(&mut self) -> &mut dyn Any320 fn mut_any(&mut self) -> &mut dyn Any {
321 self
322 }
323
box_any(self: Box<Self>) -> Box<dyn Any>324 fn box_any(self: Box<Self>) -> Box<dyn Any> {
325 self
326 }
327
rc_any(self: Rc<Self>) -> Rc<dyn Any>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 {
arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>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 {
ref_any(&self) -> &dyn Any340 fn ref_any(&self) -> &dyn Any {
341 self
342 }
343
mut_any(&mut self) -> &mut dyn Any344 fn mut_any(&mut self) -> &mut dyn Any {
345 self
346 }
347
box_any(self: Box<Self>) -> Box<dyn Any>348 fn box_any(self: Box<Self>) -> Box<dyn Any> {
349 self
350 }
351
rc_any(self: Rc<Self>) -> Rc<dyn Any>352 fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
353 self
354 }
355 }
356
357 impl CastFromSync for dyn Any + Sync + Send + 'static {
arc_any(self: Arc<Self>) -> Arc<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
create_test_caster() -> (TypeId, BoxedCaster)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]
cast_ref()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]
cast_mut()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]
cast_box()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]
cast_rc()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]
cast_arc()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]
cast_ref_wrong()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]
cast_mut_wrong()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]
cast_box_wrong()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]
cast_rc_wrong()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]
cast_arc_wrong()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]
cast_ref_from_any()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]
cast_mut_from_any()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]
cast_box_from_any()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]
cast_rc_from_any()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]
cast_arc_from_any()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]
impls_ref()519 fn impls_ref() {
520 let ts = TestStruct;
521 let st: &dyn SourceTrait = &ts;
522 assert!(st.impls::<dyn Debug>());
523 }
524
525 #[test]
impls_mut()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]
impls_box()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]
impls_rc()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]
impls_arc()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]
impls_not_ref()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]
impls_not_mut()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]
impls_not_box()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]
impls_not_rc()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]
impls_not_arc()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