097b6bd5324efa9e729dfde8655f71887279f221
[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::marker::PhantomData;
14
15 use raw::RawAnyMap;
16 use unchecked_any::UncheckedAnyExt;
17
18 macro_rules! impl_common_methods {
19 (
20 field: $t:ident.$field:ident;
21 new() => $new:expr;
22 with_capacity($with_capacity_arg:ident) => $with_capacity:expr;
23 ) => {
24 impl $t {
25 /// Create an empty collection.
26 #[inline]
27 pub fn new() -> $t {
28 $t {
29 $field: $new,
30 }
31 }
32
33 /// Creates an empty collection with the given initial capacity.
34 #[inline]
35 pub fn with_capacity($with_capacity_arg: usize) -> $t {
36 $t {
37 $field: $with_capacity,
38 }
39 }
40
41 /// Returns the number of elements the collection can hold without reallocating.
42 #[inline]
43 pub fn capacity(&self) -> usize {
44 self.$field.capacity()
45 }
46
47 /// Reserves capacity for at least `additional` more elements to be inserted
48 /// in the collection. The collection may reserve more space to avoid
49 /// frequent reallocations.
50 ///
51 /// # Panics
52 ///
53 /// Panics if the new allocation size overflows `usize`.
54 #[inline]
55 pub fn reserve(&mut self, additional: usize) {
56 self.$field.reserve(additional)
57 }
58
59 /// Shrinks the capacity of the collection as much as possible. It will drop
60 /// down as much as possible while maintaining the internal rules
61 /// and possibly leaving some space in accordance with the resize policy.
62 #[inline]
63 pub fn shrink_to_fit(&mut self) {
64 self.$field.shrink_to_fit()
65 }
66
67 /// Returns the number of items in the collection.
68 #[inline]
69 pub fn len(&self) -> usize {
70 self.$field.len()
71 }
72
73 /// Returns true if there are no items in the collection.
74 #[inline]
75 pub fn is_empty(&self) -> bool {
76 self.$field.is_empty()
77 }
78
79 /// Removes all items from the collection. Keeps the allocated memory for reuse.
80 #[inline]
81 pub fn clear(&mut self) {
82 self.$field.clear()
83 }
84 }
85 }
86 }
87
88 mod unchecked_any;
89 pub mod raw;
90
91 /// A collection containing zero or one values for any given type and allowing convenient,
92 /// type-safe access to those values.
93 ///
94 /// ```rust
95 /// # use anymap::AnyMap;
96 /// let mut data = AnyMap::new();
97 /// assert_eq!(data.get(), None::<&i32>);
98 /// data.insert(42i32);
99 /// assert_eq!(data.get(), Some(&42i32));
100 /// data.remove::<i32>();
101 /// assert_eq!(data.get::<i32>(), None);
102 ///
103 /// #[derive(PartialEq, Debug)]
104 /// struct Foo {
105 /// str: String,
106 /// }
107 ///
108 /// assert_eq!(data.get::<Foo>(), None);
109 /// data.insert(Foo { str: format!("foo") });
110 /// assert_eq!(data.get(), Some(&Foo { str: format!("foo") }));
111 /// data.get_mut::<Foo>().map(|foo| foo.str.push('t'));
112 /// assert_eq!(&*data.get::<Foo>().unwrap().str, "foot");
113 /// ```
114 ///
115 /// Values containing non-static references are not permitted.
116 #[derive(Debug)]
117 pub struct AnyMap {
118 raw: RawAnyMap,
119 }
120
121 impl_common_methods! {
122 field: AnyMap.raw;
123 new() => RawAnyMap::new();
124 with_capacity(capacity) => RawAnyMap::with_capacity(capacity);
125 }
126
127 impl AnyMap {
128 /// Returns a reference to the value stored in the collection for the type `T`, if it exists.
129 pub fn get<T: Any>(&self) -> Option<&T> {
130 self.raw.get(&TypeId::of::<T>())
131 .map(|any| unsafe { any.downcast_ref_unchecked::<T>() })
132 }
133
134 /// Returns a mutable reference to the value stored in the collection for the type `T`,
135 /// if it exists.
136 pub fn get_mut<T: Any>(&mut self) -> Option<&mut T> {
137 self.raw.get_mut(&TypeId::of::<T>())
138 .map(|any| unsafe { any.downcast_mut_unchecked::<T>() })
139 }
140
141 /// Sets the value stored in the collection for the type `T`.
142 /// If the collection already had a value of type `T`, that value is returned.
143 /// Otherwise, `None` is returned.
144 pub fn insert<T: Any>(&mut self, value: T) -> Option<T> {
145 unsafe {
146 self.raw.insert(TypeId::of::<T>(), Box::new(value))
147 .map(|any| *any.downcast_unchecked::<T>())
148 }
149 }
150
151 /// Removes the `T` value from the collection,
152 /// returning it if there was one or `None` if there was not.
153 pub fn remove<T: Any>(&mut self) -> Option<T> {
154 self.raw.remove(&TypeId::of::<T>())
155 .map(|any| *unsafe { any.downcast_unchecked::<T>() })
156 }
157
158 /// Returns true if the collection contains a value of type `T`.
159 #[inline]
160 pub fn contains<T: Any>(&self) -> bool {
161 self.raw.contains_key(&TypeId::of::<T>())
162 }
163
164 /// Gets the entry for the given type in the collection for in-place manipulation
165 pub fn entry<T: Any>(&mut self) -> Entry<T> {
166 match self.raw.entry(TypeId::of::<T>()) {
167 raw::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
168 inner: e,
169 type_: PhantomData,
170 }),
171 raw::Entry::Vacant(e) => Entry::Vacant(VacantEntry {
172 inner: e,
173 type_: PhantomData,
174 }),
175 }
176 }
177
178 /// Get a reference to the raw untyped map underlying the `AnyMap`.
179 ///
180 /// Normal users will not need to use this, but generic libraries working with an `AnyMap` may
181 /// just find a use for it occasionally.
182 #[inline]
183 pub fn as_raw(&self) -> &RawAnyMap {
184 &self.raw
185 }
186
187 /// Get a mutable reference to the raw untyped map underlying the `AnyMap`.
188 ///
189 /// Normal users will not need to use this, but generic libraries working with an `AnyMap` may
190 /// just find a use for it occasionally.
191 #[inline]
192 pub fn as_raw_mut(&mut self) -> &mut RawAnyMap {
193 &mut self.raw
194 }
195
196 /// Convert the `AnyMap` into the raw untyped map that underlyies it.
197 ///
198 /// Normal users will not need to use this, but generic libraries working with an `AnyMap` may
199 /// just find a use for it occasionally.
200 #[inline]
201 pub fn into_raw(self) -> RawAnyMap {
202 self.raw
203 }
204
205 /// Convert a raw untyped map into an `AnyMap`.
206 ///
207 /// Normal users will not need to use this, but generic libraries working with an `AnyMap` may
208 /// just find a use for it occasionally.
209 #[inline]
210 pub fn from_raw(raw: RawAnyMap) -> AnyMap {
211 AnyMap {
212 raw: raw,
213 }
214 }
215 }
216
217 /// A view into a single occupied location in an `AnyMap`.
218 pub struct OccupiedEntry<'a, V: 'a> {
219 inner: raw::OccupiedEntry<'a>,
220 type_: PhantomData<V>,
221 }
222
223 /// A view into a single empty location in an `AnyMap`.
224 pub struct VacantEntry<'a, V: 'a> {
225 inner: raw::VacantEntry<'a>,
226 type_: PhantomData<V>,
227 }
228
229 /// A view into a single location in an `AnyMap`, which may be vacant or occupied.
230 pub enum Entry<'a, V: 'a> {
231 /// An occupied Entry
232 Occupied(OccupiedEntry<'a, V>),
233 /// A vacant Entry
234 Vacant(VacantEntry<'a, V>),
235 }
236
237 impl<'a, V: Any + Clone> Entry<'a, V> {
238 /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
239 pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, V>> {
240 match self {
241 Entry::Occupied(inner) => Ok(inner.into_mut()),
242 Entry::Vacant(inner) => Err(inner),
243 }
244 }
245 }
246
247 impl<'a, V: Any> OccupiedEntry<'a, V> {
248 /// Gets a reference to the value in the entry
249 pub fn get(&self) -> &V {
250 unsafe { self.inner.get().downcast_ref_unchecked() }
251 }
252
253 /// Gets a mutable reference to the value in the entry
254 pub fn get_mut(&mut self) -> &mut V {
255 unsafe { self.inner.get_mut().downcast_mut_unchecked() }
256 }
257
258 /// Converts the OccupiedEntry into a mutable reference to the value in the entry
259 /// with a lifetime bound to the collection itself
260 pub fn into_mut(self) -> &'a mut V {
261 unsafe { self.inner.into_mut().downcast_mut_unchecked() }
262 }
263
264 /// Sets the value of the entry, and returns the entry's old value
265 pub fn insert(&mut self, value: V) -> V {
266 unsafe { *self.inner.insert(Box::new(value)).downcast_unchecked() }
267 }
268
269 /// Takes the value out of the entry, and returns it
270 pub fn remove(self) -> V {
271 unsafe { *self.inner.remove().downcast_unchecked() }
272 }
273 }
274
275 impl<'a, V: Any> VacantEntry<'a, V> {
276 /// Sets the value of the entry with the VacantEntry's key,
277 /// and returns a mutable reference to it
278 pub fn insert(self, value: V) -> &'a mut V {
279 unsafe { self.inner.insert(Box::new(value)).downcast_mut_unchecked() }
280 }
281 }
282
283 #[bench]
284 fn bench_insertion(b: &mut ::test::Bencher) {
285 b.iter(|| {
286 let mut data = AnyMap::new();
287 for _ in 0..100 {
288 let _ = data.insert(42);
289 }
290 })
291 }
292
293 #[bench]
294 fn bench_get_missing(b: &mut ::test::Bencher) {
295 b.iter(|| {
296 let data = AnyMap::new();
297 for _ in 0..100 {
298 assert_eq!(data.get(), None::<&i32>);
299 }
300 })
301 }
302
303 #[bench]
304 fn bench_get_present(b: &mut ::test::Bencher) {
305 b.iter(|| {
306 let mut data = AnyMap::new();
307 let _ = data.insert(42);
308 // These inner loops are a feeble attempt to drown the other factors.
309 for _ in 0..100 {
310 assert_eq!(data.get(), Some(&42));
311 }
312 })
313 }
314
315 #[test]
316 fn test_entry() {
317 #[derive(Debug, PartialEq)] struct A(i32);
318 #[derive(Debug, PartialEq)] struct B(i32);
319 #[derive(Debug, PartialEq)] struct C(i32);
320 #[derive(Debug, PartialEq)] struct D(i32);
321 #[derive(Debug, PartialEq)] struct E(i32);
322 #[derive(Debug, PartialEq)] struct F(i32);
323 #[derive(Debug, PartialEq)] struct J(i32);
324
325 let mut map: AnyMap = AnyMap::new();
326 assert_eq!(map.insert(A(10)), None);
327 assert_eq!(map.insert(B(20)), None);
328 assert_eq!(map.insert(C(30)), None);
329 assert_eq!(map.insert(D(40)), None);
330 assert_eq!(map.insert(E(50)), None);
331 assert_eq!(map.insert(F(60)), None);
332
333 // Existing key (insert)
334 match map.entry::<A>() {
335 Entry::Vacant(_) => unreachable!(),
336 Entry::Occupied(mut view) => {
337 assert_eq!(view.get(), &A(10));
338 assert_eq!(view.insert(A(100)), A(10));
339 }
340 }
341 assert_eq!(map.get::<A>().unwrap(), &A(100));
342 assert_eq!(map.len(), 6);
343
344
345 // Existing key (update)
346 match map.entry::<B>() {
347 Entry::Vacant(_) => unreachable!(),
348 Entry::Occupied(mut view) => {
349 let v = view.get_mut();
350 let new_v = B(v.0 * 10);
351 *v = new_v;
352 }
353 }
354 assert_eq!(map.get().unwrap(), &B(200));
355 assert_eq!(map.len(), 6);
356
357
358 // Existing key (remove)
359 match map.entry::<C>() {
360 Entry::Vacant(_) => unreachable!(),
361 Entry::Occupied(view) => {
362 assert_eq!(view.remove(), C(30));
363 }
364 }
365 assert_eq!(map.get::<C>(), None);
366 assert_eq!(map.len(), 5);
367
368
369 // Inexistent key (insert)
370 match map.entry::<J>() {
371 Entry::Occupied(_) => unreachable!(),
372 Entry::Vacant(view) => {
373 assert_eq!(*view.insert(J(1000)), J(1000));
374 }
375 }
376 assert_eq!(map.get::<J>().unwrap(), &J(1000));
377 assert_eq!(map.len(), 6);
378 }