1use 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#[doc(hidden)]
87#[distributed_slice]
88pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..];
89
90static 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#[doc(hidden)]
115pub struct Caster<T: ?Sized + 'static> {
116 pub cast_ref: fn(from: &dyn Any) -> &T,
119
120 pub cast_mut: fn(from: &mut dyn Any) -> &mut T,
123
124 pub cast_box: fn(from: Box<dyn Any>) -> Box<T>,
127
128 pub cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>,
131
132 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
170fn 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
177pub trait CastFrom: Any + 'static {
189 fn ref_any(&self) -> &dyn Any;
191
192 fn mut_any(&mut self) -> &mut dyn Any;
194
195 fn box_any(self: Box<Self>) -> Box<dyn Any>;
197
198 fn rc_any(self: Rc<Self>) -> Rc<dyn Any>;
200}
201
202pub 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}