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