calimero_primitives/
reflect.rs

1use core::any::{type_name, TypeId};
2use core::marker::PhantomData;
3use core::mem::transmute;
4use core::ptr;
5use std::rc::Rc;
6use std::sync::Arc;
7
8// https://github.com/sagebind/castaway/pull/14
9
10/// Produces type IDs that are compatible with `TypeId::of::<T>`, but without
11/// `T: 'static` bound.
12fn non_static_type_id<T: ?Sized>() -> TypeId {
13    trait NonStaticAny {
14        fn get_type_id(&self) -> TypeId
15        where
16            Self: 'static;
17    }
18
19    impl<T: ?Sized> NonStaticAny for PhantomData<T> {
20        fn get_type_id(&self) -> TypeId
21        where
22            Self: 'static,
23        {
24            TypeId::of::<T>()
25        }
26    }
27
28    let phantom_data = PhantomData::<T>;
29    NonStaticAny::get_type_id(unsafe {
30        transmute::<&dyn NonStaticAny, &(dyn NonStaticAny + 'static)>(&phantom_data)
31    })
32}
33
34pub trait Reflect {
35    fn type_id(&self) -> TypeId {
36        non_static_type_id::<Self>()
37    }
38
39    fn type_name(&self) -> &'static str {
40        type_name::<Self>()
41    }
42
43    fn as_dyn_ref<'a>(&self) -> &(dyn Reflect + 'a)
44    where
45        Self: 'a;
46
47    fn as_dyn_mut<'a>(&mut self) -> &mut (dyn Reflect + 'a)
48    where
49        Self: 'a;
50
51    fn as_dyn_box<'a>(self: Box<Self>) -> Box<dyn Reflect + 'a>
52    where
53        Self: 'a;
54
55    fn as_dyn_rc<'a>(self: Rc<Self>) -> Rc<dyn Reflect + 'a>
56    where
57        Self: 'a;
58
59    fn as_dyn_arc<'a>(self: Arc<Self>) -> Arc<dyn Reflect + 'a>
60    where
61        Self: 'a;
62}
63
64impl<T> Reflect for T {
65    fn as_dyn_ref<'a>(&self) -> &(dyn Reflect + 'a)
66    where
67        T: 'a,
68    {
69        self
70    }
71
72    fn as_dyn_mut<'a>(&mut self) -> &mut (dyn Reflect + 'a)
73    where
74        T: 'a,
75    {
76        self
77    }
78
79    fn as_dyn_box<'a>(self: Box<Self>) -> Box<dyn Reflect + 'a>
80    where
81        T: 'a,
82    {
83        self
84    }
85
86    fn as_dyn_rc<'a>(self: Rc<Self>) -> Rc<dyn Reflect + 'a>
87    where
88        T: 'a,
89    {
90        self
91    }
92
93    fn as_dyn_arc<'a>(self: Arc<Self>) -> Arc<dyn Reflect + 'a>
94    where
95        T: 'a,
96    {
97        self
98    }
99}
100
101pub trait ReflectExt: Reflect {
102    fn is<T: Reflect + ?Sized>(&self) -> bool {
103        self.type_id() == non_static_type_id::<T>()
104    }
105
106    fn type_id() -> TypeId {
107        non_static_type_id::<Self>()
108    }
109
110    fn downcast_ref<T: Reflect>(&self) -> Option<&T> {
111        if self.is::<T>() {
112            return Some(unsafe { &*ptr::from_ref(self).cast() });
113        }
114
115        None
116    }
117
118    fn downcast_mut<T: Reflect>(&mut self) -> Option<&mut T> {
119        if self.is::<T>() {
120            return Some(unsafe { &mut *ptr::from_mut(self).cast() });
121        }
122
123        None
124    }
125
126    fn downcast_box<T: Reflect>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
127        if (&*self).is::<T>() {
128            return Ok(unsafe { Box::from_raw(Box::into_raw(self).cast()) });
129        }
130
131        Err(self)
132    }
133
134    fn downcast_rc<T: Reflect>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>> {
135        if (&*self).is::<T>() {
136            return Ok(unsafe { Rc::from_raw(Rc::into_raw(self).cast()) });
137        }
138
139        Err(self)
140    }
141
142    fn downcast_arc<T: Reflect>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>> {
143        if (&*self).is::<T>() {
144            return Ok(unsafe { Arc::from_raw(Arc::into_raw(self).cast()) });
145        }
146
147        Err(self)
148    }
149}
150
151impl<T: Reflect + ?Sized> ReflectExt for T {}