about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/anymap/src/lib.rs370
1 files changed, 176 insertions, 194 deletions
diff --git a/crates/anymap/src/lib.rs b/crates/anymap/src/lib.rs
index 967c3769ec6..d8c6c889f78 100644
--- a/crates/anymap/src/lib.rs
+++ b/crates/anymap/src/lib.rs
@@ -10,21 +10,15 @@
 //! This crate has two independent features, each of which provides an implementation providing
 //! types `Map`, `AnyMap`, `OccupiedEntry`, `VacantEntry`, `Entry` and `RawMap`:
 //!
-#![cfg_attr(feature = "std", doc = " - **std** (default, *enabled* in this build):")]
-#![cfg_attr(not(feature = "std"), doc = " - **std** (default, *disabled* in this build):")]
+//! - **std** (default, *enabled* in this build):
 //!   an implementation using `std::collections::hash_map`, placed in the crate root
 //!   (e.g. `anymap::AnyMap`).
 //!
-#![cfg_attr(feature = "hashbrown", doc = " - **hashbrown** (optional; *enabled* in this build):")]
-#![cfg_attr(
-    not(feature = "hashbrown"),
-    doc = " - **hashbrown** (optional; *disabled* in this build):"
-)]
+//! - **hashbrown** (optional; *enabled* in this build):
 //!   an implementation using `alloc` and `hashbrown::hash_map`, placed in a module `hashbrown`
 //!   (e.g. `anymap::hashbrown::AnyMap`).
 
 #![warn(missing_docs, unused_results)]
-#![cfg_attr(not(feature = "std"), no_std)]
 
 use core::convert::TryInto;
 use core::hash::Hasher;
@@ -63,213 +57,201 @@ impl Hasher for TypeIdHasher {
     }
 }
 
-#[cfg(any(feature = "std", feature = "hashbrown"))]
-macro_rules! everything {
-    ($example_init:literal, $($parent:ident)::+ $(, $entry_generics:ty)?) => {
-        use core::any::{Any, TypeId};
-        use core::hash::BuildHasherDefault;
-        use core::marker::PhantomData;
+use core::any::{Any, TypeId};
+use core::hash::BuildHasherDefault;
+use core::marker::PhantomData;
 
-        #[cfg(not(feature = "std"))]
-        use alloc::boxed::Box;
+use ::std::collections::hash_map::{self, HashMap};
 
-        use ::$($parent)::+::hash_map::{self, HashMap};
+use crate::any::{Downcast, IntoBox};
 
-        use crate::any::{Downcast, IntoBox};
+/// Raw access to the underlying `HashMap`.
+///
+/// This alias is provided for convenience because of the ugly third generic parameter.
+pub type RawMap<A> = HashMap<TypeId, Box<A>, BuildHasherDefault<TypeIdHasher>>;
 
-        /// Raw access to the underlying `HashMap`.
-        ///
-        /// This alias is provided for convenience because of the ugly third generic parameter.
-        pub type RawMap<A> = HashMap<TypeId, Box<A>, BuildHasherDefault<TypeIdHasher>>;
+/// A collection containing zero or one values for any given type and allowing convenient,
+/// type-safe access to those values.
+///
+/// The type parameter `A` allows you to use a different value type; normally you will want
+/// it to be `core::any::Any` (also known as `std::any::Any`), but there are other choices:
+///
+/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with
+///   that, you can only add types that implement `Clone` to the map.
+/// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map<dyn Any + Send>`) to add those
+///   auto traits.
+///
+/// Cumulatively, there are thus six forms of map:
+///
+/// - <code>[Map]&lt;dyn [core::any::Any]&gt;</code>,
+///   also spelled [`AnyMap`] for convenience.
+/// - <code>[Map]&lt;dyn [core::any::Any] + Send&gt;</code>
+/// - <code>[Map]&lt;dyn [core::any::Any] + Send + Sync&gt;</code>
+/// - <code>[Map]&lt;dyn [CloneAny]&gt;</code>
+/// - <code>[Map]&lt;dyn [CloneAny] + Send&gt;</code>
+/// - <code>[Map]&lt;dyn [CloneAny] + Send + Sync&gt;</code>
+///
+/// ## Example
+///
+/// (Here using the [`AnyMap`] convenience alias; the first line could use
+/// <code>[anymap::Map][Map]::&lt;[core::any::Any]&gt;::new()</code> instead if desired.)
+///
+/// ```rust
+#[doc = "let mut data = anymap::AnyMap::new();"]
+/// assert_eq!(data.get(), None::<&i32>);
+/// ```
+///
+/// Values containing non-static references are not permitted.
+#[derive(Debug)]
+pub struct Map<A: ?Sized + Downcast = dyn Any> {
+    raw: RawMap<A>,
+}
 
-        /// A collection containing zero or one values for any given type and allowing convenient,
-        /// type-safe access to those values.
-        ///
-        /// The type parameter `A` allows you to use a different value type; normally you will want
-        /// it to be `core::any::Any` (also known as `std::any::Any`), but there are other choices:
-        ///
-        /// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with
-        ///   that, you can only add types that implement `Clone` to the map.
-        /// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map<dyn Any + Send>`) to add those
-        ///   auto traits.
-        ///
-        /// Cumulatively, there are thus six forms of map:
-        ///
-        /// - <code>[Map]&lt;dyn [core::any::Any]&gt;</code>,
-        ///   also spelled [`AnyMap`] for convenience.
-        /// - <code>[Map]&lt;dyn [core::any::Any] + Send&gt;</code>
-        /// - <code>[Map]&lt;dyn [core::any::Any] + Send + Sync&gt;</code>
-        /// - <code>[Map]&lt;dyn [CloneAny]&gt;</code>
-        /// - <code>[Map]&lt;dyn [CloneAny] + Send&gt;</code>
-        /// - <code>[Map]&lt;dyn [CloneAny] + Send + Sync&gt;</code>
-        ///
-        /// ## Example
-        ///
-        /// (Here using the [`AnyMap`] convenience alias; the first line could use
-        /// <code>[anymap::Map][Map]::&lt;[core::any::Any]&gt;::new()</code> instead if desired.)
-        ///
-        /// ```rust
-        #[doc = $example_init]
-        /// assert_eq!(data.get(), None::<&i32>);
-        /// ```
-        ///
-        /// Values containing non-static references are not permitted.
-        #[derive(Debug)]
-        pub struct Map<A: ?Sized + Downcast = dyn Any> {
-            raw: RawMap<A>,
-        }
+/// The most common type of `Map`: just using `Any`; <code>[Map]&lt;dyn [Any]&gt;</code>.
+///
+/// Why is this a separate type alias rather than a default value for `Map<A>`?
+/// `Map::new()` doesn’t seem to be happy to infer that it should go with the default
+/// value. It’s a bit sad, really. Ah well, I guess this approach will do.
+pub type AnyMap = Map<dyn Any>;
+impl<A: ?Sized + Downcast> Default for Map<A> {
+    #[inline]
+    fn default() -> Map<A> {
+        Map::new()
+    }
+}
 
-        /// The most common type of `Map`: just using `Any`; <code>[Map]&lt;dyn [Any]&gt;</code>.
-        ///
-        /// Why is this a separate type alias rather than a default value for `Map<A>`?
-        /// `Map::new()` doesn’t seem to be happy to infer that it should go with the default
-        /// value. It’s a bit sad, really. Ah well, I guess this approach will do.
-        pub type AnyMap = Map<dyn Any>;
-        impl<A: ?Sized + Downcast> Default for Map<A> {
-            #[inline]
-            fn default() -> Map<A> {
-                Map::new()
-            }
-        }
+impl<A: ?Sized + Downcast> Map<A> {
+    /// Create an empty collection.
+    #[inline]
+    pub fn new() -> Map<A> {
+        Map { raw: RawMap::with_hasher(Default::default()) }
+    }
 
-        impl<A: ?Sized + Downcast> Map<A> {
-            /// Create an empty collection.
-            #[inline]
-            pub fn new() -> Map<A> {
-                Map {
-                    raw: RawMap::with_hasher(Default::default()),
-                }
-            }
+    /// Returns a reference to the value stored in the collection for the type `T`,
+    /// if it exists.
+    #[inline]
+    pub fn get<T: IntoBox<A>>(&self) -> Option<&T> {
+        self.raw.get(&TypeId::of::<T>()).map(|any| unsafe { any.downcast_ref_unchecked::<T>() })
+    }
 
-            /// Returns a reference to the value stored in the collection for the type `T`,
-            /// if it exists.
-            #[inline]
-            pub fn get<T: IntoBox<A>>(&self) -> Option<&T> {
-                self.raw.get(&TypeId::of::<T>())
-                    .map(|any| unsafe { any.downcast_ref_unchecked::<T>() })
+    /// Gets the entry for the given type in the collection for in-place manipulation
+    #[inline]
+    pub fn entry<T: IntoBox<A>>(&mut self) -> Entry<A, T> {
+        match self.raw.entry(TypeId::of::<T>()) {
+            hash_map::Entry::Occupied(e) => {
+                Entry::Occupied(OccupiedEntry { inner: e, type_: PhantomData })
             }
-
-            /// Gets the entry for the given type in the collection for in-place manipulation
-            #[inline]
-            pub fn entry<T: IntoBox<A>>(&mut self) -> Entry<A, T> {
-                match self.raw.entry(TypeId::of::<T>()) {
-                    hash_map::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
-                        inner: e,
-                        type_: PhantomData,
-                    }),
-                    hash_map::Entry::Vacant(e) => Entry::Vacant(VacantEntry {
-                        inner: e,
-                        type_: PhantomData,
-                    }),
-                }
+            hash_map::Entry::Vacant(e) => {
+                Entry::Vacant(VacantEntry { inner: e, type_: PhantomData })
             }
-
-        }
-
-        /// A view into a single occupied location in an `Map`.
-        pub struct OccupiedEntry<'a, A: ?Sized + Downcast, V: 'a> {
-            inner: hash_map::OccupiedEntry<'a, TypeId, Box<A>, $($entry_generics)?>,
-            type_: PhantomData<V>,
-        }
-
-        /// A view into a single empty location in an `Map`.
-        pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> {
-            inner: hash_map::VacantEntry<'a, TypeId, Box<A>, $($entry_generics)?>,
-            type_: PhantomData<V>,
         }
+    }
+}
 
-        /// A view into a single location in an `Map`, which may be vacant or occupied.
-        pub enum Entry<'a, A: ?Sized + Downcast, V: 'a> {
-            /// An occupied Entry
-            Occupied(OccupiedEntry<'a, A, V>),
-            /// A vacant Entry
-            Vacant(VacantEntry<'a, A, V>),
-        }
+/// A view into a single occupied location in an `Map`.
+pub struct OccupiedEntry<'a, A: ?Sized + Downcast, V: 'a> {
+    inner: hash_map::OccupiedEntry<'a, TypeId, Box<A>>,
+    type_: PhantomData<V>,
+}
 
-        impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> Entry<'a, A, V> {
+/// A view into a single empty location in an `Map`.
+pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> {
+    inner: hash_map::VacantEntry<'a, TypeId, Box<A>>,
+    type_: PhantomData<V>,
+}
 
+/// A view into a single location in an `Map`, which may be vacant or occupied.
+pub enum Entry<'a, A: ?Sized + Downcast, V: 'a> {
+    /// An occupied Entry
+    Occupied(OccupiedEntry<'a, A, V>),
+    /// A vacant Entry
+    Vacant(VacantEntry<'a, A, V>),
+}
 
-            /// Ensures a value is in the entry by inserting the result of the default function if
-            /// empty, and returns a mutable reference to the value in the entry.
-            #[inline]
-            pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
-                match self {
-                    Entry::Occupied(inner) => inner.into_mut(),
-                    Entry::Vacant(inner) => inner.insert(default()),
-                }
-            }
+impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> Entry<'a, A, V> {
+    /// Ensures a value is in the entry by inserting the result of the default function if
+    /// empty, and returns a mutable reference to the value in the entry.
+    #[inline]
+    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
+        match self {
+            Entry::Occupied(inner) => inner.into_mut(),
+            Entry::Vacant(inner) => inner.insert(default()),
         }
+    }
+}
 
-        impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> OccupiedEntry<'a, A, V> {
-            /// Converts the OccupiedEntry into a mutable reference to the value in the entry
-            /// with a lifetime bound to the collection itself
-            #[inline]
-            pub fn into_mut(self) -> &'a mut V {
-                unsafe { self.inner.into_mut().downcast_mut_unchecked() }
-            }
-        }
+impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> OccupiedEntry<'a, A, V> {
+    /// Converts the OccupiedEntry into a mutable reference to the value in the entry
+    /// with a lifetime bound to the collection itself
+    #[inline]
+    pub fn into_mut(self) -> &'a mut V {
+        unsafe { self.inner.into_mut().downcast_mut_unchecked() }
+    }
+}
 
-        impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> VacantEntry<'a, A, V> {
-            /// Sets the value of the entry with the VacantEntry's key,
-            /// and returns a mutable reference to it
-            #[inline]
-            pub fn insert(self, value: V) -> &'a mut V {
-                unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() }
-            }
-        }
+impl<'a, A: ?Sized + Downcast, V: IntoBox<A>> VacantEntry<'a, A, V> {
+    /// Sets the value of the entry with the VacantEntry's key,
+    /// and returns a mutable reference to it
+    #[inline]
+    pub fn insert(self, value: V) -> &'a mut V {
+        unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() }
+    }
+}
 
-        #[cfg(test)]
-        mod tests {
-            use crate::CloneAny;
-            use super::*;
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::CloneAny;
 
-            #[derive(Clone, Debug, PartialEq)] struct A(i32);
-            #[derive(Clone, Debug, PartialEq)] struct B(i32);
-            #[derive(Clone, Debug, PartialEq)] struct C(i32);
-            #[derive(Clone, Debug, PartialEq)] struct D(i32);
-            #[derive(Clone, Debug, PartialEq)] struct E(i32);
-            #[derive(Clone, Debug, PartialEq)] struct F(i32);
-            #[derive(Clone, Debug, PartialEq)] struct J(i32);
+    #[derive(Clone, Debug, PartialEq)]
+    struct A(i32);
+    #[derive(Clone, Debug, PartialEq)]
+    struct B(i32);
+    #[derive(Clone, Debug, PartialEq)]
+    struct C(i32);
+    #[derive(Clone, Debug, PartialEq)]
+    struct D(i32);
+    #[derive(Clone, Debug, PartialEq)]
+    struct E(i32);
+    #[derive(Clone, Debug, PartialEq)]
+    struct F(i32);
+    #[derive(Clone, Debug, PartialEq)]
+    struct J(i32);
 
-            #[test]
-            fn test_varieties() {
-                fn assert_send<T: Send>() { }
-                fn assert_sync<T: Sync>() { }
-                fn assert_debug<T: ::core::fmt::Debug>() { }
-                assert_send::<Map<dyn Any + Send>>();
-                assert_send::<Map<dyn Any + Send + Sync>>();
-                assert_sync::<Map<dyn Any + Send + Sync>>();
-                assert_debug::<Map<dyn Any>>();
-                assert_debug::<Map<dyn Any + Send>>();
-                assert_debug::<Map<dyn Any + Send + Sync>>();
-                assert_send::<Map<dyn CloneAny + Send>>();
-                assert_send::<Map<dyn CloneAny + Send + Sync>>();
-                assert_sync::<Map<dyn CloneAny + Send + Sync>>();
-                assert_debug::<Map<dyn CloneAny>>();
-                assert_debug::<Map<dyn CloneAny + Send>>();
-                assert_debug::<Map<dyn CloneAny + Send + Sync>>();
-            }
-        }
-    };
-}
+    #[test]
+    fn test_varieties() {
+        fn assert_send<T: Send>() {}
+        fn assert_sync<T: Sync>() {}
+        fn assert_debug<T: ::core::fmt::Debug>() {}
+        assert_send::<Map<dyn Any + Send>>();
+        assert_send::<Map<dyn Any + Send + Sync>>();
+        assert_sync::<Map<dyn Any + Send + Sync>>();
+        assert_debug::<Map<dyn Any>>();
+        assert_debug::<Map<dyn Any + Send>>();
+        assert_debug::<Map<dyn Any + Send + Sync>>();
+        assert_send::<Map<dyn CloneAny + Send>>();
+        assert_send::<Map<dyn CloneAny + Send + Sync>>();
+        assert_sync::<Map<dyn CloneAny + Send + Sync>>();
+        assert_debug::<Map<dyn CloneAny>>();
+        assert_debug::<Map<dyn CloneAny + Send>>();
+        assert_debug::<Map<dyn CloneAny + Send + Sync>>();
+    }
 
-#[test]
-fn type_id_hasher() {
-    use core::any::TypeId;
-    use core::hash::Hash;
-    fn verify_hashing_with(type_id: TypeId) {
-        let mut hasher = TypeIdHasher::default();
-        type_id.hash(&mut hasher);
-        // SAFETY: u64 is valid for all bit patterns.
-        let _ = hasher.finish();
+    #[test]
+    fn type_id_hasher() {
+        use core::any::TypeId;
+        use core::hash::Hash;
+        fn verify_hashing_with(type_id: TypeId) {
+            let mut hasher = TypeIdHasher::default();
+            type_id.hash(&mut hasher);
+            // SAFETY: u64 is valid for all bit patterns.
+            let _ = hasher.finish();
+        }
+        // Pick a variety of types, just to demonstrate it’s all sane. Normal, zero-sized, unsized, &c.
+        verify_hashing_with(TypeId::of::<usize>());
+        verify_hashing_with(TypeId::of::<()>());
+        verify_hashing_with(TypeId::of::<str>());
+        verify_hashing_with(TypeId::of::<&str>());
+        verify_hashing_with(TypeId::of::<Vec<u8>>());
     }
-    // Pick a variety of types, just to demonstrate it’s all sane. Normal, zero-sized, unsized, &c.
-    verify_hashing_with(TypeId::of::<usize>());
-    verify_hashing_with(TypeId::of::<()>());
-    verify_hashing_with(TypeId::of::<str>());
-    verify_hashing_with(TypeId::of::<&str>());
-    verify_hashing_with(TypeId::of::<Vec<u8>>());
 }
-
-#[cfg(feature = "std")]
-everything!("let mut data = anymap::AnyMap::new();", std::collections);