Skip to content

Commit

Permalink
Merge pull request #380 from iajoiner/feat/macros-no-std
Browse files Browse the repository at this point in the history
feat: add no_std macros `indexmap_with_default` and `indexset_with_default`
  • Loading branch information
cuviper authored Mar 5, 2025
2 parents 5b133ae + 5fd8971 commit b10b273
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]

Expand Down
74 changes: 74 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -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]
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit b10b273

Please sign in to comment.