ea1033205c80ecbf0242068778dfb172c168f73c
[anymap] / src / lib.rs
1 //! This crate provides the `AnyMap` type, a safe and convenient store for one value of each type.
2
3 #![feature(core, std_misc, hash)]
4 #![cfg_attr(test, feature(test))]
5 #![warn(unused_qualifications, non_upper_case_globals,
6 variant_size_differences, unused_typecasts,
7 missing_docs, unused_results)]
8
9 #[cfg(test)]
10 extern crate test;
11
12 use std::any::{Any, TypeId};
13 use std::mem::forget;
14 use std::collections::HashMap;
15 use std::collections::hash_map;
16 use std::hash::Hasher;
17 use std::collections::hash_state::HashState;
18 use std::mem::transmute;
19 use std::raw::TraitObject;
20 use std::marker::PhantomData;
21
22 struct TypeIdHasher {
23 value: u64,
24 }
25
26 struct TypeIdState;
27
28 impl HashState for TypeIdState {
29 type Hasher = TypeIdHasher;
30
31 fn hasher(&self) -> TypeIdHasher {
32 TypeIdHasher { value: 0 }
33 }
34 }
35
36 impl Hasher for TypeIdHasher {
37 #[inline(always)]
38 fn write(&mut self, bytes: &[u8]) {
39 // This expects to receive one and exactly one 64-bit value
40 debug_assert!(bytes.len() == 8);
41 unsafe {
42 std::ptr::copy_nonoverlapping(&mut self.value, transmute(&bytes[0]), 1)
43 }
44 }
45
46 #[inline(always)]
47 fn finish(&self) -> u64 { self.value }
48 }
49
50 /// An extension of `AnyRefExt` allowing unchecked downcasting of trait objects to `&T`.
51 trait UncheckedAnyRefExt<'a> {
52 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
53 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
54 unsafe fn downcast_ref_unchecked<T: 'static>(self) -> &'a T;
55 }
56
57 impl<'a> UncheckedAnyRefExt<'a> for &'a Any {
58 #[inline]
59 unsafe fn downcast_ref_unchecked<T: 'static>(self) -> &'a T {
60 // Get the raw representation of the trait object
61 let to: TraitObject = transmute(self);
62
63 // Extract the data pointer
64 transmute(to.data)
65 }
66 }
67
68 /// An extension of `AnyMutRefExt` allowing unchecked downcasting of trait objects to `&mut T`.
69 trait UncheckedAnyMutRefExt<'a> {
70 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
71 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
72 unsafe fn downcast_mut_unchecked<T: 'static>(self) -> &'a mut T;
73 }
74
75 impl<'a> UncheckedAnyMutRefExt<'a> for &'a mut Any {
76 #[inline]
77 unsafe fn downcast_mut_unchecked<T: 'static>(self) -> &'a mut T {
78 // Get the raw representation of the trait object
79 let to: TraitObject = transmute(self);
80
81 // Extract the data pointer
82 transmute(to.data)
83 }
84 }
85
86 /// An extension of `BoxAny` allowing unchecked downcasting of trait objects to `Box<T>`.
87 trait UncheckedBoxAny {
88 /// Returns the boxed value, assuming that it is of type `T`. This should only be called if you
89 /// are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
90 unsafe fn downcast_unchecked<T: 'static>(self) -> Box<T>;
91 }
92
93 impl UncheckedBoxAny for Box<Any + 'static> {
94 #[inline]
95 unsafe fn downcast_unchecked<T: 'static>(self) -> Box<T> {
96 // Get the raw representation of the trait object
97 let to: TraitObject = *transmute::<&Box<Any>, &TraitObject>(&self);
98
99 // Prevent destructor on self being run
100 forget(self);
101
102 // Extract the data pointer
103 transmute(to.data)
104 }
105 }
106
107 /// A collection containing zero or one values for any given type and allowing convenient,
108 /// type-safe access to those values.
109 ///
110 /// ```rust
111 /// # use anymap::AnyMap;
112 /// let mut data = AnyMap::new();
113 /// assert_eq!(data.get(), None::<&i32>);
114 /// data.insert(42i32);
115 /// assert_eq!(data.get(), Some(&42i32));
116 /// data.remove::<i32>();
117 /// assert_eq!(data.get::<i32>(), None);
118 ///
119 /// #[derive(PartialEq, Debug)]
120 /// struct Foo {
121 /// str: String,
122 /// }
123 ///
124 /// assert_eq!(data.get::<Foo>(), None);
125 /// data.insert(Foo { str: format!("foo") });
126 /// assert_eq!(data.get(), Some(&Foo { str: format!("foo") }));
127 /// data.get_mut::<Foo>().map(|foo| foo.str.push('t'));
128 /// assert_eq!(&*data.get::<Foo>().unwrap().str, "foot");
129 /// ```
130 ///
131 /// Values containing non-static references are not permitted.
132 pub struct AnyMap {
133 data: HashMap<TypeId, Box<Any + 'static>, TypeIdState>,
134 }
135
136 impl AnyMap {
137 /// Construct a new `AnyMap`.
138 #[inline]
139 pub fn new() -> AnyMap {
140 AnyMap {
141 data: HashMap::with_hash_state(TypeIdState),
142 }
143 }
144
145 /// Creates an empty AnyMap with the given initial capacity.
146 #[inline]
147 pub fn with_capcity(capacity: usize) -> AnyMap {
148 AnyMap {
149 data: HashMap::with_capacity_and_hash_state(capacity, TypeIdState),
150 }
151 }
152
153 /// Returns the number of elements the collection can hold without reallocating.
154 #[inline]
155 pub fn capacity(&self) -> usize {
156 self.data.capacity()
157 }
158
159 /// Reserves capacity for at least `additional` more elements to be inserted
160 /// in the `AnyMap`. The collection may reserve more space to avoid
161 /// frequent reallocations.
162 ///
163 /// # Panics
164 ///
165 /// Panics if the new allocation size overflows `usize`.
166 #[inline]
167 pub fn reserve(&mut self, additional: usize) {
168 self.data.reserve(additional)
169 }
170
171 /// Shrinks the capacity of the collection as much as possible. It will drop
172 /// down as much as possible while maintaining the internal rules
173 /// and possibly leaving some space in accordance with the resize policy.
174 #[inline]
175 pub fn shrink_to_fit(&mut self) {
176 self.data.shrink_to_fit()
177 }
178
179 /// An iterator visiting all items in the collection in arbitrary order.
180 /// Iterator element type is `&Any`.
181 ///
182 /// This is probably not a great deal of use.
183 #[inline]
184 pub fn iter(&self) -> Iter {
185 Iter {
186 inner: self.data.iter(),
187 }
188 }
189
190 /// An iterator visiting all items in the collection in arbitrary order.
191 /// Iterator element type is `&mut Any`.
192 ///
193 /// This is probably not a great deal of use.
194 #[inline]
195 pub fn iter_mut(&mut self) -> IterMut {
196 IterMut {
197 inner: self.data.iter_mut(),
198 }
199 }
200
201 /// An iterator visiting all items in the collection in arbitrary order.
202 /// Creates a consuming iterator, that is, one that moves each item
203 /// out of the map in arbitrary order. The map cannot be used after
204 /// calling this.
205 ///
206 /// Iterator element type is `Box<Any>`.
207 #[inline]
208 pub fn into_iter(self) -> IntoIter {
209 IntoIter {
210 inner: self.data.into_iter(),
211 }
212 }
213
214 /// Returns a reference to the value stored in the collection for the type `T`, if it exists.
215 pub fn get<T: Any + 'static>(&self) -> Option<&T> {
216 self.data.get(&TypeId::of::<T>())
217 .map(|any| unsafe { any.downcast_ref_unchecked::<T>() })
218 }
219
220 /// Returns a mutable reference to the value stored in the collection for the type `T`,
221 /// if it exists.
222 pub fn get_mut<T: Any + 'static>(&mut self) -> Option<&mut T> {
223 self.data.get_mut(&TypeId::of::<T>())
224 .map(|any| unsafe { any.downcast_mut_unchecked::<T>() })
225 }
226
227 /// Sets the value stored in the collection for the type `T`.
228 /// If the collection already had a value of type `T`, that value is returned.
229 /// Otherwise, `None` is returned.
230 pub fn insert<T: Any + 'static>(&mut self, value: T) -> Option<T> {
231 self.data.insert(TypeId::of::<T>(), Box::new(value) as Box<Any>)
232 .map(|any| *unsafe { any.downcast_unchecked::<T>() })
233 }
234
235 /// Removes the `T` value from the collection,
236 /// returning it if there was one or `None` if there was not.
237 pub fn remove<T: Any + 'static>(&mut self) -> Option<T> {
238 self.data.remove(&TypeId::of::<T>())
239 .map(|any| *unsafe { any.downcast_unchecked::<T>() })
240 }
241
242 /// Returns true if the collection contains a value of type `T`.
243 pub fn contains<T: Any + 'static>(&self) -> bool {
244 self.data.contains_key(&TypeId::of::<T>())
245 }
246
247 /// Gets the entry for the given type in the collection for in-place manipulation
248 pub fn entry<T: Any + 'static>(&mut self) -> Entry<T> {
249 match self.data.entry(TypeId::of::<T>()) {
250 hash_map::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
251 entry: e,
252 type_: PhantomData,
253 }),
254 hash_map::Entry::Vacant(e) => Entry::Vacant(VacantEntry {
255 entry: e,
256 type_: PhantomData,
257 }),
258 }
259 }
260
261 /// Returns the number of items in the collection.
262 #[inline]
263 pub fn len(&self) -> usize {
264 self.data.len()
265 }
266
267 /// Returns true if there are no items in the collection.
268 #[inline]
269 pub fn is_empty(&self) -> bool {
270 self.data.is_empty()
271 }
272
273 /// Clears the map, returning all items as an iterator.
274 ///
275 /// Iterator element type is `Box<Any>`.
276 ///
277 /// Keeps the allocated memory for reuse.
278 #[inline]
279 pub fn drain(&mut self) -> Drain {
280 Drain {
281 inner: self.data.drain(),
282 }
283 }
284
285 /// Removes all items from the collection. Keeps the allocated memory for reuse.
286 #[inline]
287 pub fn clear(&mut self) {
288 self.data.clear();
289 }
290 }
291
292 /// A view into a single occupied location in an AnyMap
293 pub struct OccupiedEntry<'a, V: 'a> {
294 entry: hash_map::OccupiedEntry<'a, TypeId, Box<Any + 'static>>,
295 type_: PhantomData<V>,
296 }
297
298 /// A view into a single empty location in an AnyMap
299 pub struct VacantEntry<'a, V: 'a> {
300 entry: hash_map::VacantEntry<'a, TypeId, Box<Any + 'static>>,
301 type_: PhantomData<V>,
302 }
303
304 /// A view into a single location in an AnyMap, which may be vacant or occupied
305 pub enum Entry<'a, V: 'a> {
306 /// An occupied Entry
307 Occupied(OccupiedEntry<'a, V>),
308 /// A vacant Entry
309 Vacant(VacantEntry<'a, V>),
310 }
311
312 impl<'a, V: 'static + Clone> Entry<'a, V> {
313 /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
314 pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, V>> {
315 match self {
316 Entry::Occupied(entry) => Ok(entry.into_mut()),
317 Entry::Vacant(entry) => Err(entry),
318 }
319 }
320 }
321
322 impl<'a, V: 'static> OccupiedEntry<'a, V> {
323 /// Gets a reference to the value in the entry
324 pub fn get(&self) -> &V {
325 unsafe { self.entry.get().downcast_ref_unchecked() }
326 }
327
328 /// Gets a mutable reference to the value in the entry
329 pub fn get_mut(&mut self) -> &mut V {
330 unsafe { self.entry.get_mut().downcast_mut_unchecked() }
331 }
332
333 /// Converts the OccupiedEntry into a mutable reference to the value in the entry
334 /// with a lifetime bound to the collection itself
335 pub fn into_mut(self) -> &'a mut V {
336 unsafe { self.entry.into_mut().downcast_mut_unchecked() }
337 }
338
339 /// Sets the value of the entry, and returns the entry's old value
340 pub fn insert(&mut self, value: V) -> V {
341 unsafe { *self.entry.insert(Box::new(value) as Box<Any + 'static>).downcast_unchecked() }
342 }
343
344 /// Takes the value out of the entry, and returns it
345 pub fn remove(self) -> V {
346 unsafe { *self.entry.remove().downcast_unchecked() }
347 }
348 }
349
350 impl<'a, V: 'static> VacantEntry<'a, V> {
351 /// Sets the value of the entry with the VacantEntry's key,
352 /// and returns a mutable reference to it
353 pub fn insert(self, value: V) -> &'a mut V {
354 unsafe { self.entry.insert(Box::new(value) as Box<Any + 'static>).downcast_mut_unchecked() }
355 }
356 }
357
358 /// `AnyMap` iterator.
359 #[derive(Clone)]
360 pub struct Iter<'a> {
361 inner: hash_map::Iter<'a, TypeId, Box<Any + 'static>>,
362 }
363
364 /// `AnyMap` mutable references iterator.
365 pub struct IterMut<'a> {
366 inner: hash_map::IterMut<'a, TypeId, Box<Any + 'static>>,
367 }
368
369 /// `AnyMap` draining iterator.
370 pub struct Drain<'a> {
371 inner: hash_map::Drain<'a, TypeId, Box<Any + 'static>>,
372 }
373
374 /// `AnyMap` move iterator.
375 pub struct IntoIter {
376 inner: hash_map::IntoIter<TypeId, Box<Any + 'static>>,
377 }
378
379 impl<'a> Iterator for Iter<'a> {
380 type Item = &'a Any;
381
382 #[inline]
383 fn next(&mut self) -> Option<&'a Any> {
384 self.inner.next().map(|item| &**item.1)
385 }
386
387 #[inline]
388 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
389 }
390
391 impl<'a> Iterator for IterMut<'a> {
392 type Item = &'a mut Any;
393
394 #[inline]
395 fn next(&mut self) -> Option<&'a mut Any> {
396 self.inner.next().map(|item| &mut **item.1)
397 }
398
399 #[inline]
400 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
401 }
402
403 impl<'a> Iterator for Drain<'a> {
404 type Item = Box<Any + 'static>;
405
406 #[inline]
407 fn next(&mut self) -> Option<Box<Any + 'static>> {
408 self.inner.next().map(|item| item.1)
409 }
410
411 #[inline]
412 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
413 }
414
415 impl Iterator for IntoIter {
416 type Item = Box<Any + 'static>;
417
418 #[inline]
419 fn next(&mut self) -> Option<Box<Any + 'static>> {
420 self.inner.next().map(|item| item.1)
421 }
422
423 #[inline]
424 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
425 }
426
427 #[bench]
428 fn bench_insertion(b: &mut ::test::Bencher) {
429 b.iter(|| {
430 let mut data = AnyMap::new();
431 for _ in 0..100 {
432 let _ = data.insert(42);
433 }
434 })
435 }
436
437 #[bench]
438 fn bench_get_missing(b: &mut ::test::Bencher) {
439 b.iter(|| {
440 let data = AnyMap::new();
441 for _ in 0..100 {
442 assert_eq!(data.get(), None::<&i32>);
443 }
444 })
445 }
446
447 #[bench]
448 fn bench_get_present(b: &mut ::test::Bencher) {
449 b.iter(|| {
450 let mut data = AnyMap::new();
451 let _ = data.insert(42);
452 // These inner loops are a feeble attempt to drown the other factors.
453 for _ in 0..100 {
454 assert_eq!(data.get(), Some(&42));
455 }
456 })
457 }
458
459 #[test]
460 fn test_entry() {
461 #[derive(Debug, PartialEq)] struct A(i32);
462 #[derive(Debug, PartialEq)] struct B(i32);
463 #[derive(Debug, PartialEq)] struct C(i32);
464 #[derive(Debug, PartialEq)] struct D(i32);
465 #[derive(Debug, PartialEq)] struct E(i32);
466 #[derive(Debug, PartialEq)] struct F(i32);
467 #[derive(Debug, PartialEq)] struct J(i32);
468
469 let mut map: AnyMap = AnyMap::new();
470 assert_eq!(map.insert(A(10)), None);
471 assert_eq!(map.insert(B(20)), None);
472 assert_eq!(map.insert(C(30)), None);
473 assert_eq!(map.insert(D(40)), None);
474 assert_eq!(map.insert(E(50)), None);
475 assert_eq!(map.insert(F(60)), None);
476
477 // Existing key (insert)
478 match map.entry::<A>() {
479 Entry::Vacant(_) => unreachable!(),
480 Entry::Occupied(mut view) => {
481 assert_eq!(view.get(), &A(10));
482 assert_eq!(view.insert(A(100)), A(10));
483 }
484 }
485 assert_eq!(map.get::<A>().unwrap(), &A(100));
486 assert_eq!(map.len(), 6);
487
488
489 // Existing key (update)
490 match map.entry::<B>() {
491 Entry::Vacant(_) => unreachable!(),
492 Entry::Occupied(mut view) => {
493 let v = view.get_mut();
494 let new_v = B(v.0 * 10);
495 *v = new_v;
496 }
497 }
498 assert_eq!(map.get().unwrap(), &B(200));
499 assert_eq!(map.len(), 6);
500
501
502 // Existing key (remove)
503 match map.entry::<C>() {
504 Entry::Vacant(_) => unreachable!(),
505 Entry::Occupied(view) => {
506 assert_eq!(view.remove(), C(30));
507 }
508 }
509 assert_eq!(map.get::<C>(), None);
510 assert_eq!(map.len(), 5);
511
512
513 // Inexistent key (insert)
514 match map.entry::<J>() {
515 Entry::Occupied(_) => unreachable!(),
516 Entry::Vacant(view) => {
517 assert_eq!(*view.insert(J(1000)), J(1000));
518 }
519 }
520 assert_eq!(map.get::<J>().unwrap(), &J(1000));
521 assert_eq!(map.len(), 6);
522 }