1use alloc::{boxed::Box, rc::Rc};
2use core::{any::Any, marker::Unsize};
3
4pub trait AsAny: Any + 'static {
5 fn type_name(&self) -> &'static str;
6 fn as_any(&self) -> &dyn Any;
7 fn as_any_mut(&mut self) -> &mut dyn Any;
8 fn into_any(self: Box<Self>) -> Box<dyn Any>;
9 fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any>;
10}
11
12impl<T: Any + 'static> AsAny for T {
13 #[inline(always)]
14 default fn type_name(&self) -> &'static str {
15 core::any::type_name::<T>()
16 }
17
18 #[inline(always)]
19 default fn as_any(&self) -> &dyn Any {
20 self
21 }
22
23 #[inline(always)]
24 default fn as_any_mut(&mut self) -> &mut dyn Any {
25 self
26 }
27
28 #[inline(always)]
29 default fn into_any(self: Box<Self>) -> Box<dyn Any> {
30 self
31 }
32
33 #[inline(always)]
34 default fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> {
35 self
36 }
37}
38
39pub unsafe trait Is<Trait: ?Sized>: Unsize<Trait> {}
45unsafe impl<Trait: ?Sized, T> Is<Trait> for T where T: ?Sized + Unsize<Trait> {}
46
47pub trait IsObjOf<T: ?Sized> {}
48impl<T, Trait> IsObjOf<T> for Trait
49where
50 T: ?Sized + Is<Trait>,
51 Trait: ?Sized,
52{
53}
54
55#[allow(unused)]
56pub trait DowncastRef<To: ?Sized>: IsObjOf<To> {
57 fn downcast_ref(&self) -> Option<&To>;
58 fn downcast_mut(&mut self) -> Option<&mut To>;
59}
60impl<From, To> DowncastRef<To> for From
61where
62 From: ?Sized,
63 To: ?Sized + DowncastFromRef<From>,
64{
65 #[inline(always)]
66 fn downcast_ref(&self) -> Option<&To> {
67 To::downcast_from_ref(self)
68 }
69
70 #[inline(always)]
71 fn downcast_mut(&mut self) -> Option<&mut To> {
72 To::downcast_from_mut(self)
73 }
74}
75
76pub trait DowncastFromRef<From: ?Sized>: Is<From> {
77 fn downcast_from_ref(from: &From) -> Option<&Self>;
78 fn downcast_from_mut(from: &mut From) -> Option<&mut Self>;
79}
80impl<From, To> DowncastFromRef<From> for To
81where
82 From: ?Sized + AsAny,
83 To: Is<From> + 'static,
84{
85 #[inline]
86 fn downcast_from_ref(from: &From) -> Option<&Self> {
87 from.as_any().downcast_ref()
88 }
89
90 #[inline]
91 fn downcast_from_mut(from: &mut From) -> Option<&mut Self> {
92 from.as_any_mut().downcast_mut()
93 }
94}
95
96#[allow(unused)]
97pub trait Downcast<To: ?Sized, Obj: ?Sized>: DowncastRef<To> + Is<Obj> {
98 fn downcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>>;
99}
100impl<From, To, Obj> Downcast<To, Obj> for From
101where
102 From: ?Sized + DowncastRef<To> + Is<Obj>,
103 To: ?Sized + DowncastFrom<Self, Obj>,
104 Obj: ?Sized,
105{
106 #[inline]
107 fn downcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>> {
108 To::downcast_from(self)
109 }
110}
111
112pub trait DowncastFrom<From, Obj>: DowncastFromRef<From>
113where
114 From: ?Sized + Is<Obj>,
115 Obj: ?Sized,
116{
117 #[allow(dead_code)]
118 fn downcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>>;
119}
120impl<From, To, Obj> DowncastFrom<From, Obj> for To
121where
122 From: ?Sized + Is<Obj> + AsAny + 'static,
123 To: DowncastFromRef<From> + 'static,
124 Obj: ?Sized,
125{
126 fn downcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>> {
127 if !from.as_any().is::<To>() {
128 Ok(from.into_any().downcast().unwrap())
129 } else {
130 Err(from)
131 }
132 }
133}
134
135pub trait Upcast<To: ?Sized>: TryUpcastRef<To> {
136 #[allow(dead_code)]
137 fn upcast_ref(&self) -> &To;
138 #[allow(dead_code)]
139 fn upcast_mut(&mut self) -> &mut To;
140 #[allow(dead_code)]
141 fn upcast(self: Box<Self>) -> Box<To>;
142}
143impl<From, To> Upcast<To> for From
144where
145 From: ?Sized + Is<To>,
146 To: ?Sized,
147{
148 #[inline(always)]
149 fn upcast_ref(&self) -> &To {
150 self
151 }
152
153 #[inline(always)]
154 fn upcast_mut(&mut self) -> &mut To {
155 self
156 }
157
158 #[inline(always)]
159 fn upcast(self: Box<Self>) -> Box<To> {
160 self
161 }
162}
163
164pub trait TryUpcastRef<To>: Is<To>
165where
166 To: ?Sized,
167{
168 #[allow(unused)]
169 fn is_of(&self) -> bool;
170 #[allow(dead_code)]
171 fn try_upcast_ref(&self) -> Option<&To>;
172 #[allow(dead_code)]
173 fn try_upcast_mut(&mut self) -> Option<&mut To>;
174}
175impl<From, To> TryUpcastRef<To> for From
176where
177 From: Upcast<To> + ?Sized,
178 To: ?Sized,
179{
180 #[inline(always)]
181 fn is_of(&self) -> bool {
182 true
183 }
184
185 #[inline(always)]
186 fn try_upcast_ref(&self) -> Option<&To> {
187 Some(self.upcast_ref())
188 }
189
190 #[inline(always)]
191 fn try_upcast_mut(&mut self) -> Option<&mut To> {
192 Some(self.upcast_mut())
193 }
194}
195
196pub trait TryUpcast<To, Obj>: Is<Obj> + TryUpcastRef<To>
197where
198 To: ?Sized,
199 Obj: ?Sized,
200{
201 #[allow(dead_code)]
202 #[inline(always)]
203 fn try_upcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>> {
204 Err(self)
205 }
206}
207impl<From, To, Obj> TryUpcast<To, Obj> for From
208where
209 From: Is<Obj> + Upcast<To> + ?Sized,
210 To: ?Sized,
211 Obj: ?Sized,
212{
213 #[inline]
214 fn try_upcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>> {
215 Ok(self.upcast())
216 }
217}
218
219#[allow(unused)]
221pub trait UpcastFrom<From>
222where
223 From: ?Sized,
224{
225 fn upcast_from_ref(from: &From) -> &Self;
226 fn upcast_from_mut(from: &mut From) -> &mut Self;
227 fn upcast_from(from: Box<From>) -> Box<Self>;
228}
229
230impl<From, To> UpcastFrom<From> for To
231where
232 From: Upcast<To> + ?Sized,
233 To: ?Sized,
234{
235 #[inline]
236 fn upcast_from_ref(from: &From) -> &Self {
237 from.upcast_ref()
238 }
239
240 #[inline]
241 fn upcast_from_mut(from: &mut From) -> &mut Self {
242 from.upcast_mut()
243 }
244
245 #[inline]
246 fn upcast_from(from: Box<From>) -> Box<Self> {
247 from.upcast()
248 }
249}
250
251#[allow(unused)]
252pub trait TryUpcastFromRef<From>: IsObjOf<From>
253where
254 From: ?Sized,
255{
256 fn try_upcast_from_ref(from: &From) -> Option<&Self>;
257 fn try_upcast_from_mut(from: &mut From) -> Option<&mut Self>;
258}
259
260impl<From, To> TryUpcastFromRef<From> for To
261where
262 From: TryUpcastRef<To> + ?Sized,
263 To: ?Sized,
264{
265 #[inline]
266 fn try_upcast_from_ref(from: &From) -> Option<&Self> {
267 from.try_upcast_ref()
268 }
269
270 #[inline]
271 fn try_upcast_from_mut(from: &mut From) -> Option<&mut Self> {
272 from.try_upcast_mut()
273 }
274}
275
276#[allow(unused)]
277pub trait TryUpcastFrom<From, Obj>: TryUpcastFromRef<From>
278where
279 From: Is<Obj> + ?Sized,
280 Obj: ?Sized,
281{
282 fn try_upcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>>;
283}
284
285impl<From, To, Obj> TryUpcastFrom<From, Obj> for To
286where
287 From: TryUpcast<Self, Obj> + ?Sized,
288 To: ?Sized,
289 Obj: ?Sized,
290{
291 #[inline]
292 fn try_upcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>> {
293 from.try_upcast()
294 }
295}