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