anymap2/
any.rs

1//! The different types of `Any` for use in a map.
2//!
3//! This is based on `std::any`, but goes a little further, with `CloneAny`
4//! being a cloneable `Any`. `CloneAnySend`, `CloneAnySync`, and
5//! `CloneAnySendSync` further retrict what can be placed in the map with the
6//! `Send` and `Sync` bounds.
7
8use std::{any::Any as StdAny, fmt};
9
10#[doc(hidden)]
11pub trait CloneToAny {
12    /// Clone `self` into a new `Box<CloneAny>` object.
13    fn clone_to_any(&self) -> Box<dyn CloneAny>;
14}
15
16impl<T: Any + Clone> CloneToAny for T {
17    #[inline]
18    fn clone_to_any(&self) -> Box<dyn CloneAny> {
19        Box::new(self.clone())
20    }
21}
22
23#[doc(hidden)]
24pub trait CloneToAnySend: Send {
25    /// Clone `self` into a new `Box<CloneAnySend + Send>` object.
26    fn clone_to_any_send(&self) -> Box<dyn CloneAnySend + Send>;
27}
28
29impl<T: Any + Send + Clone> CloneToAnySend for T {
30    #[inline]
31    fn clone_to_any_send(&self) -> Box<dyn CloneAnySend + Send> {
32        Box::new(self.clone())
33    }
34}
35
36#[doc(hidden)]
37pub trait CloneToAnySync: Sync {
38    /// Clone `self` into a new `Box<CloneAnySync + Sync>` object.
39    fn clone_to_any_sync(&self) -> Box<dyn CloneAnySync + Sync>;
40}
41
42impl<T: Any + Sync + Clone> CloneToAnySync for T {
43    #[inline]
44    fn clone_to_any_sync(&self) -> Box<dyn CloneAnySync + Sync> {
45        Box::new(self.clone())
46    }
47}
48
49#[doc(hidden)]
50pub trait CloneToAnySendSync: Send + Sync {
51    /// Clone `self` into a new `Box<CloneAnySendSync + Send + Sync>` object.
52    fn clone_to_any_send_sync(&self) -> Box<dyn CloneAnySendSync + Send + Sync>;
53}
54
55impl<T: Any + Send + Sync + Clone> CloneToAnySendSync for T {
56    #[inline]
57    fn clone_to_any_send_sync(&self) -> Box<dyn CloneAnySendSync + Send + Sync> {
58        Box::new(self.clone())
59    }
60}
61
62macro_rules! define {
63    (CloneAny) => {
64        /// A type to emulate dynamic typing.
65        ///
66        /// Every type with no non-`'static` references implements `Any`.
67        define!(CloneAny remainder);
68    };
69    (CloneAnySend) => {
70        /// A type to emulate dynamic typing.
71        ///
72        /// Every type with no non-`'static` references implements `Any`.
73        define!(CloneAnySend remainder);
74    };
75    (CloneAnySync) => {
76        /// A type to emulate dynamic typing.
77        ///
78        /// Every type with no non-`'static` references implements `Any`.
79        define!(CloneAnySync remainder);
80    };
81    (CloneAnySendSync) => {
82        /// A type to emulate dynamic typing.
83        ///
84        /// Every type with no non-`'static` references implements `Any`.
85        define!(CloneAnySendSync remainder);
86    };
87    (Any) => {
88        /// A type to emulate dynamic typing with cloning.
89        ///
90        /// Every type with no non-`'static` references that implements `Clone` implements `Any`.
91        define!(Any remainder);
92    };
93    ($t:ident remainder) => {
94        /// See the [`std::any` documentation](https://doc.rust-lang.org/std/any/index.html) for
95        /// more details on `Any` in general.
96        ///
97        /// This trait is not `std::any::Any` but rather a type extending that for this library’s
98        /// purposes so that it can be combined with marker traits like
99        /// <code><a class=trait title=core::marker::Send
100        /// href=http://doc.rust-lang.org/std/marker/trait.Send.html>Send</a></code> and
101        /// <code><a class=trait title=core::marker::Sync
102        /// href=http://doc.rust-lang.org/std/marker/trait.Sync.html>Sync</a></code>.
103        ///
104        define!($t trait);
105    };
106    (CloneAny trait) => {
107        /// See also [`Any`](trait.Any.html) for a version without the `Clone` requirement.
108        pub trait CloneAny: Any + CloneToAny { }
109        impl<T: StdAny + Clone> CloneAny for T { }
110    };
111    (CloneAnySend trait) => {
112        /// See also [`Any`](trait.Any.html) for a version without the `Clone + Send` requirements.
113        pub trait CloneAnySend: Any + CloneToAnySend { }
114        impl<T: StdAny + Send + Clone> CloneAnySend for T { }
115    };
116    (CloneAnySync trait) => {
117        /// See also [`Any`](trait.Any.html) for a version without the `Clone + Sync` requirements.
118        pub trait CloneAnySync: Any + CloneToAnySync { }
119        impl<T: StdAny + Sync + Clone> CloneAnySync for T { }
120    };
121    (CloneAnySendSync trait) => {
122        /// See also [`Any`](trait.Any.html) for a version without the `Clone + Send + Sync` requirements.
123        pub trait CloneAnySendSync: Any + CloneToAnySendSync { }
124        impl<T: StdAny + Send + Sync + Clone> CloneAnySendSync for T { }
125    };
126    (Any trait) => {
127        /// See also [`CloneAny`](trait.CloneAny.html) for a cloneable version of this trait.
128        pub trait Any: StdAny { }
129        impl<T: StdAny> Any for T { }
130    };
131}
132
133macro_rules! impl_clone {
134    ($t:ty, $method:ident) => {
135        impl Clone for Box<$t> {
136            #[inline]
137            fn clone(&self) -> Box<$t> {
138                (**self).$method()
139            }
140        }
141    };
142}
143
144// Not public outside the crate.
145#[allow(missing_docs, clippy::missing_safety_doc)]
146pub trait UncheckedAnyExt: Any {
147    unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T;
148    unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T;
149    unsafe fn downcast_unchecked<T: Any>(self: Box<Self>) -> Box<T>;
150}
151
152#[doc(hidden)]
153/// A trait for the conversion of an object into a boxed trait object.
154pub trait IntoBox<A: ?Sized + UncheckedAnyExt>: Any {
155    /// Convert self into the appropriate boxed form.
156    fn into_box(self) -> Box<A>;
157}
158
159macro_rules! implement {
160    ($base:ident, $(+ $bounds:ident)*) => {
161        impl fmt::Debug for dyn $base $(+ $bounds)* {
162            #[inline]
163            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164                f.pad(stringify!($base $(+ $bounds)*))
165            }
166        }
167
168        impl UncheckedAnyExt for dyn $base $(+ $bounds)* {
169            #[inline]
170            unsafe fn downcast_ref_unchecked<T>(&self) -> &T {
171                &*(self as *const Self as *const T)
172            }
173
174            #[inline]
175            unsafe fn downcast_mut_unchecked<T>(&mut self) -> &mut T {
176                &mut *(self as *mut Self as *mut T)
177            }
178
179            #[inline]
180            unsafe fn downcast_unchecked<T>(self: Box<Self>) -> Box<T> {
181                Box::from_raw(Box::into_raw(self) as *mut T)
182            }
183        }
184
185        impl<T: $base $(+ $bounds)*> IntoBox<dyn $base $(+ $bounds)*> for T {
186            #[inline]
187            fn into_box(self) -> Box<dyn $base $(+ $bounds)*> {
188                Box::new(self)
189            }
190        }
191    }
192}
193
194define!(Any);
195implement!(Any,);
196implement!(Any, + Send);
197implement!(Any, + Sync);
198implement!(Any, + Send + Sync);
199implement!(CloneAny,);
200implement!(CloneAnySend, + Send);
201implement!(CloneAnySync, + Sync);
202implement!(CloneAnySendSync, + Send + Sync);
203
204define!(CloneAny);
205define!(CloneAnySend);
206define!(CloneAnySync);
207define!(CloneAnySendSync);
208impl_clone!(dyn CloneAny, clone_to_any);
209impl_clone!((dyn CloneAnySend + Send), clone_to_any_send);
210impl_clone!((dyn CloneAnySync + Sync), clone_to_any_sync);
211impl_clone!((dyn CloneAnySendSync + Send + Sync), clone_to_any_send_sync);