intertrait/
lib.rs

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
59use std::any::{Any, TypeId};
60use std::collections::HashMap;
61use std::rc::Rc;
62use std::sync::Arc;
63
64use linkme::distributed_slice;
65use once_cell::sync::Lazy;
66
67pub use intertrait_macros::*;
68
69use crate::hasher::BuildFastHasher;
70
71pub mod cast;
72mod hasher;
73
74#[doc(hidden)]
75pub type BoxedCaster = Box<dyn Any + Send + Sync>;
76
77#[cfg(doctest)]
78doc_comment::doctest!("../README.md");
79
80/// A distributed slice gathering constructor functions for [`Caster<T>`]s.
81///
82/// A constructor function returns `TypeId` of a concrete type involved in the casting
83/// and a `Box` of a trait object backed by a [`Caster<T>`].
84///
85/// [`Caster<T>`]: ./struct.Caster.html
86#[doc(hidden)]
87#[distributed_slice]
88pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..];
89
90/// A `HashMap` mapping `TypeId` of a [`Caster<T>`] to an instance of it.
91///
92/// [`Caster<T>`]: ./struct.Caster.html
93static CASTER_MAP: Lazy<HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>> =
94    Lazy::new(|| {
95        CASTERS
96            .iter()
97            .map(|f| {
98                let (type_id, caster) = f();
99                ((type_id, (*caster).type_id()), caster)
100            })
101            .collect()
102    });
103
104fn cast_arc_panic<T: ?Sized + 'static>(_: Arc<dyn Any + Sync + Send>) -> Arc<T> {
105    panic!("Prepend [sync] to the list of target traits for Sync + Send types")
106}
107
108/// A `Caster` knows how to cast a reference to or `Box` of a trait object for `Any`
109/// to a trait object of trait `T`. Each `Caster` instance is specific to a concrete type.
110/// That is, it knows how to cast to single specific trait implemented by single specific type.
111///
112/// An implementation of a trait for a concrete type doesn't need to manually provide
113/// a `Caster`. Instead attach `#[cast_to]` to the `impl` block.
114#[doc(hidden)]
115pub struct Caster<T: ?Sized + 'static> {
116    /// Casts an immutable reference to a trait object for `Any` to a reference
117    /// to a trait object for trait `T`.
118    pub cast_ref: fn(from: &dyn Any) -> &T,
119
120    /// Casts a mutable reference to a trait object for `Any` to a mutable reference
121    /// to a trait object for trait `T`.
122    pub cast_mut: fn(from: &mut dyn Any) -> &mut T,
123
124    /// Casts a `Box` holding a trait object for `Any` to another `Box` holding a trait object
125    /// for trait `T`.
126    pub cast_box: fn(from: Box<dyn Any>) -> Box<T>,
127
128    /// Casts an `Rc` holding a trait object for `Any` to another `Rc` holding a trait object
129    /// for trait `T`.
130    pub cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
131
132    /// Casts an `Arc` holding a trait object for `Any + Sync + Send + 'static`
133    /// to another `Arc` holding a trait object for trait `T`.
134    pub cast_arc: fn(from: Arc<dyn Any + Sync + Send + 'static>) -> Arc<T>,
135}
136
137impl<T: ?Sized + 'static> Caster<T> {
138    pub fn new(
139        cast_ref: fn(from: &dyn Any) -> &T,
140        cast_mut: fn(from: &mut dyn Any) -> &mut T,
141        cast_box: fn(from: Box<dyn Any>) -> Box<T>,
142        cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
143    ) -> Caster<T> {
144        Caster::<T> {
145            cast_ref,
146            cast_mut,
147            cast_box,
148            cast_rc,
149            cast_arc: cast_arc_panic,
150        }
151    }
152
153    pub fn new_sync(
154        cast_ref: fn(from: &dyn Any) -> &T,
155        cast_mut: fn(from: &mut dyn Any) -> &mut T,
156        cast_box: fn(from: Box<dyn Any>) -> Box<T>,
157        cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
158        cast_arc: fn(from: Arc<dyn Any + Sync + Send>) -> Arc<T>,
159    ) -> Caster<T> {
160        Caster::<T> {
161            cast_ref,
162            cast_mut,
163            cast_box,
164            cast_rc,
165            cast_arc,
166        }
167    }
168}
169
170/// Returns a `Caster<S, T>` from a concrete type `S` to a trait `T` implemented by it.
171fn caster<T: ?Sized + 'static>(type_id: TypeId) -> Option<&'static Caster<T>> {
172    CASTER_MAP
173        .get(&(type_id, TypeId::of::<Caster<T>>()))
174        .and_then(|caster| caster.downcast_ref::<Caster<T>>())
175}
176
177/// `CastFrom` must be extended by a trait that wants to allow for casting into another trait.
178///
179/// It is used for obtaining a trait object for [`Any`] from a trait object for its sub-trait,
180/// and blanket implemented for all `Sized + Any + 'static` types.
181///
182/// # Examples
183/// ```ignore
184/// trait Source: CastFrom {
185///     ...
186/// }
187/// ```
188pub trait CastFrom: Any + 'static {
189    /// Returns a immutable reference to `Any`, which is backed by the type implementing this trait.
190    fn ref_any(&self) -> &dyn Any;
191
192    /// Returns a mutable reference to `Any`, which is backed by the type implementing this trait.
193    fn mut_any(&mut self) -> &mut dyn Any;
194
195    /// Returns a `Box` of `Any`, which is backed by the type implementing this trait.
196    fn box_any(self: Box<Self>) -> Box<dyn Any>;
197
198    /// Returns an `Rc` of `Any`, which is backed by the type implementing this trait.
199    fn rc_any(self: Rc<Self>) -> Rc<dyn Any>;
200}
201
202/// `CastFromSync` must be extended by a trait that is `Any + Sync + Send + 'static`
203/// and wants to allow for casting into another trait behind references and smart pointers
204/// especially including `Arc`.
205///
206/// It is used for obtaining a trait object for [`Any + Sync + Send + 'static`] from an object
207/// for its sub-trait, and blanket implemented for all `Sized + Sync + Send + 'static` types.
208///
209/// # Examples
210/// ```ignore
211/// trait Source: CastFromSync {
212///     ...
213/// }
214/// ```
215pub trait CastFromSync: CastFrom + Sync + Send + 'static {
216    fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>;
217}
218
219impl<T: Sized + Any + 'static> CastFrom for T {
220    fn ref_any(&self) -> &dyn Any {
221        self
222    }
223
224    fn mut_any(&mut self) -> &mut dyn Any {
225        self
226    }
227
228    fn box_any(self: Box<Self>) -> Box<dyn Any> {
229        self
230    }
231
232    fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
233        self
234    }
235}
236
237impl CastFrom for dyn Any + 'static {
238    fn ref_any(&self) -> &dyn Any {
239        self
240    }
241
242    fn mut_any(&mut self) -> &mut dyn Any {
243        self
244    }
245
246    fn box_any(self: Box<Self>) -> Box<dyn Any> {
247        self
248    }
249
250    fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
251        self
252    }
253}
254
255impl<T: Sized + Sync + Send + 'static> CastFromSync for T {
256    fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> {
257        self
258    }
259}
260
261impl CastFrom for dyn Any + Sync + Send + 'static {
262    fn ref_any(&self) -> &dyn Any {
263        self
264    }
265
266    fn mut_any(&mut self) -> &mut dyn Any {
267        self
268    }
269
270    fn box_any(self: Box<Self>) -> Box<dyn Any> {
271        self
272    }
273
274    fn rc_any(self: Rc<Self>) -> Rc<dyn Any> {
275        self
276    }
277}
278
279impl CastFromSync for dyn Any + Sync + Send + 'static {
280    fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> {
281        self
282    }
283}
284
285#[cfg(test)]
286mod tests {
287    use std::any::{Any, TypeId};
288    use std::fmt::{Debug, Display};
289
290    use linkme::distributed_slice;
291
292    use crate::{BoxedCaster, CastFromSync};
293
294    use super::cast::*;
295    use super::*;
296
297    #[distributed_slice(super::CASTERS)]
298    static TEST_CASTER: fn() -> (TypeId, BoxedCaster) = create_test_caster;
299
300    #[derive(Debug)]
301    struct TestStruct;
302
303    trait SourceTrait: CastFromSync {}
304
305    impl SourceTrait for TestStruct {}
306
307    fn create_test_caster() -> (TypeId, BoxedCaster) {
308        let type_id = TypeId::of::<TestStruct>();
309        let caster = Box::new(Caster::<dyn Debug> {
310            cast_ref: |from| from.downcast_ref::<TestStruct>().unwrap(),
311            cast_mut: |from| from.downcast_mut::<TestStruct>().unwrap(),
312            cast_box: |from| from.downcast::<TestStruct>().unwrap(),
313            cast_rc: |from| from.downcast::<TestStruct>().unwrap(),
314            cast_arc: |from| from.downcast::<TestStruct>().unwrap(),
315        });
316        (type_id, caster)
317    }
318
319    #[test]
320    fn cast_ref() {
321        let ts = TestStruct;
322        let st: &dyn SourceTrait = &ts;
323        let debug = st.cast::<dyn Debug>();
324        assert!(debug.is_some());
325    }
326
327    #[test]
328    fn cast_mut() {
329        let mut ts = TestStruct;
330        let st: &mut dyn SourceTrait = &mut ts;
331        let debug = st.cast::<dyn Debug>();
332        assert!(debug.is_some());
333    }
334
335    #[test]
336    fn cast_box() {
337        let ts = Box::new(TestStruct);
338        let st: Box<dyn SourceTrait> = ts;
339        let debug = st.cast::<dyn Debug>();
340        assert!(debug.is_ok());
341    }
342
343    #[test]
344    fn cast_rc() {
345        let ts = Rc::new(TestStruct);
346        let st: Rc<dyn SourceTrait> = ts;
347        let debug = st.cast::<dyn Debug>();
348        assert!(debug.is_ok());
349    }
350
351    #[test]
352    fn cast_arc() {
353        let ts = Arc::new(TestStruct);
354        let st: Arc<dyn SourceTrait> = ts;
355        let debug = st.cast::<dyn Debug>();
356        assert!(debug.is_ok());
357    }
358
359    #[test]
360    fn cast_ref_wrong() {
361        let ts = TestStruct;
362        let st: &dyn SourceTrait = &ts;
363        let display = st.cast::<dyn Display>();
364        assert!(display.is_none());
365    }
366
367    #[test]
368    fn cast_mut_wrong() {
369        let mut ts = TestStruct;
370        let st: &mut dyn SourceTrait = &mut ts;
371        let display = st.cast::<dyn Display>();
372        assert!(display.is_none());
373    }
374
375    #[test]
376    fn cast_box_wrong() {
377        let ts = Box::new(TestStruct);
378        let st: Box<dyn SourceTrait> = ts;
379        let display = st.cast::<dyn Display>();
380        assert!(display.is_err());
381    }
382
383    #[test]
384    fn cast_rc_wrong() {
385        let ts = Rc::new(TestStruct);
386        let st: Rc<dyn SourceTrait> = ts;
387        let display = st.cast::<dyn Display>();
388        assert!(display.is_err());
389    }
390
391    #[test]
392    fn cast_arc_wrong() {
393        let ts = Arc::new(TestStruct);
394        let st: Arc<dyn SourceTrait> = ts;
395        let display = st.cast::<dyn Display>();
396        assert!(display.is_err());
397    }
398
399    #[test]
400    fn cast_ref_from_any() {
401        let ts = TestStruct;
402        let st: &dyn Any = &ts;
403        let debug = st.cast::<dyn Debug>();
404        assert!(debug.is_some());
405    }
406
407    #[test]
408    fn cast_mut_from_any() {
409        let mut ts = TestStruct;
410        let st: &mut dyn Any = &mut ts;
411        let debug = st.cast::<dyn Debug>();
412        assert!(debug.is_some());
413    }
414
415    #[test]
416    fn cast_box_from_any() {
417        let ts = Box::new(TestStruct);
418        let st: Box<dyn Any> = ts;
419        let debug = st.cast::<dyn Debug>();
420        assert!(debug.is_ok());
421    }
422
423    #[test]
424    fn cast_rc_from_any() {
425        let ts = Rc::new(TestStruct);
426        let st: Rc<dyn Any> = ts;
427        let debug = st.cast::<dyn Debug>();
428        assert!(debug.is_ok());
429    }
430
431    #[test]
432    fn cast_arc_from_any() {
433        let ts = Arc::new(TestStruct);
434        let st: Arc<dyn Any + Send + Sync> = ts;
435        let debug = st.cast::<dyn Debug>();
436        assert!(debug.is_ok());
437    }
438
439    #[test]
440    fn impls_ref() {
441        let ts = TestStruct;
442        let st: &dyn SourceTrait = &ts;
443        assert!(st.impls::<dyn Debug>());
444    }
445
446    #[test]
447    fn impls_mut() {
448        let mut ts = TestStruct;
449        let st: &mut dyn SourceTrait = &mut ts;
450        assert!((*st).impls::<dyn Debug>());
451    }
452
453    #[test]
454    fn impls_box() {
455        let ts = Box::new(TestStruct);
456        let st: Box<dyn SourceTrait> = ts;
457        assert!((*st).impls::<dyn Debug>());
458    }
459
460    #[test]
461    fn impls_rc() {
462        let ts = Rc::new(TestStruct);
463        let st: Rc<dyn SourceTrait> = ts;
464        assert!((*st).impls::<dyn Debug>());
465    }
466
467    #[test]
468    fn impls_arc() {
469        let ts = Arc::new(TestStruct);
470        let st: Arc<dyn SourceTrait> = ts;
471        assert!((*st).impls::<dyn Debug>());
472    }
473
474    #[test]
475    fn impls_not_ref() {
476        let ts = TestStruct;
477        let st: &dyn SourceTrait = &ts;
478        assert!(!st.impls::<dyn Display>());
479    }
480
481    #[test]
482    fn impls_not_mut() {
483        let mut ts = TestStruct;
484        let st: &mut dyn Any = &mut ts;
485        assert!(!(*st).impls::<dyn Display>());
486    }
487
488    #[test]
489    fn impls_not_box() {
490        let ts = Box::new(TestStruct);
491        let st: Box<dyn SourceTrait> = ts;
492        assert!(!st.impls::<dyn Display>());
493    }
494
495    #[test]
496    fn impls_not_rc() {
497        let ts = Rc::new(TestStruct);
498        let st: Rc<dyn SourceTrait> = ts;
499        assert!(!(*st).impls::<dyn Display>());
500    }
501
502    #[test]
503    fn impls_not_arc() {
504        let ts = Arc::new(TestStruct);
505        let st: Arc<dyn SourceTrait> = ts;
506        assert!(!(*st).impls::<dyn Display>());
507    }
508}