1 #![cfg_attr(not(feature = "std"), no_std)]
2 
3 #[cfg(not(feature = "std"))]
4 mod std {
5     pub use core::*;
6 }
7 
8 use std::any::{Any as StdAny, TypeId, type_name};
9 use std::fmt::{self, Debug, Display};
10 
11 #[cfg(feature = "std")]
12 use std::{error::Error, rc::Rc, sync::Arc};
13 
14 // ++++++++++++++++++++ Any ++++++++++++++++++++
15 
16 pub trait Any: StdAny {
17     #[doc(hidden)]
as_any(&self) -> &dyn StdAny18     fn as_any(&self) -> &dyn StdAny;
19 
20     #[doc(hidden)]
as_any_mut(&mut self) -> &mut dyn StdAny21     fn as_any_mut(&mut self) -> &mut dyn StdAny;
22 
23     #[doc(hidden)]
24     #[cfg(feature = "std")]
into_any(self: Box<Self>) -> Box<dyn StdAny>25     fn into_any(self: Box<Self>) -> Box<dyn StdAny>;
26 
27     #[doc(hidden)]
28     #[cfg(feature = "std")]
into_any_rc(self: Rc<Self>) -> Rc<dyn StdAny>29     fn into_any_rc(self: Rc<Self>) -> Rc<dyn StdAny>;
30 
type_name(&self) -> &'static str31     fn type_name(&self) -> &'static str;
32 }
33 
34 impl<T> Any for T where T: StdAny {
35     #[doc(hidden)]
as_any(&self) -> &dyn StdAny36     fn as_any(&self) -> &dyn StdAny { self }
37 
38     #[doc(hidden)]
as_any_mut(&mut self) -> &mut dyn StdAny39     fn as_any_mut(&mut self) -> &mut dyn StdAny { self }
40 
41     #[cfg(feature = "std")]
into_any(self: Box<Self>) -> Box<dyn StdAny>42     fn into_any(self: Box<Self>) -> Box<dyn StdAny> { self }
43 
44     #[cfg(feature = "std")]
into_any_rc(self: Rc<Self>) -> Rc<dyn StdAny>45     fn into_any_rc(self: Rc<Self>) -> Rc<dyn StdAny> { self }
46 
type_name(&self) -> &'static str47     fn type_name(&self) -> &'static str { type_name::<Self>() }
48 }
49 
50 #[cfg(feature = "std")]
51 pub trait AnySync: Any + Send + Sync {
into_any_arc(self: Arc<Self>) -> Arc<dyn StdAny + Send + Sync>52     fn into_any_arc(self: Arc<Self>) -> Arc<dyn StdAny + Send + Sync>;
53 }
54 
55 #[cfg(feature = "std")]
56 impl<T> AnySync for T where T: Any + Send + Sync {
into_any_arc(self: Arc<Self>) -> Arc<dyn StdAny + Send + Sync>57     fn into_any_arc(self: Arc<Self>) -> Arc<dyn StdAny + Send + Sync> { self }
58 }
59 
60 // ++++++++++++++++++++ TypeMismatch ++++++++++++++++++++
61 
62 #[derive(Debug, Clone, Copy)]
63 pub struct TypeMismatch {
64     pub expected: &'static str,
65     pub found: &'static str,
66 }
67 
68 impl TypeMismatch {
new<T, O>(found_obj: &O) -> Self where T: Any + ?Sized, O: Any + ?Sized69     pub fn new<T, O>(found_obj: &O) -> Self
70         where T: Any + ?Sized, O: Any + ?Sized
71     {
72         TypeMismatch {
73             expected: type_name::<T>(),
74             found: found_obj.type_name(),
75         }
76     }
77 }
78 
79 impl Display for TypeMismatch {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result80     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
81         write!(fmt, "Type mismatch: Expected '{}', found '{}'!", self.expected, self.found)
82     }
83 }
84 
85 #[cfg(feature = "std")]
86 impl Error for TypeMismatch {}
87 
88 // ++++++++++++++++++++ DowncastError ++++++++++++++++++++
89 
90 pub struct DowncastError<O> {
91     mismatch: TypeMismatch,
92     object: O,
93 }
94 
95 impl<O> DowncastError<O> {
new(mismatch: TypeMismatch, object: O) -> Self96     pub fn new(mismatch: TypeMismatch, object: O) -> Self {
97         Self{ mismatch, object }
98     }
type_mismatch(&self) -> TypeMismatch99     pub fn type_mismatch(&self) -> TypeMismatch { self.mismatch }
into_object(self) -> O100     pub fn into_object(self) -> O { self.object }
101 }
102 
103 impl<O> Debug for DowncastError<O> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result104     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
105         fmt.debug_struct("DowncastError")
106             .field("mismatch", &self.mismatch)
107             .finish()
108     }
109 }
110 
111 impl<O> Display for DowncastError<O> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result112     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
113         Display::fmt(&self.mismatch, fmt)
114     }
115 }
116 
117 #[cfg(feature = "std")]
118 impl<O> Error for DowncastError<O> {}
119 
120 // ++++++++++++++++++++ Downcast ++++++++++++++++++++
121 
122 pub trait Downcast<T>: Any
123     where T: Any
124 {
is_type(&self) -> bool125     fn is_type(&self) -> bool { self.type_id() == TypeId::of::<T>() }
126 
downcast_ref(&self) -> Result<&T, TypeMismatch>127     fn downcast_ref(&self) -> Result<&T, TypeMismatch> {
128         if self.is_type() {
129             Ok(self.as_any().downcast_ref().unwrap())
130         } else {
131             Err(TypeMismatch::new::<T, Self>(self))
132         }
133     }
134 
downcast_mut(&mut self) -> Result<&mut T, TypeMismatch>135     fn downcast_mut(&mut self) -> Result<&mut T, TypeMismatch> {
136         if self.is_type() {
137             Ok(self.as_any_mut().downcast_mut().unwrap())
138         } else {
139             Err(TypeMismatch::new::<T, Self>(self))
140         }
141     }
142 
143     #[cfg(feature = "std")]
downcast(self: Box<Self>) -> Result<Box<T>, DowncastError<Box<Self>>>144     fn downcast(self: Box<Self>) -> Result<Box<T>, DowncastError<Box<Self>>> {
145         if self.is_type() {
146             Ok(self.into_any().downcast().unwrap())
147         } else {
148             let mismatch = TypeMismatch::new::<T, Self>(&*self);
149             Err(DowncastError::new(mismatch, self))
150         }
151     }
152 
153     #[cfg(feature = "std")]
downcast_rc(self: Rc<Self>) -> Result<Rc<T>, DowncastError<Rc<Self>>>154     fn downcast_rc(self: Rc<Self>) -> Result<Rc<T>, DowncastError<Rc<Self>>> {
155         if self.is_type() {
156             Ok(self.into_any_rc().downcast().unwrap())
157         } else {
158             let mismatch = TypeMismatch::new::<T, Self>(&*self);
159             Err(DowncastError::new(mismatch, self))
160         }
161     }
162 }
163 
164 #[cfg(feature = "std")]
165 pub trait DowncastSync<T>: Downcast<T> + AnySync
166     where T: AnySync
167 {
downcast_arc(self: Arc<Self>) -> Result<Arc<T>, DowncastError<Arc<Self>>>168     fn downcast_arc(self: Arc<Self>) -> Result<Arc<T>, DowncastError<Arc<Self>>> {
169         if self.is_type() {
170             Ok(self.into_any_arc().downcast().unwrap())
171         } else {
172             let mismatch = TypeMismatch::new::<T, Self>(&*self);
173             Err(DowncastError::new(mismatch, self))
174         }
175     }
176 }
177 
178 // ++++++++++++++++++++ macros ++++++++++++++++++++
179 
180 #[doc(hidden)]
181 pub mod _std {
182     #[cfg(feature = "std")]
183     pub use std::*;
184     #[cfg(not(feature = "std"))]
185     pub use core::*;
186 }
187 
188 /// Implements [`Downcast`](trait.Downcast.html) for your trait-object-type.
189 ///
190 /// ```ignore
191 /// impl_downcast!(Foo);
192 /// impl_downcast!(<B> Foo<B> where B: Bar);
193 /// impl_downcast!(<B> Foo<Bar = B>);
194 /// ```
195 ///
196 /// expands to
197 ///
198 /// ```ignore
199 /// impl<T> Downcast<T> for Foo
200 ///     where T: Any
201 /// {}
202 ///
203 /// impl<T, B> Downcast<T> for Foo<B>
204 ///     where T: Any, B: Bar
205 /// {}
206 ///
207 /// impl<T, B> Downcast<T> for Foo<Bar = B>
208 ///     where T: Any
209 /// {}
210 /// ```
211 #[macro_export]
212 macro_rules! impl_downcast {
213     (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
214         impl<_T, $($params),+> $crate::Downcast<_T> for $base
215             where _T: $crate::Any, $($params: 'static,)* $($($bounds)+)*
216         {}
217     };
218     ($base:ty) => {
219         impl<_T> $crate::Downcast<_T> for $base
220             where _T: $crate::Any
221         {}
222     };
223 }
224 
225 /// Implements [`Downcast`](trait.Downcast.html) and [`DowncastSync`](trait.DowncastSync.html) for your trait-object-type.
226 #[cfg(feature = "std")]
227 #[macro_export]
228 macro_rules! impl_downcast_sync {
229     (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
230         impl<_T, $($params),+> $crate::Downcast<_T> for $base
231             where _T: $crate::Any, $($params: 'static,)* $($($bounds)+)*
232         {}
233 
234         impl<_T, $($params),+> $crate::DowncastSync<_T> for $base
235             where _T: $crate::AnySync, $($params: 'static,)* $($($bounds)+)*
236         {}
237     };
238     ($base:ty) => {
239         impl<_T> $crate::Downcast<_T> for $base
240             where _T: $crate::Any
241         {}
242 
243         impl<_T> $crate::DowncastSync<_T> for $base
244             where _T: $crate::AnySync
245         {}
246     };
247 }
248 
249 #[doc(hidden)]
250 #[macro_export]
251 macro_rules! downcast_methods_core {
252     (@items) => {
253         #[allow(unused, missing_docs)]
254         pub fn is<_T>(&self) -> bool
255             where _T: $crate::Any, Self: $crate::Downcast<_T>
256         {
257             $crate::Downcast::<_T>::is_type(self)
258         }
259 
260         #[allow(unused, missing_docs)]
261         pub fn downcast_ref<_T>(&self) -> $crate::_std::result::Result<&_T, $crate::TypeMismatch>
262             where _T: $crate::Any, Self: $crate::Downcast<_T>
263         {
264             $crate::Downcast::<_T>::downcast_ref(self)
265         }
266 
267         #[allow(unused, missing_docs)]
268         pub fn downcast_mut<_T>(&mut self) -> $crate::_std::result::Result<&mut _T, $crate::TypeMismatch>
269             where _T: $crate::Any, Self: $crate::Downcast<_T>
270         {
271             $crate::Downcast::<_T>::downcast_mut(self)
272         }
273     };
274     (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
275         impl<$($params),+> $base
276             where $($params: 'static,)* $($($bounds)+)*
277         {
278             $crate::downcast_methods_core!(@items);
279         }
280     };
281     ($base:ty) => {
282         impl $base {
283             $crate::downcast_methods_core!(@items);
284         }
285     };
286 }
287 
288 #[doc(hidden)]
289 #[macro_export]
290 macro_rules! downcast_methods_std {
291     (@items) => {
292         $crate::downcast_methods_core!(@items);
293 
294         #[allow(unused, missing_docs)]
295         pub fn downcast<_T>(self: $crate::_std::boxed::Box<Self>) -> $crate::_std::result::Result<$crate::_std::boxed::Box<_T>, $crate::DowncastError<$crate::_std::boxed::Box<Self>>>
296             where _T: $crate::Any, Self: $crate::Downcast<_T>
297         {
298             $crate::Downcast::<_T>::downcast(self)
299         }
300 
301         #[allow(unused, missing_docs)]
302         pub fn downcast_rc<_T>(self: $crate::_std::rc::Rc<Self>) -> $crate::_std::result::Result<$crate::_std::rc::Rc<_T>, $crate::DowncastError<$crate::_std::rc::Rc<Self>>>
303             where _T: $crate::Any, Self: $crate::Downcast<_T>
304         {
305             $crate::Downcast::<_T>::downcast_rc(self)
306         }
307     };
308     (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
309         impl<$($params),+> $base
310             $(where $($bounds)+)*
311         {
312             $crate::downcast_methods_std!(@items);
313         }
314     };
315     ($base:ty) => {
316         impl $base {
317             $crate::downcast_methods_std!(@items);
318         }
319     };
320 }
321 
322 #[doc(hidden)]
323 #[cfg(feature = "std")]
324 #[macro_export]
325 macro_rules! downcast_sync_methods {
326     (@items) => {
327         $crate::downcast_methods_std!(@items);
328 
329         #[allow(unused, missing_docs)]
330         pub fn downcast_arc<_T>(self: $crate::_std::sync::Arc<Self>) -> $crate::_std::result::Result<$crate::_std::sync::Arc<_T>, $crate::DowncastError<$crate::_std::sync::Arc<Self>>>
331             where _T: $crate::AnySync, Self: $crate::DowncastSync<_T>
332         {
333             $crate::DowncastSync::<_T>::downcast_arc(self)
334         }
335     };
336     (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => {
337         impl<$($params),+> $base
338             $(where $($bounds)+)*
339         {
340             $crate::downcast_sync_methods!(@items);
341         }
342     };
343     ($base:ty) => {
344         impl $base {
345             $crate::downcast_sync_methods!(@items);
346         }
347     };
348 }
349 
350 
351 /// Generate `downcast`-methods for your trait-object-type.
352 ///
353 /// ```ignore
354 /// downcast_methods!(Foo);
355 /// downcast_methods!(<B> Foo<B> where B: Bar);
356 /// downcast_methods!(<B> Foo<Bar = B>);
357 /// ```
358 ///
359 /// ```ignore
360 /// impl dyn Foo {
361 /// /* impl<B> dyn Foo<B> where B: Bar { */
362 /// /* impl<B> dyn Foo<Bar = B> { */
363 ///
364 ///     pub fn is<T>(&self) -> bool
365 ///         where T: Any, Self: Downcast<T>
366 ///     { ... }
367 ///
368 ///     pub fn downcast_ref<T>(&self) -> Result<&T, TypeMismatch>
369 ///         where T: Any, Self: Downcast<T>
370 ///     { ... }
371 ///
372 ///     pub fn downcast_mut<T>(&mut self) -> Result<&mut T, TypeMismatch>
373 ///         where T: Any, Self: Downcast<T>
374 ///     { ... }
375 /// }
376 /// ```
377 #[cfg(not(feature = "std"))]
378 #[macro_export]
379 macro_rules! downcast_methods {
380     ($($tt:tt)+) => { $crate::downcast_methods_core!($($tt)+); }
381 }
382 
383 /// Generate `downcast`-methods for your trait-object-type.
384 ///
385 /// ```ignore
386 /// downcast_methods!(Foo);
387 /// downcast_methods!(<B> Foo<B> where B: Bar);
388 /// downcast_methods!(<B> Foo<Bar = B>);
389 /// ```
390 ///
391 /// ```ignore
392 /// impl dyn Foo {
393 /// /* impl<B> dyn Foo<B> where B: Bar {  */
394 /// /* impl<B> dyn Foo<Bar = B> {  */
395 ///
396 ///     pub fn is<T>(&self) -> bool
397 ///         where T: Any, Self: Downcast<T>
398 ///     { ... }
399 ///
400 ///     pub fn downcast_ref<T>(&self) -> Result<&T, TypeMismatch>
401 ///         where T: Any, Self: Downcast<T>
402 ///     { ... }
403 ///
404 ///     pub fn downcast_mut<T>(&mut self) -> Result<&mut T, TypeMismatch>
405 ///         where T: Any, Self: Downcast<T>
406 ///     { ... }
407 ///
408 ///     pub fn downcast<T>(self: Box<Self>) -> Result<Box<T>, DowncastError<Box<T>>>
409 ///         where T: Any, Self: Downcast<T>
410 ///     { ... }
411 /// }
412 /// ```
413 #[cfg(feature = "std")]
414 #[macro_export]
415 macro_rules! downcast_methods {
416     ($($tt:tt)+) => { $crate::downcast_methods_std!($($tt)+); }
417 }
418 
419 /// Implements [`Downcast`](trait.Downcast.html) and generates
420 /// `downcast`-methods for your trait-object-type.
421 ///
422 /// See [`impl_downcast`](macro.impl_downcast.html),
423 /// [`downcast_methods`](macro.downcast_methods.html).
424 #[macro_export]
425 macro_rules! downcast {
426     ($($tt:tt)+) => {
427         $crate::impl_downcast!($($tt)+);
428         $crate::downcast_methods!($($tt)+);
429     }
430 }
431 
432 /// Implements [`DowncastSync`](trait.DowncastSync.html) and generates
433 /// `downcast`-methods for your trait-object-type.
434 ///
435 /// See [`impl_downcast_sync`](macro.impl_downcast.html),
436 /// [`downcast_sync_methods`](macro.downcast_methods.html).
437 #[cfg(feature = "std")]
438 #[macro_export]
439 macro_rules! downcast_sync {
440     ($($tt:tt)+) => {
441         $crate::impl_downcast_sync!($($tt)+);
442         $crate::downcast_sync_methods!($($tt)+);
443     }
444 }
445 
446 // NOTE: We only implement the trait, because implementing the methods won't
447 // be possible when we replace downcast::Any by std::any::Any.
448 downcast!(dyn Any);
449 downcast!((dyn Any + Send));
450 downcast!((dyn Any + Sync));
451 #[cfg(feature = "std")]
452 downcast_sync!(dyn AnySync);
453 
454