anymap2/
lib.rs

1//! This crate provides the `AnyMap` type, a safe and convenient store for one
2//! value of each type.
3
4#![warn(missing_docs, unused_results)]
5#![allow(unused_doc_comments)]
6
7//#![deny(warnings)]
8use std::{any::TypeId, marker::PhantomData};
9
10use crate::{
11    any::{Any, IntoBox, UncheckedAnyExt},
12    raw::RawMap,
13};
14
15macro_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 { $field: $new }
26            }
27
28            /// Creates an empty collection with the given initial capacity.
29            #[inline]
30            pub fn with_capacity($with_capacity_arg: usize) -> $t<A> {
31                $t {
32                    $field: $with_capacity,
33                }
34            }
35
36            /// Returns the number of elements the collection can hold without
37            /// reallocating.
38            #[inline]
39            pub fn capacity(&self) -> usize {
40                self.$field.capacity()
41            }
42
43            /// Reserves capacity for at least `additional` more elements to be inserted
44            /// in the collection. The collection may reserve more space to avoid
45            /// frequent reallocations.
46            ///
47            /// # Panics
48            ///
49            /// Panics if the new allocation size overflows `usize`.
50            #[inline]
51            pub fn reserve(&mut self, additional: usize) {
52                self.$field.reserve(additional)
53            }
54
55            /// Shrinks the capacity of the collection as much as possible. It will drop
56            /// down as much as possible while maintaining the internal rules
57            /// and possibly leaving some space in accordance with the resize policy.
58            #[inline]
59            pub fn shrink_to_fit(&mut self) {
60                self.$field.shrink_to_fit()
61            }
62
63            /// Returns the number of items in the collection.
64            #[inline]
65            pub fn len(&self) -> usize {
66                self.$field.len()
67            }
68
69            /// Returns true if there are no items in the collection.
70            #[inline]
71            pub fn is_empty(&self) -> bool {
72                self.$field.is_empty()
73            }
74
75            /// Removes all items from the collection. Keeps the allocated memory for
76            /// reuse.
77            #[inline]
78            pub fn clear(&mut self) {
79                self.$field.clear()
80            }
81        }
82
83        impl<A: ?Sized + UncheckedAnyExt> Default for $t<A> {
84            #[inline]
85            fn default() -> $t<A> {
86                $t::new()
87            }
88        }
89    };
90}
91
92pub mod any;
93pub mod raw;
94
95/// A collection containing zero or one values for any given type and allowing
96/// convenient, type-safe access to those values.
97///
98/// The type parameter `A` allows you to use a different value type; normally
99/// you will want it to be `anymap::any::Any`, but there are other choices:
100///
101/// - If you want the entire map to be cloneable, use `CloneAny` instead of
102///   `Any`.
103/// - You can add on `+ Send` and/or `+ Sync` (e.g. `Map<Any + Send>`) to add
104///   those bounds.
105///
106/// ```rust
107/// # use anymap2::AnyMap;
108/// let mut data = AnyMap::new();
109/// assert_eq!(data.get(), None::<&i32>);
110/// data.insert(42i32);
111/// assert_eq!(data.get(), Some(&42i32));
112/// data.remove::<i32>();
113/// assert_eq!(data.get::<i32>(), None);
114///
115/// #[derive(Clone, PartialEq, Debug)]
116/// struct Foo {
117///     str: String,
118/// }
119///
120/// assert_eq!(data.get::<Foo>(), None);
121/// data.insert(Foo {
122///     str: format!("foo"),
123/// });
124/// assert_eq!(
125///     data.get(),
126///     Some(&Foo {
127///         str: format!("foo")
128///     })
129/// );
130/// data.get_mut::<Foo>().map(|foo| foo.str.push('t'));
131/// assert_eq!(&*data.get::<Foo>().unwrap().str, "foot");
132/// ```
133///
134/// Values containing non-static references are not permitted.
135#[derive(Debug)]
136pub struct Map<A: ?Sized + UncheckedAnyExt = dyn Any> {
137    raw: RawMap<A>,
138}
139
140// #[derive(Clone)] would want A to implement Clone, but in reality it’s only
141// Box<A> that can.
142impl<A: ?Sized + UncheckedAnyExt> Clone for Map<A>
143where
144    Box<A>: Clone,
145{
146    #[inline]
147    fn clone(&self) -> Map<A> {
148        Map {
149            raw: self.raw.clone(),
150        }
151    }
152}
153
154/// The most common type of `Map`: just using `Any`.
155///
156/// Why is this a separate type alias rather than a default value for `Map<A>`?
157/// `Map::new()` doesn’t seem to be happy to infer that it should go with the
158/// default value. It’s a bit sad, really. Ah well, I guess this approach will
159/// do.
160pub type AnyMap = Map<dyn Any>;
161
162/// Sync version
163pub type SendSyncAnyMap = Map<dyn Any + Send + Sync>;
164
165impl_common_methods! {
166    field: Map.raw;
167    new() => RawMap::new();
168    with_capacity(capacity) => RawMap::with_capacity(capacity);
169}
170
171impl<A: ?Sized + UncheckedAnyExt> Map<A> {
172    /// Returns a reference to the value stored in the collection for the type
173    /// `T`, if it exists.
174    #[inline]
175    pub fn get<T: IntoBox<A>>(&self) -> Option<&T> {
176        self.raw
177            .get(&TypeId::of::<T>())
178            .map(|any| unsafe { any.downcast_ref_unchecked::<T>() })
179    }
180
181    /// Returns a mutable reference to the value stored in the collection for
182    /// the type `T`, if it exists.
183    #[inline]
184    pub fn get_mut<T: IntoBox<A>>(&mut self) -> Option<&mut T> {
185        self.raw
186            .get_mut(&TypeId::of::<T>())
187            .map(|any| unsafe { any.downcast_mut_unchecked::<T>() })
188    }
189
190    /// Sets the value stored in the collection for the type `T`.
191    /// If the collection already had a value of type `T`, that value is
192    /// returned. Otherwise, `None` is returned.
193    #[inline]
194    pub fn insert<T: IntoBox<A>>(&mut self, value: T) -> Option<T> {
195        unsafe {
196            self.raw
197                .insert(TypeId::of::<T>(), value.into_box())
198                .map(|any| *any.downcast_unchecked::<T>())
199        }
200    }
201
202    /// Removes the `T` value from the collection,
203    /// returning it if there was one or `None` if there was not.
204    #[inline]
205    pub fn remove<T: IntoBox<A>>(&mut self) -> Option<T> {
206        self.raw
207            .remove(&TypeId::of::<T>())
208            .map(|any| *unsafe { any.downcast_unchecked::<T>() })
209    }
210
211    /// Returns true if the collection contains a value of type `T`.
212    #[inline]
213    pub fn contains<T: IntoBox<A>>(&self) -> bool {
214        self.raw.contains_key(&TypeId::of::<T>())
215    }
216
217    /// Gets the entry for the given type in the collection for in-place
218    /// manipulation
219    #[inline]
220    pub fn entry<T: IntoBox<A>>(&mut self) -> Entry<A, T> {
221        match self.raw.entry(TypeId::of::<T>()) {
222            raw::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
223                inner: e,
224                type_: PhantomData,
225            }),
226            raw::Entry::Vacant(e) => Entry::Vacant(VacantEntry {
227                inner: e,
228                type_: PhantomData,
229            }),
230        }
231    }
232}
233
234impl<A: ?Sized + UncheckedAnyExt> AsRef<RawMap<A>> for Map<A> {
235    #[inline]
236    fn as_ref(&self) -> &RawMap<A> {
237        &self.raw
238    }
239}
240
241impl<A: ?Sized + UncheckedAnyExt> AsMut<RawMap<A>> for Map<A> {
242    #[inline]
243    fn as_mut(&mut self) -> &mut RawMap<A> {
244        &mut self.raw
245    }
246}
247
248impl<A: ?Sized + UncheckedAnyExt> From<Map<A>> for RawMap<A> {
249    #[inline]
250    fn from(map: Map<A>) -> Self {
251        map.raw
252    }
253}
254
255/// A view into a single occupied location in an `Map`.
256pub struct OccupiedEntry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
257    inner: raw::OccupiedEntry<'a, A>,
258    type_: PhantomData<V>,
259}
260
261/// A view into a single empty location in an `Map`.
262pub struct VacantEntry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
263    inner: raw::VacantEntry<'a, A>,
264    type_: PhantomData<V>,
265}
266
267/// A view into a single location in an `Map`, which may be vacant or occupied.
268pub enum Entry<'a, A: ?Sized + UncheckedAnyExt, V: 'a> {
269    /// An occupied Entry
270    Occupied(OccupiedEntry<'a, A, V>),
271    /// A vacant Entry
272    Vacant(VacantEntry<'a, A, V>),
273}
274
275impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> Entry<'a, A, V> {
276    /// Ensures a value is in the entry by inserting the default if empty, and
277    /// returns a mutable reference to the value in the entry.
278    #[inline]
279    pub fn or_insert(self, default: V) -> &'a mut V {
280        match self {
281            Entry::Occupied(inner) => inner.into_mut(),
282            Entry::Vacant(inner) => inner.insert(default),
283        }
284    }
285
286    /// Ensures a value is in the entry by inserting the result of the default
287    /// function if empty, and returns a mutable reference to the value in
288    /// the entry.
289    #[inline]
290    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
291        match self {
292            Entry::Occupied(inner) => inner.into_mut(),
293            Entry::Vacant(inner) => inner.insert(default()),
294        }
295    }
296}
297
298impl<'a, A: ?Sized + UncheckedAnyExt, V: Default + IntoBox<A>> Entry<'a, A, V> {
299    /// Ensures a value is in the entry by inserting the default value if empty,
300    /// and returns a mutable reference to the value in the entry.
301    ///
302    /// # Examples
303    ///
304    /// ```
305    /// # use anymap2::AnyMap;
306    /// let mut data = AnyMap::new();
307    /// {
308    ///     let r = data.entry::<i32>().or_default();
309    ///     assert_eq!(r, &mut 0);
310    ///     *r = 1;
311    /// }
312    /// assert_eq!(data.get(), Some(&1));
313    /// assert_eq!(data.entry::<i32>().or_default(), &mut 1);
314    /// ```
315    pub fn or_default(self) -> &'a mut V {
316        match self {
317            Entry::Occupied(entry) => entry.into_mut(),
318            Entry::Vacant(entry) => entry.insert(Default::default()),
319        }
320    }
321}
322
323impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> OccupiedEntry<'a, A, V> {
324    /// Gets a reference to the value in the entry
325    #[inline]
326    pub fn get(&self) -> &V {
327        unsafe { self.inner.get().downcast_ref_unchecked() }
328    }
329
330    /// Gets a mutable reference to the value in the entry
331    #[inline]
332    pub fn get_mut(&mut self) -> &mut V {
333        unsafe { self.inner.get_mut().downcast_mut_unchecked() }
334    }
335
336    /// Converts the OccupiedEntry into a mutable reference to the value in the
337    /// entry with a lifetime bound to the collection itself
338    #[inline]
339    pub fn into_mut(self) -> &'a mut V {
340        unsafe { self.inner.into_mut().downcast_mut_unchecked() }
341    }
342
343    /// Sets the value of the entry, and returns the entry's old value
344    #[inline]
345    pub fn insert(&mut self, value: V) -> V {
346        unsafe { *self.inner.insert(value.into_box()).downcast_unchecked() }
347    }
348
349    /// Takes the value out of the entry, and returns it
350    #[inline]
351    pub fn remove(self) -> V {
352        unsafe { *self.inner.remove().downcast_unchecked() }
353    }
354}
355
356impl<'a, A: ?Sized + UncheckedAnyExt, V: IntoBox<A>> VacantEntry<'a, A, V> {
357    /// Sets the value of the entry with the VacantEntry's key,
358    /// and returns a mutable reference to it
359    #[inline]
360    pub fn insert(self, value: V) -> &'a mut V {
361        unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() }
362    }
363}
364
365#[cfg(test)]
366mod tests {
367    use crate::{
368        any::{Any, CloneAny, CloneAnySend, CloneAnySendSync, CloneAnySync},
369        AnyMap, Entry, Map,
370    };
371
372    #[derive(Clone, Debug, PartialEq)]
373    struct A(i32);
374    #[derive(Clone, Debug, PartialEq)]
375    struct B(i32);
376    #[derive(Clone, Debug, PartialEq)]
377    struct C(i32);
378    #[derive(Clone, Debug, PartialEq)]
379    struct D(i32);
380    #[derive(Clone, Debug, PartialEq)]
381    struct E(i32);
382    #[derive(Clone, Debug, PartialEq)]
383    struct F(i32);
384    #[derive(Clone, Debug, PartialEq)]
385    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                // Existing key (update)
411                match map.entry::<B>() {
412                    Entry::Vacant(_) => unreachable!(),
413                    Entry::Occupied(mut view) => {
414                        let v = view.get_mut();
415                        let new_v = B(v.0 * 10);
416                        *v = new_v;
417                    }
418                }
419                assert_eq!(map.get::<B>().unwrap(), &B(200));
420                assert_eq!(map.len(), 6);
421
422                // Existing key (remove)
423                match map.entry::<C>() {
424                    Entry::Vacant(_) => unreachable!(),
425                    Entry::Occupied(view) => {
426                        assert_eq!(view.remove(), C(30));
427                    }
428                }
429                assert_eq!(map.get::<C>(), None);
430                assert_eq!(map.len(), 5);
431
432                // Inexistent key (insert)
433                match map.entry::<J>() {
434                    Entry::Occupied(_) => unreachable!(),
435                    Entry::Vacant(view) => {
436                        assert_eq!(*view.insert(J(1000)), J(1000));
437                    }
438                }
439                assert_eq!(map.get::<J>().unwrap(), &J(1000));
440                assert_eq!(map.len(), 6);
441
442                // Entry.or_insert on existing key
443                map.entry::<B>().or_insert(B(71)).0 += 1;
444                assert_eq!(map.get::<B>().unwrap(), &B(201));
445                assert_eq!(map.len(), 6);
446
447                // Entry.or_insert on nonexisting key
448                map.entry::<C>().or_insert(C(300)).0 += 1;
449                assert_eq!(map.get::<C>().unwrap(), &C(301));
450                assert_eq!(map.len(), 7);
451            }
452        };
453    }
454
455    test_entry!(test_entry_any, AnyMap);
456    test_entry!(test_entry_cloneany, Map<dyn CloneAny>);
457
458    #[test]
459    fn test_default() {
460        let map: AnyMap = Default::default();
461        assert_eq!(map.len(), 0);
462    }
463
464    #[test]
465    fn test_clone() {
466        let mut map: Map<dyn CloneAny> = Map::new();
467        let _ = map.insert(A(1));
468        let _ = map.insert(B(2));
469        let _ = map.insert(D(3));
470        let _ = map.insert(E(4));
471        let _ = map.insert(F(5));
472        let _ = map.insert(J(6));
473        let map2 = map.clone();
474        assert_eq!(map2.len(), 6);
475        assert_eq!(map2.get::<A>(), Some(&A(1)));
476        assert_eq!(map2.get::<B>(), Some(&B(2)));
477        assert_eq!(map2.get::<C>(), None);
478        assert_eq!(map2.get::<D>(), Some(&D(3)));
479        assert_eq!(map2.get::<E>(), Some(&E(4)));
480        assert_eq!(map2.get::<F>(), Some(&F(5)));
481        assert_eq!(map2.get::<J>(), Some(&J(6)));
482    }
483
484    #[test]
485    fn test_varieties() {
486        fn assert_send<T: Send>() {}
487        fn assert_sync<T: Sync>() {}
488        fn assert_clone<T: Clone>() {}
489        fn assert_debug<T: ::std::fmt::Debug>() {}
490        assert_send::<Map<dyn Any + Send>>();
491        assert_send::<Map<dyn Any + Send + Sync>>();
492        assert_sync::<Map<dyn Any + Sync>>();
493        assert_sync::<Map<dyn Any + Send + Sync>>();
494        assert_debug::<Map<dyn Any>>();
495        assert_debug::<Map<dyn Any + Send>>();
496        assert_debug::<Map<dyn Any + Sync>>();
497        assert_debug::<Map<dyn Any + Send + Sync>>();
498        assert_send::<Map<dyn CloneAnySend + Send>>();
499        assert_send::<Map<dyn CloneAnySendSync + Send + Sync>>();
500        assert_sync::<Map<dyn CloneAnySync + Sync>>();
501        assert_sync::<Map<dyn CloneAnySendSync + Send + Sync>>();
502        assert_clone::<Map<dyn CloneAnySend + Send>>();
503        assert_clone::<Map<dyn CloneAnySendSync + Send + Sync>>();
504        assert_clone::<Map<dyn CloneAnySync + Sync>>();
505        assert_clone::<Map<dyn CloneAnySendSync + Send + Sync>>();
506        assert_debug::<Map<dyn CloneAny>>();
507        assert_debug::<Map<dyn CloneAnySend + Send>>();
508        assert_debug::<Map<dyn CloneAnySync + Sync>>();
509        assert_debug::<Map<dyn CloneAnySendSync + Send + Sync>>();
510    }
511}