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