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 #[allow(static_mut_refs)]
caster_map() -> &'static HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>126 pub fn caster_map() -> &'static HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher> {
127 return unsafe {
128 CASTER_MAP.as_ref().unwrap_or_else(|| {
129 panic!("intertrait_caster_map() must be called after CASTER_MAP is initialized")
130 })
131 };
132 }
133
134 /// Initializes the global [`CASTER_MAP`] with [`CASTERS`].
135 ///
136 /// no_std环境下,需要手动调用此函数初始化CASTER_MAP
137 #[cfg(target_os = "none")]
init_caster_map()138 pub fn init_caster_map() {
139 use core::sync::atomic::AtomicBool;
140
141 let pd = AtomicBool::new(false);
142 let r = pd.compare_exchange(
143 false,
144 true,
145 core::sync::atomic::Ordering::SeqCst,
146 core::sync::atomic::Ordering::SeqCst,
147 );
148
149 if r.is_err() {
150 panic!("init_caster_map() must be called only once");
151 }
152
153 let hashmap = CASTERS
154 .iter()
155 .map(|f| {
156 let (type_id, caster) = f();
157 ((type_id, (*caster).type_id()), caster)
158 })
159 .collect();
160
161 unsafe { CASTER_MAP = Some(hashmap) };
162 }
163
164 #[cfg(not(target_os = "none"))]
init_caster_map()165 pub fn init_caster_map() {}
166
cast_arc_panic<T: ?Sized + 'static>(_: Arc<dyn Any + Sync + Send>) -> Arc<T>167 fn cast_arc_panic<T: ?Sized + 'static>(_: Arc<dyn Any + Sync + Send>) -> Arc<T> {
168 panic!("Prepend [sync] to the list of target traits for Sync + Send types")
169 }
170
171 /// A `Caster` knows how to cast a reference to or `Box` of a trait object for `Any`
172 /// to a trait object of trait `T`. Each `Caster` instance is specific to a concrete type.
173 /// That is, it knows how to cast to single specific trait implemented by single specific type.
174 ///
175 /// An implementation of a trait for a concrete type doesn't need to manually provide
176 /// a `Caster`. Instead attach `#[cast_to]` to the `impl` block.
177 #[doc(hidden)]
178 pub struct Caster<T: ?Sized + 'static> {
179 /// Casts an immutable reference to a trait object for `Any` to a reference
180 /// to a trait object for trait `T`.
181 pub cast_ref: fn(from: &dyn Any) -> &T,
182
183 /// Casts a mutable reference to a trait object for `Any` to a mutable reference
184 /// to a trait object for trait `T`.
185 pub cast_mut: fn(from: &mut dyn Any) -> &mut T,
186
187 /// Casts a `Box` holding a trait object for `Any` to another `Box` holding a trait object
188 /// for trait `T`.
189 pub cast_box: fn(from: Box<dyn Any>) -> Box<T>,
190
191 /// Casts an `Rc` holding a trait object for `Any` to another `Rc` holding a trait object
192 /// for trait `T`.
193 pub cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
194
195 /// Casts an `Arc` holding a trait object for `Any + Sync + Send + 'static`
196 /// to another `Arc` holding a trait object for trait `T`.
197 pub cast_arc: fn(from: Arc<dyn Any + Sync + Send + 'static>) -> Arc<T>,
198 }
199
200 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>201 pub fn new(
202 cast_ref: fn(from: &dyn Any) -> &T,
203 cast_mut: fn(from: &mut dyn Any) -> &mut T,
204 cast_box: fn(from: Box<dyn Any>) -> Box<T>,
205 cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
206 ) -> Caster<T> {
207 Caster::<T> {
208 cast_ref,
209 cast_mut,
210 cast_box,
211 cast_rc,
212 cast_arc: cast_arc_panic,
213 }
214 }
215
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>216 pub fn new_sync(
217 cast_ref: fn(from: &dyn Any) -> &T,
218 cast_mut: fn(from: &mut dyn Any) -> &mut T,
219 cast_box: fn(from: Box<dyn Any>) -> Box<T>,
220 cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
221 cast_arc: fn(from: Arc<dyn Any + Sync + Send>) -> Arc<T>,
222 ) -> Caster<T> {
223 Caster::<T> {
224 cast_ref,
225 cast_mut,
226 cast_box,
227 cast_rc,
228 cast_arc,
229 }
230 }
231 }
232
233 /// Returns a `Caster<S, T>` from a concrete type `S` to a trait `T` implemented by it.
234 ///
235 /// ## 参数
236 ///
237 /// - type_id: 源类型的type_id
238 ///
239 /// T: 目标trait
caster<T: ?Sized + 'static>(type_id: TypeId) -> Option<&'static Caster<T>>240 fn caster<T: ?Sized + 'static>(type_id: TypeId) -> Option<&'static Caster<T>> {
241 #[cfg(not(target_os = "none"))]
242 {
243 CASTER_MAP
244 .get(&(type_id, TypeId::of::<Caster<T>>()))
245 .and_then(|caster| caster.downcast_ref::<Caster<T>>())
246 }
247
248 #[cfg(target_os = "none")]
249 {
250 caster_map()
251 .get(&(type_id, TypeId::of::<Caster<T>>()))
252 .and_then(|caster| caster.downcast_ref::<Caster<T>>())
253 }
254 }
255
256 /// `CastFrom` must be extended by a trait that wants to allow for casting into another trait.
257 ///
258 /// It is used for obtaining a trait object for [`Any`] from a trait object for its sub-trait,
259 /// and blanket implemented for all `Sized + Any + 'static` types.
260 ///
261 /// # Examples
262 /// ```ignore
263 /// trait Source: CastFrom {
264 /// ...
265 /// }
266 /// ```
267 pub trait CastFrom: Any + 'static {
268 /// Returns a immutable reference to `Any`, which is backed by the type implementing this trait.
ref_any(&self) -> &dyn Any269 fn ref_any(&self) -> &dyn Any;
270
271 /// Returns a mutable reference to `Any`, which is backed by the type implementing this trait.
mut_any(&mut self) -> &mut dyn Any272 fn mut_any(&mut self) -> &mut dyn Any;
273
274 /// Returns a `Box` of `Any`, which is backed by the type implementing this trait.
box_any(self: Box<Self>) -> Box<dyn Any>275 fn box_any(self: Box<Self>) -> Box<dyn Any>;
276
277 /// Returns an `Rc` of `Any`, which is backed by the type implementing this trait.
rc_any(self: Rc<Self>) -> Rc<dyn Any>278 fn rc_any(self: Rc<Self>) -> Rc<dyn Any>;
279 }
280
281 /// `CastFromSync` must be extended by a trait that is `Any + Sync + Send + 'static`
282 /// and wants to allow for casting into another trait behind references and smart pointers
283 /// especially including `Arc`.
284 ///
285 /// It is used for obtaining a trait object for [`Any + Sync + Send + 'static`] from an object
286 /// for its sub-trait, and blanket implemented for all `Sized + Sync + Send + 'static` types.
287 ///
288 /// # Examples
289 /// ```ignore
290 /// trait Source: CastFromSync {
291 /// ...
292 /// }
293 /// ```
294 pub trait CastFromSync: CastFrom + Sync + Send + 'static {
arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>295 fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>;
296 }
297
298 impl<T: Sized + Any + 'static> CastFrom for T {
ref_any(&self) -> &dyn Any299 fn ref_any(&self) -> &dyn Any {
300 self
301 }
302
mut_any(&mut self) -> &mut dyn Any303 fn mut_any(&mut self) -> &mut dyn Any {
304 self
305 }
306
box_any(self: Box<Self>) -> Box<dyn Any>307 fn box_any(self: Box<Self>) -> Box<dyn Any> {
308 self
309 }
310
rc_any(self: Rc<Self>) -> Rc<dyn Any>311 fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
312 self
313 }
314 }
315
316 impl CastFrom for dyn Any + 'static {
ref_any(&self) -> &dyn Any317 fn ref_any(&self) -> &dyn Any {
318 self
319 }
320
mut_any(&mut self) -> &mut dyn Any321 fn mut_any(&mut self) -> &mut dyn Any {
322 self
323 }
324
box_any(self: Box<Self>) -> Box<dyn Any>325 fn box_any(self: Box<Self>) -> Box<dyn Any> {
326 self
327 }
328
rc_any(self: Rc<Self>) -> Rc<dyn Any>329 fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
330 self
331 }
332 }
333
334 impl<T: Sized + Sync + Send + 'static> CastFromSync for T {
arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>335 fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> {
336 self
337 }
338 }
339
340 impl CastFrom for dyn Any + Sync + Send + 'static {
ref_any(&self) -> &dyn Any341 fn ref_any(&self) -> &dyn Any {
342 self
343 }
344
mut_any(&mut self) -> &mut dyn Any345 fn mut_any(&mut self) -> &mut dyn Any {
346 self
347 }
348
box_any(self: Box<Self>) -> Box<dyn Any>349 fn box_any(self: Box<Self>) -> Box<dyn Any> {
350 self
351 }
352
rc_any(self: Rc<Self>) -> Rc<dyn Any>353 fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
354 self
355 }
356 }
357
358 impl CastFromSync for dyn Any + Sync + Send + 'static {
arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>359 fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> {
360 self
361 }
362 }
363
364 #[cfg(test)]
365 mod tests {
366 extern crate std;
367 use std::any::{Any, TypeId};
368 use std::fmt::{Debug, Display};
369
370 use linkme::distributed_slice;
371
372 use crate::{BoxedCaster, CastFromSync};
373
374 use super::cast::*;
375 use super::*;
376
377 #[distributed_slice(super::CASTERS)]
378 static TEST_CASTER: fn() -> (TypeId, BoxedCaster) = create_test_caster;
379
380 #[derive(Debug)]
381 struct TestStruct;
382
383 trait SourceTrait: CastFromSync {}
384
385 impl SourceTrait for TestStruct {}
386
create_test_caster() -> (TypeId, BoxedCaster)387 fn create_test_caster() -> (TypeId, BoxedCaster) {
388 let type_id = TypeId::of::<TestStruct>();
389 let caster = Box::new(Caster::<dyn Debug> {
390 cast_ref: |from| from.downcast_ref::<TestStruct>().unwrap(),
391 cast_mut: |from| from.downcast_mut::<TestStruct>().unwrap(),
392 cast_box: |from| from.downcast::<TestStruct>().unwrap(),
393 cast_rc: |from| from.downcast::<TestStruct>().unwrap(),
394 cast_arc: |from| from.downcast::<TestStruct>().unwrap(),
395 });
396 (type_id, caster)
397 }
398
399 #[test]
cast_ref()400 fn cast_ref() {
401 let ts = TestStruct;
402 let st: &dyn SourceTrait = &ts;
403 let debug = st.cast::<dyn Debug>();
404 assert!(debug.is_some());
405 }
406
407 #[test]
cast_mut()408 fn cast_mut() {
409 let mut ts = TestStruct;
410 let st: &mut dyn SourceTrait = &mut ts;
411 let debug = st.cast::<dyn Debug>();
412 assert!(debug.is_some());
413 }
414
415 #[test]
cast_box()416 fn cast_box() {
417 let ts = Box::new(TestStruct);
418 let st: Box<dyn SourceTrait> = ts;
419 let debug = st.cast::<dyn Debug>();
420 assert!(debug.is_ok());
421 }
422
423 #[test]
cast_rc()424 fn cast_rc() {
425 let ts = Rc::new(TestStruct);
426 let st: Rc<dyn SourceTrait> = ts;
427 let debug = st.cast::<dyn Debug>();
428 assert!(debug.is_ok());
429 }
430
431 #[test]
cast_arc()432 fn cast_arc() {
433 let ts = Arc::new(TestStruct);
434 let st: Arc<dyn SourceTrait> = ts;
435 let debug = st.cast::<dyn Debug>();
436 assert!(debug.is_ok());
437 }
438
439 #[test]
cast_ref_wrong()440 fn cast_ref_wrong() {
441 let ts = TestStruct;
442 let st: &dyn SourceTrait = &ts;
443 let display = st.cast::<dyn Display>();
444 assert!(display.is_none());
445 }
446
447 #[test]
cast_mut_wrong()448 fn cast_mut_wrong() {
449 let mut ts = TestStruct;
450 let st: &mut dyn SourceTrait = &mut ts;
451 let display = st.cast::<dyn Display>();
452 assert!(display.is_none());
453 }
454
455 #[test]
cast_box_wrong()456 fn cast_box_wrong() {
457 let ts = Box::new(TestStruct);
458 let st: Box<dyn SourceTrait> = ts;
459 let display = st.cast::<dyn Display>();
460 assert!(display.is_err());
461 }
462
463 #[test]
cast_rc_wrong()464 fn cast_rc_wrong() {
465 let ts = Rc::new(TestStruct);
466 let st: Rc<dyn SourceTrait> = ts;
467 let display = st.cast::<dyn Display>();
468 assert!(display.is_err());
469 }
470
471 #[test]
cast_arc_wrong()472 fn cast_arc_wrong() {
473 let ts = Arc::new(TestStruct);
474 let st: Arc<dyn SourceTrait> = ts;
475 let display = st.cast::<dyn Display>();
476 assert!(display.is_err());
477 }
478
479 #[test]
cast_ref_from_any()480 fn cast_ref_from_any() {
481 let ts = TestStruct;
482 let st: &dyn Any = &ts;
483 let debug = st.cast::<dyn Debug>();
484 assert!(debug.is_some());
485 }
486
487 #[test]
cast_mut_from_any()488 fn cast_mut_from_any() {
489 let mut ts = TestStruct;
490 let st: &mut dyn Any = &mut ts;
491 let debug = st.cast::<dyn Debug>();
492 assert!(debug.is_some());
493 }
494
495 #[test]
cast_box_from_any()496 fn cast_box_from_any() {
497 let ts = Box::new(TestStruct);
498 let st: Box<dyn Any> = ts;
499 let debug = st.cast::<dyn Debug>();
500 assert!(debug.is_ok());
501 }
502
503 #[test]
cast_rc_from_any()504 fn cast_rc_from_any() {
505 let ts = Rc::new(TestStruct);
506 let st: Rc<dyn Any> = ts;
507 let debug = st.cast::<dyn Debug>();
508 assert!(debug.is_ok());
509 }
510
511 #[test]
cast_arc_from_any()512 fn cast_arc_from_any() {
513 let ts = Arc::new(TestStruct);
514 let st: Arc<dyn Any + Send + Sync> = ts;
515 let debug = st.cast::<dyn Debug>();
516 assert!(debug.is_ok());
517 }
518
519 #[test]
impls_ref()520 fn impls_ref() {
521 let ts = TestStruct;
522 let st: &dyn SourceTrait = &ts;
523 assert!(st.impls::<dyn Debug>());
524 }
525
526 #[test]
impls_mut()527 fn impls_mut() {
528 let mut ts = TestStruct;
529 let st: &mut dyn SourceTrait = &mut ts;
530 assert!((*st).impls::<dyn Debug>());
531 }
532
533 #[test]
impls_box()534 fn impls_box() {
535 let ts = Box::new(TestStruct);
536 let st: Box<dyn SourceTrait> = ts;
537 assert!((*st).impls::<dyn Debug>());
538 }
539
540 #[test]
impls_rc()541 fn impls_rc() {
542 let ts = Rc::new(TestStruct);
543 let st: Rc<dyn SourceTrait> = ts;
544 assert!((*st).impls::<dyn Debug>());
545 }
546
547 #[test]
impls_arc()548 fn impls_arc() {
549 let ts = Arc::new(TestStruct);
550 let st: Arc<dyn SourceTrait> = ts;
551 assert!((*st).impls::<dyn Debug>());
552 }
553
554 #[test]
impls_not_ref()555 fn impls_not_ref() {
556 let ts = TestStruct;
557 let st: &dyn SourceTrait = &ts;
558 assert!(!st.impls::<dyn Display>());
559 }
560
561 #[test]
impls_not_mut()562 fn impls_not_mut() {
563 let mut ts = TestStruct;
564 let st: &mut dyn Any = &mut ts;
565 assert!(!(*st).impls::<dyn Display>());
566 }
567
568 #[test]
impls_not_box()569 fn impls_not_box() {
570 let ts = Box::new(TestStruct);
571 let st: Box<dyn SourceTrait> = ts;
572 assert!(!st.impls::<dyn Display>());
573 }
574
575 #[test]
impls_not_rc()576 fn impls_not_rc() {
577 let ts = Rc::new(TestStruct);
578 let st: Rc<dyn SourceTrait> = ts;
579 assert!(!(*st).impls::<dyn Display>());
580 }
581
582 #[test]
impls_not_arc()583 fn impls_not_arc() {
584 let ts = Arc::new(TestStruct);
585 let st: Arc<dyn SourceTrait> = ts;
586 assert!(!(*st).impls::<dyn Display>());
587 }
588 }
589