dbsp/dynamic/downcast.rs
1use std::any::{Any, TypeId};
2
3/// Trait for types that return a reference to self as `dyn Any`.
4///
5/// Used to construct [`DowncastTrait`].
6pub trait AsAny: 'static {
7 fn as_any(&self) -> &dyn Any;
8}
9
10impl<T: 'static> AsAny for T {
11 fn as_any(&self) -> &dyn Any {
12 self
13 }
14}
15
16/// A trait for trait objects that can be downcast to a reference
17/// to the concrete type they wrap.
18// NOTE: We don't auto-derive this trait for all types that satisfy
19// the bound. Instead it needs to be derived manually for trait
20// object types only.
21pub trait DowncastTrait: AsAny {
22 /// Cast trait object reference to a reference to a concrete type `T`.
23 ///
24 /// Panics if the inner value of `self` does not have type `T`.
25 #[inline]
26 fn downcast_checked<T: AsAny>(&self) -> &T {
27 assert_eq!(
28 self.as_any().type_id(),
29 TypeId::of::<T>(),
30 "downcast_checked from incorrect type to {}",
31 std::any::type_name::<T>()
32 );
33 unsafe { &*(self as *const _ as *const T) }
34 }
35
36 /// Cast trait object reference to a mutable reference to a concrete type `T`.
37 ///
38 /// Panics if the inner value of `self` does not have type `T`.
39 #[inline]
40 fn downcast_mut_checked<T: AsAny>(&mut self) -> &mut T {
41 assert_eq!(
42 (self as &Self).as_any().type_id(),
43 TypeId::of::<T>(),
44 "downcast_mut_checked from incorrect type to {}",
45 std::any::type_name::<T>()
46 );
47 unsafe { &mut *(self as *mut _ as *mut T) }
48 }
49
50 /// Cast trait object reference to a reference to a concrete type `T`, eliding type checking.
51 ///
52 /// # Safety
53 ///
54 /// The inner value of `self` must be of type `T`.
55 #[inline]
56 unsafe fn downcast<T: AsAny>(&self) -> &T {
57 debug_assert_eq!(
58 self.as_any().type_id(),
59 TypeId::of::<T>(),
60 "downcast from incorrect type to {}",
61 std::any::type_name::<T>()
62 );
63 &*(self as *const _ as *const T)
64 }
65
66 /// Cast trait object reference to a reference to a mutable reference to concrete type `T`,
67 /// eliding type checking.
68 ///
69 /// # Safety
70 ///
71 /// The inner value of `self` must be of type `T`.
72 #[inline]
73 unsafe fn downcast_mut<T: AsAny>(&mut self) -> &mut T {
74 debug_assert_eq!(
75 (self as &Self).as_any().type_id(),
76 TypeId::of::<T>(),
77 "downcast_mut from incorrect type {} to {}",
78 std::any::type_name::<Self>(),
79 std::any::type_name::<T>()
80 );
81 &mut *(self as *mut _ as *mut T)
82 }
83}