any_key/
lib.rs

1//! Dynamically typed keys for associative arrays.
2//!
3//! ## Example
4//!
5//! ```
6//! use std::collections::{BTreeMap, HashMap};
7//! use any_key::{AnyHash, AnyOrd};
8//!
9//! #[derive(PartialEq, Eq, Hash, PartialOrd, Ord)]
10//! struct Foo;
11//!
12//! // AnyHash can be used as a key for HashMap-like types
13//! let mut map = HashMap::new();
14//! map.insert(Box::new("hello") as Box<AnyHash>, 1);
15//! map.insert(Box::new(42) as Box<AnyHash>, 2);
16//! map.insert(Box::new(Foo) as Box<AnyHash>, 3);
17//! assert_eq!(map.get(&(Box::new("hello") as Box<AnyHash>)), Some(&1));
18//! assert_eq!(map.get(&(Box::new(42) as Box<AnyHash>)), Some(&2));
19//! assert_eq!(map.get(&(Box::new(Foo) as Box<AnyHash>)), Some(&3));
20//!
21//! // AnyOrd can be used as a key for HashMap-like types
22//! let mut map = BTreeMap::new();
23//! map.insert(Box::new("hello") as Box<AnyOrd>, 1);
24//! map.insert(Box::new(42) as Box<AnyOrd>, 2);
25//! map.insert(Box::new(Foo) as Box<AnyOrd>, 3);
26//! assert_eq!(map.get(&(Box::new("hello") as Box<AnyOrd>)), Some(&1));
27//! assert_eq!(map.get(&(Box::new(42) as Box<AnyOrd>)), Some(&2));
28//! assert_eq!(map.get(&(Box::new(Foo) as Box<AnyOrd>)), Some(&3));
29//! ```
30
31extern crate debugit;
32#[macro_use]
33extern crate mopa;
34
35use std::{cmp, fmt, hash, ops};
36use std::any::TypeId;
37
38/// Work around the inability of `Hash` to accept unsized `Hasher`s.
39#[derive(Debug)]
40pub struct HasherMut<H: ?Sized>(H);
41
42impl<H: ops::DerefMut + ?Sized> hash::Hasher for HasherMut<H>
43    where H::Target: hash::Hasher
44{
45    fn finish(&self) -> u64 {
46        self.0.finish()
47    }
48
49    fn write(&mut self, bytes: &[u8]) {
50        self.0.write(bytes)
51    }
52}
53
54/// Object-safe trait for dynamically typed hashable keys.
55///
56/// All `Eq + Hash + 'static` types automatically implement this trait.
57///
58/// On nightly, if the inner value implements `Debug`, then `Debug` for
59/// `AnyHash` will use that implementation.  Otherwise, it will only show a
60/// generic message.
61pub trait AnyHash: mopa::Any {
62    fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result;
63
64    fn eq(&self, other: &AnyHash) -> bool;
65
66    fn hash(&self, hasher: &mut hash::Hasher);
67}
68
69mopafy!(AnyHash);
70
71impl<T: Eq + hash::Hash + 'static> AnyHash for T {
72    fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
73        f.debug_tuple("AnyHash")
74            .field(&TypeId::of::<Self>())
75            .field(&debugit::DebugIt(self))
76            .finish()
77    }
78
79    fn eq(&self, other: &AnyHash) -> bool {
80        match other.downcast_ref::<Self>() {
81            None => false,
82            Some(other) => self == other,
83        }
84    }
85
86    fn hash(&self, hasher: &mut hash::Hasher) {
87        hash::Hash::hash(&(TypeId::of::<Self>(), self), &mut HasherMut(hasher))
88    }
89}
90
91impl fmt::Debug for AnyHash {
92    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93        self.debug(f)
94    }
95}
96
97impl fmt::Debug for AnyHash + Send {
98    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99        self.debug(f)
100    }
101}
102
103impl fmt::Debug for AnyHash + Send + Sync {
104    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105        self.debug(f)
106    }
107}
108
109impl PartialEq for AnyHash {
110    fn eq(&self, other: &Self) -> bool {
111        AnyHash::eq(self, other)
112    }
113}
114
115impl PartialEq for AnyHash + Send {
116    fn eq(&self, other: &Self) -> bool {
117        AnyHash::eq(self, other)
118    }
119}
120
121impl PartialEq for AnyHash + Send + Sync {
122    fn eq(&self, other: &Self) -> bool {
123        AnyHash::eq(self, other)
124    }
125}
126
127impl Eq for AnyHash {}
128
129impl Eq for AnyHash + Send {}
130
131impl Eq for AnyHash + Send + Sync {}
132
133impl hash::Hash for AnyHash {
134    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
135        AnyHash::hash(self, hasher)
136    }
137}
138
139impl hash::Hash for AnyHash + Send {
140    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
141        AnyHash::hash(self, hasher)
142    }
143}
144
145impl hash::Hash for AnyHash + Send + Sync {
146    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
147        AnyHash::hash(self, hasher)
148    }
149}
150
151/// Object-safe trait for dynamically typed totally ordered keys.
152///
153/// All `Ord + 'static` types automatically implement this trait.
154///
155/// On nightly, if the inner value implements `Debug`, then `Debug` for
156/// `AnyOrd` will use that implementation.  Otherwise, it will only show a
157/// generic message.
158pub trait AnyOrd: mopa::Any {
159    fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result;
160
161    fn eq(&self, other: &AnyOrd) -> bool;
162
163    fn cmp(&self, other: &AnyOrd) -> cmp::Ordering;
164}
165
166mopafy!(AnyOrd);
167
168impl<T: Ord + 'static> AnyOrd for T {
169    fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
170        f.debug_tuple("AnyOrd")
171            .field(&TypeId::of::<Self>())
172            .field(&debugit::DebugIt(self))
173            .finish()
174    }
175
176    fn eq(&self, other: &AnyOrd) -> bool {
177        match other.downcast_ref::<Self>() {
178            None => false,
179            Some(other) => self == other,
180        }
181    }
182
183    fn cmp(&self, other: &AnyOrd) -> cmp::Ordering {
184        match other.downcast_ref::<Self>() {
185            None => Ord::cmp(&TypeId::of::<Self>(), &mopa::Any::get_type_id(other)),
186            Some(other) => self.cmp(other),
187        }
188    }
189}
190
191impl fmt::Debug for AnyOrd {
192    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
193        self.debug(f)
194    }
195}
196
197impl fmt::Debug for AnyOrd + Send {
198    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199        self.debug(f)
200    }
201}
202
203impl fmt::Debug for AnyOrd + Send + Sync {
204    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
205        self.debug(f)
206    }
207}
208
209impl PartialEq for AnyOrd {
210    fn eq(&self, other: &Self) -> bool {
211        AnyOrd::eq(self, other)
212    }
213}
214
215impl PartialEq for AnyOrd + Send {
216    fn eq(&self, other: &Self) -> bool {
217        AnyOrd::eq(self, other)
218    }
219}
220
221impl PartialEq for AnyOrd + Send + Sync {
222    fn eq(&self, other: &Self) -> bool {
223        AnyOrd::eq(self, other)
224    }
225}
226
227impl Eq for AnyOrd {}
228
229impl Eq for AnyOrd + Send {}
230
231impl Eq for AnyOrd + Send + Sync {}
232
233impl PartialOrd for AnyOrd {
234    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
235        Some(self.cmp(other))
236    }
237}
238
239impl PartialOrd for AnyOrd + Send {
240    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
241        Some(self.cmp(other))
242    }
243}
244
245impl PartialOrd for AnyOrd + Send + Sync {
246    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
247        Some(self.cmp(other))
248    }
249}
250
251impl Ord for AnyOrd {
252    fn cmp(&self, other: &Self) -> cmp::Ordering {
253        AnyOrd::cmp(self, other)
254    }
255}
256
257impl Ord for AnyOrd + Send {
258    fn cmp(&self, other: &Self) -> cmp::Ordering {
259        AnyOrd::cmp(self, other)
260    }
261}
262
263impl Ord for AnyOrd + Send + Sync {
264    fn cmp(&self, other: &Self) -> cmp::Ordering {
265        AnyOrd::cmp(self, other)
266    }
267}