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}