e07d2f49affa1fe8906a05eadb22ae6bd75ccf65
[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 #[stable]
133 pub struct AnyMap {
134 data: HashMap<TypeId, Box<Any + 'static>, TypeIdState>,
135 }
136
137 impl AnyMap {
138 /// Construct a new `AnyMap`.
139 #[inline]
140 #[stable]
141 pub fn new() -> AnyMap {
142 AnyMap {
143 data: HashMap::with_hash_state(TypeIdState),
144 }
145 }
146
147 /// Creates an empty AnyMap with the given initial capacity.
148 #[inline]
149 #[stable]
150 pub fn with_capcity(capacity: usize) -> AnyMap {
151 AnyMap {
152 data: HashMap::with_capacity_and_hash_state(capacity, TypeIdState),
153 }
154 }
155
156 /// Returns the number of elements the collection can hold without reallocating.
157 #[inline]
158 #[stable]
159 pub fn capacity(&self) -> usize {
160 self.data.capacity()
161 }
162
163 /// Reserves capacity for at least `additional` more elements to be inserted
164 /// in the `AnyMap`. The collection may reserve more space to avoid
165 /// frequent reallocations.
166 ///
167 /// # Panics
168 ///
169 /// Panics if the new allocation size overflows `usize`.
170 #[inline]
171 #[stable]
172 pub fn reserve(&mut self, additional: usize) {
173 self.data.reserve(additional)
174 }
175
176 /// Shrinks the capacity of the collection as much as possible. It will drop
177 /// down as much as possible while maintaining the internal rules
178 /// and possibly leaving some space in accordance with the resize policy.
179 #[inline]
180 #[stable]
181 pub fn shrink_to_fit(&mut self) {
182 self.data.shrink_to_fit()
183 }
184
185 /// An iterator visiting all items in the collection in arbitrary order.
186 /// Iterator element type is `&Any`.
187 ///
188 /// This is probably not a great deal of use.
189 #[inline]
190 #[stable]
191 pub fn iter(&self) -> Iter {
192 Iter {
193 inner: self.data.iter(),
194 }
195 }
196
197 /// An iterator visiting all items in the collection in arbitrary order.
198 /// Iterator element type is `&mut Any`.
199 ///
200 /// This is probably not a great deal of use.
201 #[inline]
202 #[stable]
203 pub fn iter_mut(&mut self) -> IterMut {
204 IterMut {
205 inner: self.data.iter_mut(),
206 }
207 }
208
209 /// An iterator visiting all items in the collection in arbitrary order.
210 /// Creates a consuming iterator, that is, one that moves each item
211 /// out of the map in arbitrary order. The map cannot be used after
212 /// calling this.
213 ///
214 /// Iterator element type is `Box<Any>`.
215 #[inline]
216 #[stable]
217 pub fn into_iter(self) -> IntoIter {
218 IntoIter {
219 inner: self.data.into_iter(),
220 }
221 }
222
223 /// Returns a reference to the value stored in the collection for the type `T`, if it exists.
224 #[stable]
225 pub fn get<T: Any + 'static>(&self) -> Option<&T> {
226 self.data.get(&TypeId::of::<T>())
227 .map(|any| unsafe { any.downcast_ref_unchecked::<T>() })
228 }
229
230 /// Returns a mutable reference to the value stored in the collection for the type `T`,
231 /// if it exists.
232 #[stable]
233 pub fn get_mut<T: Any + 'static>(&mut self) -> Option<&mut T> {
234 self.data.get_mut(&TypeId::of::<T>())
235 .map(|any| unsafe { any.downcast_mut_unchecked::<T>() })
236 }
237
238 /// Sets the value stored in the collection for the type `T`.
239 /// If the collection already had a value of type `T`, that value is returned.
240 /// Otherwise, `None` is returned.
241 #[stable]
242 pub fn insert<T: Any + 'static>(&mut self, value: T) -> Option<T> {
243 self.data.insert(TypeId::of::<T>(), Box::new(value) as Box<Any>)
244 .map(|any| *unsafe { any.downcast_unchecked::<T>() })
245 }
246
247 /// Removes the `T` value from the collection,
248 /// returning it if there was one or `None` if there was not.
249 #[stable]
250 pub fn remove<T: Any + 'static>(&mut self) -> Option<T> {
251 self.data.remove(&TypeId::of::<T>())
252 .map(|any| *unsafe { any.downcast_unchecked::<T>() })
253 }
254
255 /// Returns true if the collection contains a value of type `T`.
256 #[stable]
257 pub fn contains<T: Any + 'static>(&self) -> bool {
258 self.data.contains_key(&TypeId::of::<T>())
259 }
260
261 /// Gets the entry for the given type in the collection for in-place manipulation
262 #[stable]
263 pub fn entry<T: Any + 'static>(&mut self) -> Entry<T> {
264 match self.data.entry(TypeId::of::<T>()) {
265 hash_map::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
266 entry: e,
267 type_: PhantomData,
268 }),
269 hash_map::Entry::Vacant(e) => Entry::Vacant(VacantEntry {
270 entry: e,
271 type_: PhantomData,
272 }),
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 type_: PhantomData<V>,
316 }
317
318 /// A view into a single empty location in an AnyMap
319 #[stable]
320 pub struct VacantEntry<'a, V: 'a> {
321 entry: hash_map::VacantEntry<'a, TypeId, Box<Any + 'static>>,
322 type_: PhantomData<V>,
323 }
324
325 /// A view into a single location in an AnyMap, which may be vacant or occupied
326 #[stable]
327 pub enum Entry<'a, V: 'a> {
328 /// An occupied Entry
329 Occupied(OccupiedEntry<'a, V>),
330 /// A vacant Entry
331 Vacant(VacantEntry<'a, V>),
332 }
333
334 impl<'a, V: 'static + Clone> Entry<'a, V> {
335 #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
336 /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
337 pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, V>> {
338 match self {
339 Entry::Occupied(entry) => Ok(entry.into_mut()),
340 Entry::Vacant(entry) => Err(entry),
341 }
342 }
343 }
344
345 impl<'a, V: 'static> OccupiedEntry<'a, V> {
346 #[stable]
347 /// Gets a reference to the value in the entry
348 pub fn get(&self) -> &V {
349 unsafe { self.entry.get().downcast_ref_unchecked() }
350 }
351
352 #[stable]
353 /// Gets a mutable reference to the value in the entry
354 pub fn get_mut(&mut self) -> &mut V {
355 unsafe { self.entry.get_mut().downcast_mut_unchecked() }
356 }
357
358 #[stable]
359 /// Converts the OccupiedEntry into a mutable reference to the value in the entry
360 /// with a lifetime bound to the collection itself
361 pub fn into_mut(self) -> &'a mut V {
362 unsafe { self.entry.into_mut().downcast_mut_unchecked() }
363 }
364
365 #[stable]
366 /// Sets the value of the entry, and returns the entry's old value
367 pub fn insert(&mut self, value: V) -> V {
368 unsafe { *self.entry.insert(Box::new(value) as Box<Any + 'static>).downcast_unchecked() }
369 }
370
371 #[stable]
372 /// Takes the value out of the entry, and returns it
373 pub fn remove(self) -> V {
374 unsafe { *self.entry.remove().downcast_unchecked() }
375 }
376 }
377
378 impl<'a, V: 'static> VacantEntry<'a, V> {
379 #[stable]
380 /// Sets the value of the entry with the VacantEntry's key,
381 /// and returns a mutable reference to it
382 pub fn insert(self, value: V) -> &'a mut V {
383 unsafe { self.entry.insert(Box::new(value) as Box<Any + 'static>).downcast_mut_unchecked() }
384 }
385 }
386
387 /// `AnyMap` iterator.
388 #[stable]
389 #[derive(Clone)]
390 pub struct Iter<'a> {
391 inner: hash_map::Iter<'a, TypeId, Box<Any + 'static>>,
392 }
393
394 /// `AnyMap` mutable references iterator.
395 #[stable]
396 pub struct IterMut<'a> {
397 inner: hash_map::IterMut<'a, TypeId, Box<Any + 'static>>,
398 }
399
400 /// `AnyMap` draining iterator.
401 #[unstable = "matches collection reform specification, waiting for dust to settle"]
402 pub struct Drain<'a> {
403 inner: hash_map::Drain<'a, TypeId, Box<Any + 'static>>,
404 }
405
406 /// `AnyMap` move iterator.
407 #[stable]
408 pub struct IntoIter {
409 inner: hash_map::IntoIter<TypeId, Box<Any + 'static>>,
410 }
411
412 #[stable]
413 impl<'a> Iterator for Iter<'a> {
414 type Item = &'a Any;
415
416 #[inline]
417 fn next(&mut self) -> Option<&'a Any> {
418 self.inner.next().map(|item| &**item.1)
419 }
420
421 #[inline]
422 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
423 }
424
425 #[stable]
426 impl<'a> Iterator for IterMut<'a> {
427 type Item = &'a mut Any;
428
429 #[inline]
430 fn next(&mut self) -> Option<&'a mut Any> {
431 self.inner.next().map(|item| &mut **item.1)
432 }
433
434 #[inline]
435 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
436 }
437
438 #[stable]
439 impl<'a> Iterator for Drain<'a> {
440 type Item = Box<Any + 'static>;
441
442 #[inline]
443 fn next(&mut self) -> Option<Box<Any + 'static>> {
444 self.inner.next().map(|item| item.1)
445 }
446
447 #[inline]
448 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
449 }
450
451 #[stable]
452 impl Iterator for IntoIter {
453 type Item = Box<Any + 'static>;
454
455 #[inline]
456 fn next(&mut self) -> Option<Box<Any + 'static>> {
457 self.inner.next().map(|item| item.1)
458 }
459
460 #[inline]
461 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
462 }
463
464 #[bench]
465 fn bench_insertion(b: &mut ::test::Bencher) {
466 b.iter(|| {
467 let mut data = AnyMap::new();
468 for _ in range(0, 100) {
469 let _ = data.insert(42i32);
470 }
471 })
472 }
473
474 #[bench]
475 fn bench_get_missing(b: &mut ::test::Bencher) {
476 b.iter(|| {
477 let data = AnyMap::new();
478 for _ in range(0, 100) {
479 assert_eq!(data.get(), None::<&i32>);
480 }
481 })
482 }
483
484 #[bench]
485 fn bench_get_present(b: &mut ::test::Bencher) {
486 b.iter(|| {
487 let mut data = AnyMap::new();
488 let _ = data.insert(42i32);
489 // These inner loops are a feeble attempt to drown the other factors.
490 for _ in range(0, 100) {
491 assert_eq!(data.get(), Some(&42i32));
492 }
493 })
494 }
495
496 #[test]
497 fn test_entry() {
498 #[derive(Debug, PartialEq)] struct A(i32);
499 #[derive(Debug, PartialEq)] struct B(i32);
500 #[derive(Debug, PartialEq)] struct C(i32);
501 #[derive(Debug, PartialEq)] struct D(i32);
502 #[derive(Debug, PartialEq)] struct E(i32);
503 #[derive(Debug, PartialEq)] struct F(i32);
504 #[derive(Debug, PartialEq)] struct J(i32);
505
506 let mut map: AnyMap = AnyMap::new();
507 assert_eq!(map.insert(A(10)), None);
508 assert_eq!(map.insert(B(20)), None);
509 assert_eq!(map.insert(C(30)), None);
510 assert_eq!(map.insert(D(40)), None);
511 assert_eq!(map.insert(E(50)), None);
512 assert_eq!(map.insert(F(60)), None);
513
514 // Existing key (insert)
515 match map.entry::<A>() {
516 Entry::Vacant(_) => unreachable!(),
517 Entry::Occupied(mut view) => {
518 assert_eq!(view.get(), &A(10));
519 assert_eq!(view.insert(A(100)), A(10));
520 }
521 }
522 assert_eq!(map.get::<A>().unwrap(), &A(100));
523 assert_eq!(map.len(), 6);
524
525
526 // Existing key (update)
527 match map.entry::<B>() {
528 Entry::Vacant(_) => unreachable!(),
529 Entry::Occupied(mut view) => {
530 let v = view.get_mut();
531 let new_v = B(v.0 * 10);
532 *v = new_v;
533 }
534 }
535 assert_eq!(map.get().unwrap(), &B(200));
536 assert_eq!(map.len(), 6);
537
538
539 // Existing key (remove)
540 match map.entry::<C>() {
541 Entry::Vacant(_) => unreachable!(),
542 Entry::Occupied(view) => {
543 assert_eq!(view.remove(), C(30));
544 }
545 }
546 assert_eq!(map.get::<C>(), None);
547 assert_eq!(map.len(), 5);
548
549
550 // Inexistent key (insert)
551 match map.entry::<J>() {
552 Entry::Occupied(_) => unreachable!(),
553 Entry::Vacant(view) => {
554 assert_eq!(*view.insert(J(1000)), J(1000));
555 }
556 }
557 assert_eq!(map.get::<J>().unwrap(), &J(1000));
558 assert_eq!(map.len(), 6);
559 }