d2b85aaf6ac2536e21bb04e1124f804feb1dce1a
[anymap] / src / lib.rs
1 //! This crate provides the `AnyMap` type, a safe and convenient store for one value of each type.
2
3 #![cfg_attr(all(feature = "bench", test), feature(test))]
4 #![warn(missing_docs, unused_results)]
5
6 #[cfg(all(feature = "bench", test))]
7 extern crate test;
8
9 use std::any::TypeId;
10 use std::marker::PhantomData;
11
12 use raw::RawMap;
13 use any::{UncheckedAnyExt, IntoBox, Any};
14
15 macro_rules! impl_common_methods {
16 (
17 field: $t:ident.$field:ident;
18 new() => $new:expr;
19 with_capacity($with_capacity_arg:ident) => $with_capacity:expr;
20 ) => {
21 impl<A: ?Sized + UncheckedAnyExt> $t<A> {
22 /// Create an empty collection.
23 #[inline]
24 pub fn new() -> $t<A> {
25 $t {
26 $field: $new,
27 }
28 }
29
30 /// Creates an empty collection with the given initial capacity.
31 #[inline]
32 pub fn with_capacity($with_capacity_arg: usize) -> $t<A> {
33 $t {
34 $field: $with_capacity,
35 }
36 }
37
38 /// Returns the number of elements the collection can hold without reallocating.
39 #[inline]
40 pub fn capacity(&self) -> usize {
41 self.$field.capacity()
42 }
43
44 /// Reserves capacity for at least `additional` more elements to be inserted
45 /// in the collection. The collection may reserve more space to avoid
46 /// frequent reallocations.
47 ///
48 /// # Panics
49 ///
50 /// Panics if the new allocation size overflows `usize`.
51 #[inline]
52 pub fn reserve(&mut self, additional: usize) {
53 self.$field.reserve(additional)
54 }
55
56 /// Shrinks the capacity of the collection as much as possible. It will drop
57 /// down as much as possible while maintaining the internal rules
58 /// and possibly leaving some space in accordance with the resize policy.
59 #[inline]
60 pub fn shrink_to_fit(&mut self) {
61 self.$field.shrink_to_fit()
62 }
63
64 /// Returns the number of items in the collection.
65 #[inline]
66 pub fn len(&self) -> usize {
67 self.$field.len()
68 }
69
70 /// Returns true if there are no items in the collection.
71 #[inline]
72 pub fn is_empty(&self) -> bool {
73 self.$field.is_empty()
74 }
75
76 /// Removes all items from the collection. Keeps the allocated memory for reuse.
77 #[inline]
78 pub fn clear(&mut self) {
79 self.$field.clear()
80 }
81 }
82 }
83 }
84
85 pub mod any;
86 pub mod raw;
87
88 /// A collection containing zero or one values for any given type and allowing convenient,
89 /// type-safe access to those values.
90 ///
91 /// The type parameter `A` allows you to use a different value type; normally you will want it to
92 /// be `anymap::any::Any`, but there are other choices:
93 ///
94 /// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`.
95 /// - You can add on `+ Send` and/or `+ Sync` (e.g. `Map<Any + Send>`) to add those bounds.
96 ///
97 /// ```rust
98 /// # use anymap::AnyMap;
99 /// let mut data = AnyMap::new();
100 /// assert_eq!(data.get(), None::<&i32>);
101 /// data.insert(42i32);
102 /// assert_eq!(data.get(), Some(&42i32));
103 /// data.remove::<i32>();
104 /// assert_eq!(data.get::<i32>(), None);
105 ///
106 /// #[derive(Clone, PartialEq, Debug)]
107 /// struct Foo {
108 /// str: String,
109 /// }
110 ///
111 /// assert_eq!(data.get::<Foo>(), None);
112 /// data.insert(Foo { str: format!("foo") });
113 /// assert_eq!(data.get(), Some(&Foo { str: format!("foo") }));
114 /// data.get_mut::<Foo>().map(|foo| foo.str.push('t'));
115 /// assert_eq!(&*data.get::<Foo>().unwrap().str, "foot");
116 /// ```
117 ///
118 /// Values containing non-static references are not permitted.
119 #[derive(Debug)]
120 pub struct Map<A: ?Sized + UncheckedAnyExt = Any> {
121 raw: RawMap<A>,
122 }
123
124 // #[derive(Clone)] would want A to implement Clone, but in reality it’s only Box<A> that can.
125 impl<A: ?Sized + UncheckedAnyExt> Clone for Map<A> where Box<A>: Clone {
126 fn clone(&self) -> Map<A> {
127 Map {
128 raw: self.raw.clone(),
129 }
130 }
131 }
132
133 /// The most common type of `Map`: just using `Any`.
134 ///
135 /// Why is this a separate type alias rather than a default value for `Map<A>`? `Map::new()`
136 /// doesn’t seem to be happy to infer that it should go with the default value.
137 /// It’s a bit sad, really. Ah well, I guess this approach will do.
138 pub type AnyMap = Map<Any>;
139
140 impl_common_methods! {
141 field: Map.raw;
142 new() => RawMap::new();
143 with_capacity(capacity) => RawMap::with_capacity(capacity);
144 }
145
146 impl<A: ?Sized + UncheckedAnyExt> Map<A> {
147 /// Returns a reference to the value stored in the collection for the type `T`, if it exists.
148 pub fn get<T: IntoBox<A>>(&self) -> Option<&T> {
149 self.raw.get(&TypeId::of::<T>())
150 .map(|any| unsafe { any.downcast_ref_unchecked::<T>() })
151 }
152
153 /// Returns a mutable reference to the value stored in the collection for the type `T`,
154 /// if it exists.
155 pub fn get_mut<T: IntoBox<A>>(&mut self) -> Option<&mut T> {
156 self.raw.get_mut(&TypeId::of::<T>())
157 .map(|any| unsafe { any.downcast_mut_unchecked::<T>() })
158 }
159
160 /// Sets the value stored in the collection for the type `T`.
161 /// If the collection already had a value of type `T`, that value is returned.
162 /// Otherwise, `None` is returned.
163 pub fn insert<T: IntoBox<A>>(&mut self, value: T) -> Option<T> {
164 unsafe {
165 self.raw.insert(TypeId::of::<T>(), value.into_box())
166 .map(|any| *any.downcast_unchecked::<T>())
167 }
168 }
169
170 /// Removes the `T` value from the collection,
171 /// returning it if there was one or `None` if there was not.
172 pub fn remove<T: IntoBox<A>>(&mut self) -> Option<T> {
173 self.raw.remove(&TypeId::of::<T>())
174 .map(|any| *unsafe { any.downcast_unchecked::<T>() })
175 }
176
177 /// Returns true if the collection contains a value of type `T`.
178 #[inline]
179 pub fn contains<T: IntoBox<A>>(&self) -> bool {
180 self.raw.contains_key(&TypeId::of::<T>())
181 }
182
183 /// Gets the entry for the given type in the collection for in-place manipulation
184 pub fn entry<T: IntoBox<A>>(&mut self) -> Entry<A, T> {
185 match self.raw.entry(TypeId::of::<T>()) {
186 raw::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
187 inner: e,
188 type_: PhantomData,
189 }),
190 raw::Entry::Vacant(e) => Entry::Vacant(VacantEntry {
191 inner: e,
192 type_: PhantomData,
193 }),
194 }
195 }
196 }
197
198 impl<A: ?Sized + UncheckedAnyExt> AsRef<RawMap<A>> for Map<A> {
199 fn as_ref(&self) -> &RawMap<A> {
200 &self.raw
201 }
202 }
203
204 impl<A: ?Sized + UncheckedAnyExt> AsMut<RawMap<A>> for Map<A> {
205 fn as_mut(&mut self) -> &mut RawMap<A> {
206 &mut self.raw
207 }
208 }
209
210 impl<A: ?Sized + UncheckedAnyExt> Into<RawMap<A>> for Map<A> {
211 fn into(self) -> RawMap<A> {
212 self.raw
213 }
214 }
215
216 /// A view into a single occupied location in an `Map`.
217 pub struct OccupiedEntry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
218 inner: raw::OccupiedEntry<'a, A>,
219 type_: PhantomData<V>,
220 }
221
222 /// A view into a single empty location in an `Map`.
223 pub struct VacantEntry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
224 inner: raw::VacantEntry<'a, A>,
225 type_: PhantomData<V>,
226 }
227
228 /// A view into a single location in an `Map`, which may be vacant or occupied.
229 pub enum Entry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
230 /// An occupied Entry
231 Occupied(OccupiedEntry<'a, A, V>),
232 /// A vacant Entry
233 Vacant(VacantEntry<'a, A, V>),
234 }
235
236 impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> Entry<'a, A, V> {
237 /// Ensures a value is in the entry by inserting the default if empty, and returns
238 /// a mutable reference to the value in the entry.
239 pub fn or_insert(self, default: V) -> &'a mut V {
240 match self {
241 Entry::Occupied(inner) => inner.into_mut(),
242 Entry::Vacant(inner) => inner.insert(default),
243 }
244 }
245
246 /// Ensures a value is in the entry by inserting the result of the default function if empty,
247 /// and returns a mutable reference to the value in the entry.
248 pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
249 match self {
250 Entry::Occupied(inner) => inner.into_mut(),
251 Entry::Vacant(inner) => inner.insert(default()),
252 }
253 }
254 }
255
256 impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> OccupiedEntry<'a, A, V> {
257 /// Gets a reference to the value in the entry
258 pub fn get(&self) -> &V {
259 unsafe { self.inner.get().downcast_ref_unchecked() }
260 }
261
262 /// Gets a mutable reference to the value in the entry
263 pub fn get_mut(&mut self) -> &mut V {
264 unsafe { self.inner.get_mut().downcast_mut_unchecked() }
265 }
266
267 /// Converts the OccupiedEntry into a mutable reference to the value in the entry
268 /// with a lifetime bound to the collection itself
269 pub fn into_mut(self) -> &'a mut V {
270 unsafe { self.inner.into_mut().downcast_mut_unchecked() }
271 }
272
273 /// Sets the value of the entry, and returns the entry's old value
274 pub fn insert(&mut self, value: V) -> V {
275 unsafe { *self.inner.insert(value.into_box()).downcast_unchecked() }
276 }
277
278 /// Takes the value out of the entry, and returns it
279 pub fn remove(self) -> V {
280 unsafe { *self.inner.remove().downcast_unchecked() }
281 }
282 }
283
284 impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> VacantEntry<'a, A, V> {
285 /// Sets the value of the entry with the VacantEntry's key,
286 /// and returns a mutable reference to it
287 pub fn insert(self, value: V) -> &'a mut V {
288 unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() }
289 }
290 }
291
292 #[cfg(all(feature = "bench", test))]
293 mod bench {
294 use AnyMap;
295 use test::Bencher;
296 use test::black_box;
297
298 #[bench]
299 fn insertion(b: &mut Bencher) {
300 b.iter(|| {
301 let mut data = AnyMap::new();
302 for _ in 0..100 {
303 let _ = data.insert(42);
304 }
305 })
306 }
307
308 #[bench]
309 fn get_missing(b: &mut Bencher) {
310 b.iter(|| {
311 let data = AnyMap::new();
312 for _ in 0..100 {
313 assert_eq!(data.get(), None::<&i32>);
314 }
315 })
316 }
317
318 #[bench]
319 fn get_present(b: &mut Bencher) {
320 b.iter(|| {
321 let mut data = AnyMap::new();
322 let _ = data.insert(42);
323 // These inner loops are a feeble attempt to drown the other factors.
324 for _ in 0..100 {
325 assert_eq!(data.get(), Some(&42));
326 }
327 })
328 }
329
330 macro_rules! big_benchmarks {
331 ($name:ident, $($T:ident)*) => (
332 #[bench]
333 fn $name(b: &mut Bencher) {
334 $(
335 struct $T(&'static str);
336 )*
337
338 b.iter(|| {
339 let mut data = AnyMap::new();
340 $(
341 let _ = black_box(data.insert($T(stringify!($T))));
342 )*
343 $(
344 let _ = black_box(data.get::<$T>());
345 )*
346 })
347 }
348 );
349 }
350
351 // Caution: if the macro does too much (e.g. assertions) this goes from being slow to being
352 // *really* slow (like add a minute for each assertion on it) and memory-hungry (like, adding
353 // several hundred megabytes to the peak for each assertion).
354 big_benchmarks! {
355 insert_and_get_on_260_types,
356 A0 B0 C0 D0 E0 F0 G0 H0 I0 J0 K0 L0 M0 N0 O0 P0 Q0 R0 S0 T0 U0 V0 W0 X0 Y0 Z0
357 A1 B1 C1 D1 E1 F1 G1 H1 I1 J1 K1 L1 M1 N1 O1 P1 Q1 R1 S1 T1 U1 V1 W1 X1 Y1 Z1
358 A2 B2 C2 D2 E2 F2 G2 H2 I2 J2 K2 L2 M2 N2 O2 P2 Q2 R2 S2 T2 U2 V2 W2 X2 Y2 Z2
359 A3 B3 C3 D3 E3 F3 G3 H3 I3 J3 K3 L3 M3 N3 O3 P3 Q3 R3 S3 T3 U3 V3 W3 X3 Y3 Z3
360 A4 B4 C4 D4 E4 F4 G4 H4 I4 J4 K4 L4 M4 N4 O4 P4 Q4 R4 S4 T4 U4 V4 W4 X4 Y4 Z4
361 A5 B5 C5 D5 E5 F5 G5 H5 I5 J5 K5 L5 M5 N5 O5 P5 Q5 R5 S5 T5 U5 V5 W5 X5 Y5 Z5
362 A6 B6 C6 D6 E6 F6 G6 H6 I6 J6 K6 L6 M6 N6 O6 P6 Q6 R6 S6 T6 U6 V6 W6 X6 Y6 Z6
363 A7 B7 C7 D7 E7 F7 G7 H7 I7 J7 K7 L7 M7 N7 O7 P7 Q7 R7 S7 T7 U7 V7 W7 X7 Y7 Z7
364 A8 B8 C8 D8 E8 F8 G8 H8 I8 J8 K8 L8 M8 N8 O8 P8 Q8 R8 S8 T8 U8 V8 W8 X8 Y8 Z8
365 A9 B9 C9 D9 E9 F9 G9 H9 I9 J9 K9 L9 M9 N9 O9 P9 Q9 R9 S9 T9 U9 V9 W9 X9 Y9 Z9
366 }
367
368 big_benchmarks! {
369 insert_and_get_on_26_types,
370 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
371 }
372 }
373
374 #[cfg(test)]
375 mod tests {
376 use {Map, AnyMap, Entry};
377 use any::{Any, CloneAny};
378
379 #[derive(Clone, Debug, PartialEq)] struct A(i32);
380 #[derive(Clone, Debug, PartialEq)] struct B(i32);
381 #[derive(Clone, Debug, PartialEq)] struct C(i32);
382 #[derive(Clone, Debug, PartialEq)] struct D(i32);
383 #[derive(Clone, Debug, PartialEq)] struct E(i32);
384 #[derive(Clone, Debug, PartialEq)] struct F(i32);
385 #[derive(Clone, Debug, PartialEq)] struct J(i32);
386
387 macro_rules! test_entry {
388 ($name:ident, $init:ty) => {
389 #[test]
390 fn $name() {
391 let mut map = <$init>::new();
392 assert_eq!(map.insert(A(10)), None);
393 assert_eq!(map.insert(B(20)), None);
394 assert_eq!(map.insert(C(30)), None);
395 assert_eq!(map.insert(D(40)), None);
396 assert_eq!(map.insert(E(50)), None);
397 assert_eq!(map.insert(F(60)), None);
398
399 // Existing key (insert)
400 match map.entry::<A>() {
401 Entry::Vacant(_) => unreachable!(),
402 Entry::Occupied(mut view) => {
403 assert_eq!(view.get(), &A(10));
404 assert_eq!(view.insert(A(100)), A(10));
405 }
406 }
407 assert_eq!(map.get::<A>().unwrap(), &A(100));
408 assert_eq!(map.len(), 6);
409
410
411 // Existing key (update)
412 match map.entry::<B>() {
413 Entry::Vacant(_) => unreachable!(),
414 Entry::Occupied(mut view) => {
415 let v = view.get_mut();
416 let new_v = B(v.0 * 10);
417 *v = new_v;
418 }
419 }
420 assert_eq!(map.get::<B>().unwrap(), &B(200));
421 assert_eq!(map.len(), 6);
422
423
424 // Existing key (remove)
425 match map.entry::<C>() {
426 Entry::Vacant(_) => unreachable!(),
427 Entry::Occupied(view) => {
428 assert_eq!(view.remove(), C(30));
429 }
430 }
431 assert_eq!(map.get::<C>(), None);
432 assert_eq!(map.len(), 5);
433
434
435 // Inexistent key (insert)
436 match map.entry::<J>() {
437 Entry::Occupied(_) => unreachable!(),
438 Entry::Vacant(view) => {
439 assert_eq!(*view.insert(J(1000)), J(1000));
440 }
441 }
442 assert_eq!(map.get::<J>().unwrap(), &J(1000));
443 assert_eq!(map.len(), 6);
444
445 // Entry.or_insert on existing key
446 map.entry::<B>().or_insert(B(71)).0 += 1;
447 assert_eq!(map.get::<B>().unwrap(), &B(201));
448 assert_eq!(map.len(), 6);
449
450 // Entry.or_insert on nonexisting key
451 map.entry::<C>().or_insert(C(300)).0 += 1;
452 assert_eq!(map.get::<C>().unwrap(), &C(301));
453 assert_eq!(map.len(), 7);
454 }
455 }
456 }
457
458 test_entry!(test_entry_any, AnyMap);
459 test_entry!(test_entry_cloneany, Map<CloneAny>);
460
461 #[test]
462 fn test_clone() {
463 let mut map: Map<CloneAny> = Map::new();
464 let _ = map.insert(A(1));
465 let _ = map.insert(B(2));
466 let _ = map.insert(D(3));
467 let _ = map.insert(E(4));
468 let _ = map.insert(F(5));
469 let _ = map.insert(J(6));
470 let map2 = map.clone();
471 assert_eq!(map2.len(), 6);
472 assert_eq!(map2.get::<A>(), Some(&A(1)));
473 assert_eq!(map2.get::<B>(), Some(&B(2)));
474 assert_eq!(map2.get::<C>(), None);
475 assert_eq!(map2.get::<D>(), Some(&D(3)));
476 assert_eq!(map2.get::<E>(), Some(&E(4)));
477 assert_eq!(map2.get::<F>(), Some(&F(5)));
478 assert_eq!(map2.get::<J>(), Some(&J(6)));
479 }
480
481 #[test]
482 fn test_varieties() {
483 fn assert_send<T: Send>() { }
484 fn assert_sync<T: Sync>() { }
485 fn assert_clone<T: Clone>() { }
486 fn assert_debug<T: ::std::fmt::Debug>() { }
487 assert_send::<Map<Any + Send>>();
488 assert_send::<Map<Any + Send + Sync>>();
489 assert_sync::<Map<Any + Sync>>();
490 assert_sync::<Map<Any + Send + Sync>>();
491 assert_debug::<Map<Any>>();
492 assert_debug::<Map<Any + Send>>();
493 assert_debug::<Map<Any + Sync>>();
494 assert_debug::<Map<Any + Send + Sync>>();
495 assert_send::<Map<CloneAny + Send>>();
496 assert_send::<Map<CloneAny + Send + Sync>>();
497 assert_sync::<Map<CloneAny + Sync>>();
498 assert_sync::<Map<CloneAny + Send + Sync>>();
499 assert_clone::<Map<CloneAny + Send>>();
500 assert_clone::<Map<CloneAny + Send + Sync>>();
501 assert_clone::<Map<CloneAny + Sync>>();
502 assert_clone::<Map<CloneAny + Send + Sync>>();
503 assert_debug::<Map<CloneAny>>();
504 assert_debug::<Map<CloneAny + Send>>();
505 assert_debug::<Map<CloneAny + Sync>>();
506 assert_debug::<Map<CloneAny + Send + Sync>>();
507 }
508 }