Keep Clippy happy.
[anymap] / src / any.rs
1 //! The different types of `Any` for use in a map.
2 //!
3 //! This stuff is all based on `std::any`, but goes a little further, with `CloneAny` being a
4 //! cloneable `Any` and with the `Send` and `Sync` bounds possible on both `Any` and `CloneAny`.
5
6 use std::mem;
7 use std::fmt;
8 use std::any::Any as StdAny;
9
10 #[doc(hidden)]
11 pub trait CloneToAny {
12 /// Clone `self` into a new `Box<CloneAny>` object.
13 fn clone_to_any(&self) -> Box<CloneAny>;
14
15 /// Clone `self` into a new `Box<CloneAny + Send>` object.
16 fn clone_to_any_send(&self) -> Box<CloneAny + Send> where Self: Send;
17
18 /// Clone `self` into a new `Box<CloneAny + Sync>` object.
19 fn clone_to_any_sync(&self) -> Box<CloneAny + Sync> where Self: Sync;
20
21 /// Clone `self` into a new `Box<CloneAny + Send + Sync>` object.
22 fn clone_to_any_send_sync(&self) -> Box<CloneAny + Send + Sync> where Self: Send + Sync;
23 }
24
25 impl<T: Any + Clone> CloneToAny for T {
26 fn clone_to_any(&self) -> Box<CloneAny> {
27 Box::new(self.clone())
28 }
29
30 fn clone_to_any_send(&self) -> Box<CloneAny + Send> where Self: Send {
31 Box::new(self.clone())
32 }
33
34 fn clone_to_any_sync(&self) -> Box<CloneAny + Sync> where Self: Sync {
35 Box::new(self.clone())
36 }
37
38 fn clone_to_any_send_sync(&self) -> Box<CloneAny + Send + Sync> where Self: Send + Sync {
39 Box::new(self.clone())
40 }
41 }
42
43 macro_rules! define {
44 (CloneAny) => {
45 /// A type to emulate dynamic typing.
46 ///
47 /// Every type with no non-`'static` references implements `Any`.
48 define!(CloneAny remainder);
49 };
50 (Any) => {
51 /// A type to emulate dynamic typing with cloning.
52 ///
53 /// Every type with no non-`'static` references that implements `Clone` implements `Any`.
54 define!(Any remainder);
55 };
56 ($t:ident remainder) => {
57 /// See the [`std::any` documentation](https://doc.rust-lang.org/std/any/index.html) for
58 /// more details on `Any` in general.
59 ///
60 /// This trait is not `std::any::Any` but rather a type extending that for this library’s
61 /// purposes so that it can be combined with marker traits like
62 /// <code><a class=trait title=core::marker::Send
63 /// href=http://doc.rust-lang.org/std/marker/trait.Send.html>Send</a></code> and
64 /// <code><a class=trait title=core::marker::Sync
65 /// href=http://doc.rust-lang.org/std/marker/trait.Sync.html>Sync</a></code>.
66 ///
67 define!($t trait);
68 };
69 (CloneAny trait) => {
70 /// See also [`Any`](trait.Any.html) for a version without the `Clone` requirement.
71 pub trait CloneAny: Any + CloneToAny { }
72 impl<T: StdAny + Clone> CloneAny for T { }
73 };
74 (Any trait) => {
75 /// See also [`CloneAny`](trait.CloneAny.html) for a cloneable version of this trait.
76 pub trait Any: StdAny { }
77 impl<T: StdAny> Any for T { }
78 };
79 }
80
81 macro_rules! impl_clone {
82 ($t:ty, $method:ident) => {
83 impl Clone for Box<$t> {
84 fn clone(&self) -> Box<$t> {
85 (**self).$method()
86 }
87 }
88 }
89 }
90
91 #[cfg(feature = "unstable")]
92 use std::raw::TraitObject;
93
94 #[cfg(not(feature = "unstable"))]
95 #[repr(C)]
96 #[derive(Copy, Clone)]
97 struct TraitObject {
98 pub data: *mut (),
99 pub vtable: *mut (),
100 }
101
102 #[allow(missing_docs)] // Bogus warning (it’s not public outside the crate), ☹
103 pub trait UncheckedAnyExt: Any {
104 unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T;
105 unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T;
106 unsafe fn downcast_unchecked<T: Any>(self: Box<Self>) -> Box<T>;
107 }
108
109 #[doc(hidden)]
110 /// A trait for the conversion of an object into a boxed trait object.
111 pub trait IntoBox<A: ?Sized + UncheckedAnyExt>: Any {
112 /// Convert self into the appropriate boxed form.
113 fn into_box(self) -> Box<A>;
114 }
115
116 macro_rules! implement {
117 ($base:ident, $(+ $bounds:ident)*) => {
118 impl fmt::Debug for $base $(+ $bounds)* {
119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120 f.pad(stringify!($base $(+ $bounds)*))
121 }
122 }
123
124 impl UncheckedAnyExt for $base $(+ $bounds)* {
125 unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
126 mem::transmute(mem::transmute::<_, TraitObject>(self).data)
127 }
128
129 unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
130 mem::transmute(mem::transmute::<_, TraitObject>(self).data)
131 }
132
133 unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> Box<T> {
134 mem::transmute(mem::transmute::<_, TraitObject>(self).data)
135 }
136 }
137
138 impl<T: $base $(+ $bounds)*> IntoBox<$base $(+ $bounds)*> for T {
139 fn into_box(self) -> Box<$base $(+ $bounds)*> {
140 Box::new(self)
141 }
142 }
143 }
144 }
145
146 define!(Any);
147 implement!(Any,);
148 implement!(Any, + Send);
149 implement!(Any, + Sync);
150 implement!(Any, + Send + Sync);
151 implement!(CloneAny,);
152 implement!(CloneAny, + Send);
153 implement!(CloneAny, + Sync);
154 implement!(CloneAny, + Send + Sync);
155
156 define!(CloneAny);
157 impl_clone!(CloneAny, clone_to_any);
158 impl_clone!((CloneAny + Send), clone_to_any_send);
159 impl_clone!((CloneAny + Sync), clone_to_any_sync);
160 impl_clone!((CloneAny + Send + Sync), clone_to_any_send_sync);