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