diff --git a/src/lib.rs b/src/lib.rs index e99f0a22..360636f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,7 +98,8 @@ //! [`with_capacity_and_hasher`][IndexMap::with_capacity_and_hasher] instead. //! A no-std compatible hasher will be needed as well, for example //! from the crate `twox-hash`. -//! - Macros [`indexmap!`] and [`indexset!`] are unavailable without `std`. +//! - Macros [`indexmap!`] and [`indexset!`] are unavailable without `std`. Use +//! the macros [`indexmap_with_default!`] and [`indexset_with_default!`] instead. #![cfg_attr(docsrs, feature(doc_cfg))] diff --git a/src/macros.rs b/src/macros.rs index 65f34369..0674ffc2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,3 +1,40 @@ +/// Create an [`IndexMap`][crate::IndexMap] from a list of key-value pairs +/// and a `BuildHasherDefault`-wrapped custom hasher. +/// +/// ## Example +/// +/// ``` +/// use indexmap::indexmap_with_default; +/// use fnv::FnvHasher; +/// +/// let map = indexmap_with_default!{ +/// FnvHasher; +/// "a" => 1, +/// "b" => 2, +/// }; +/// assert_eq!(map["a"], 1); +/// assert_eq!(map["b"], 2); +/// assert_eq!(map.get("c"), None); +/// +/// // "a" is the first key +/// assert_eq!(map.keys().next(), Some(&"a")); +/// ``` +#[macro_export] +macro_rules! indexmap_with_default { + ($H:ty; $($key:expr => $value:expr,)+) => { $crate::indexmap_with_default!($H; $($key => $value),+) }; + ($H:ty; $($key:expr => $value:expr),*) => {{ + let builder = ::core::hash::BuildHasherDefault::<$H>::default(); + const CAP: usize = <[()]>::len(&[$({ stringify!($key); }),*]); + #[allow(unused_mut)] + // Specify your custom `H` (must implement Default + Hasher) as the hasher: + let mut map = $crate::IndexMap::with_capacity_and_hasher(CAP, builder); + $( + map.insert($key, $value); + )* + map + }}; +} + #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[macro_export] @@ -35,6 +72,43 @@ macro_rules! indexmap { }; } +/// Create an [`IndexSet`][crate::IndexSet] from a list of values +/// and a `BuildHasherDefault`-wrapped custom hasher. +/// +/// ## Example +/// +/// ``` +/// use indexmap::indexset_with_default; +/// use fnv::FnvHasher; +/// +/// let set = indexset_with_default!{ +/// FnvHasher; +/// "a", +/// "b", +/// }; +/// assert!(set.contains("a")); +/// assert!(set.contains("b")); +/// assert!(!set.contains("c")); +/// +/// // "a" is the first value +/// assert_eq!(set.iter().next(), Some(&"a")); +/// ``` +#[macro_export] +macro_rules! indexset_with_default { + ($H:ty; $($value:expr,)+) => { $crate::indexset_with_default!($H; $($value),+) }; + ($H:ty; $($value:expr),*) => {{ + let builder = ::core::hash::BuildHasherDefault::<$H>::default(); + const CAP: usize = <[()]>::len(&[$({ stringify!($value); }),*]); + #[allow(unused_mut)] + // Specify your custom `H` (must implement Default + Hash) as the hasher: + let mut set = $crate::IndexSet::with_capacity_and_hasher(CAP, builder); + $( + set.insert($value); + )* + set + }}; +} + #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[macro_export]