Skip to main content

indexmap/
macros.rs

1/// Create an [`IndexMap`][crate::IndexMap] from a list of key-value pairs
2/// and a [`BuildHasherDefault`][core::hash::BuildHasherDefault]-wrapped custom hasher.
3///
4/// ## Example
5///
6/// ```
7/// use indexmap::indexmap_with_default;
8/// use std::collections::hash_map::DefaultHasher;
9///
10/// let map = indexmap_with_default!{
11///     DefaultHasher;
12///     "a" => 1,
13///     "b" => 2,
14/// };
15/// assert_eq!(map["a"], 1);
16/// assert_eq!(map["b"], 2);
17/// assert_eq!(map.get("c"), None);
18///
19/// // "a" is the first key
20/// assert_eq!(map.keys().next(), Some(&"a"));
21/// ```
22///
23/// This can also be initialized in `const` contexts:
24///
25/// ```
26/// use indexmap::{IndexMap, indexmap_with_default};
27/// use std::collections::hash_map::DefaultHasher;
28/// use std::hash::BuildHasherDefault;
29/// use std::sync::Mutex;
30///
31/// type DefaultHashBuilder = BuildHasherDefault<DefaultHasher>;
32///
33/// static GLOBAL: Mutex<IndexMap<String, i32, DefaultHashBuilder>> =
34///     Mutex::new(indexmap_with_default!());
35///
36/// if let Ok(mut map) = GLOBAL.lock() {
37///     map.insert("a".into(), 1);
38///     map.insert("b".into(), 2);
39/// }
40///
41/// assert_eq!(GLOBAL.lock().unwrap()["a"], 1);
42/// assert_eq!(GLOBAL.lock().unwrap()["b"], 2);
43/// ```
44#[macro_export]
45macro_rules! indexmap_with_default {
46    () => { const {
47        $crate::IndexMap::with_hasher(
48            // Let type inference figure out the hasher:
49            ::core::hash::BuildHasherDefault::new(),
50        )
51    }};
52    ($H:ty $(;)?) => { const {
53        $crate::IndexMap::with_hasher(
54            // Specify your custom `H` (must implement Default + Hasher) as the hasher:
55            ::core::hash::BuildHasherDefault::<$H>::new(),
56        )
57    }};
58    ($H:ty; $($key:expr => $value:expr),+ $(,)?) => {{
59        let mut map = $crate::IndexMap::with_capacity_and_hasher(
60            // Note: `stringify!($key)` is just here to consume the repetition,
61            // but we throw away that string literal during constant evaluation.
62            const { <[()]>::len(&[$({ stringify!($key); }),*]) },
63            // Specify your custom `H` (must implement Default + Hasher) as the hasher:
64            ::core::hash::BuildHasherDefault::<$H>::new(),
65        );
66        $(
67            map.insert($key, $value);
68        )+
69        map
70    }};
71}
72
73#[cfg(feature = "std")]
74#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
75#[macro_export]
76/// Create an [`IndexMap`][crate::IndexMap] from a list of key-value pairs
77///
78/// ## Example
79///
80/// ```
81/// use indexmap::indexmap;
82///
83/// let map = indexmap!{
84///     "a" => 1,
85///     "b" => 2,
86/// };
87/// assert_eq!(map["a"], 1);
88/// assert_eq!(map["b"], 2);
89/// assert_eq!(map.get("c"), None);
90///
91/// // "a" is the first key
92/// assert_eq!(map.keys().next(), Some(&"a"));
93/// ```
94macro_rules! indexmap {
95    () => { $crate::IndexMap::new() };
96    ($($key:expr => $value:expr),+ $(,)?) => {{
97        let mut map = $crate::IndexMap::with_capacity(
98            // Note: `stringify!($key)` is just here to consume the repetition,
99            // but we throw away that string literal during constant evaluation.
100            const { <[()]>::len(&[$({ stringify!($key); }),*]) },
101        );
102        $(
103            map.insert($key, $value);
104        )+
105        map
106    }};
107}
108
109/// Create an [`IndexSet`][crate::IndexSet] from a list of values
110/// and a [`BuildHasherDefault`][core::hash::BuildHasherDefault]-wrapped custom hasher.
111///
112/// ## Example
113///
114/// ```
115/// use indexmap::indexset_with_default;
116/// use std::collections::hash_map::DefaultHasher;
117///
118/// let set = indexset_with_default!{
119///     DefaultHasher;
120///     "a",
121///     "b",
122/// };
123/// assert!(set.contains("a"));
124/// assert!(set.contains("b"));
125/// assert!(!set.contains("c"));
126///
127/// // "a" is the first value
128/// assert_eq!(set.iter().next(), Some(&"a"));
129/// ```
130///
131/// This can also be initialized in `const` contexts:
132///
133/// ```
134/// use indexmap::{IndexSet, indexset_with_default};
135/// use std::collections::hash_map::DefaultHasher;
136/// use std::hash::BuildHasherDefault;
137/// use std::sync::Mutex;
138///
139/// type DefaultHashBuilder = BuildHasherDefault<DefaultHasher>;
140///
141/// static INTERN: Mutex<IndexSet<String, DefaultHashBuilder>> =
142///     Mutex::new(indexset_with_default!());
143///
144/// if let Ok(mut set) = INTERN.lock() {
145///     set.insert("a".into());
146///     set.insert("b".into());
147///     set.insert("c".into());
148/// }
149///
150/// assert!(INTERN.lock().unwrap().contains("a"));
151/// assert!(INTERN.lock().unwrap().contains("b"));
152/// assert!(INTERN.lock().unwrap().contains("c"));
153/// ```
154#[macro_export]
155macro_rules! indexset_with_default {
156    () => { const {
157        $crate::IndexSet::with_hasher(
158            // Let type inference figure out the hasher:
159            ::core::hash::BuildHasherDefault::new(),
160        )
161    }};
162    ($H:ty $(;)?) => { const {
163        $crate::IndexSet::with_hasher(
164            // Specify your custom `H` (must implement Default + Hasher) as the hasher:
165            ::core::hash::BuildHasherDefault::<$H>::new(),
166        )
167    }};
168    ($H:ty; $($value:expr),+ $(,)?) => {{
169        let mut set = $crate::IndexSet::with_capacity_and_hasher(
170            // Note: `stringify!($value)` is just here to consume the repetition,
171            // but we throw away that string literal during constant evaluation.
172            const { <[()]>::len(&[$({ stringify!($value); }),*]) },
173            // Specify your custom `H` (must implement Default + Hasher) as the hasher:
174            ::core::hash::BuildHasherDefault::<$H>::new(),
175        );
176        $(
177            set.insert($value);
178        )+
179        set
180    }};
181}
182
183#[cfg(feature = "std")]
184#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
185#[macro_export]
186/// Create an [`IndexSet`][crate::IndexSet] from a list of values
187///
188/// ## Example
189///
190/// ```
191/// use indexmap::indexset;
192///
193/// let set = indexset!{
194///     "a",
195///     "b",
196/// };
197/// assert!(set.contains("a"));
198/// assert!(set.contains("b"));
199/// assert!(!set.contains("c"));
200///
201/// // "a" is the first value
202/// assert_eq!(set.iter().next(), Some(&"a"));
203/// ```
204macro_rules! indexset {
205    () => { $crate::IndexSet::new() };
206    ($($value:expr),+ $(,)?) => {{
207        let mut set = $crate::IndexSet::with_capacity(
208            // Note: `stringify!($value)` is just here to consume the repetition,
209            // but we throw away that string literal during constant evaluation.
210            const { <[()]>::len(&[$({ stringify!($value); }),*]) },
211        );
212        $(
213            set.insert($value);
214        )+
215        set
216    }};
217}
218
219// generate all the Iterator methods by just forwarding to the underlying
220// self.iter and mapping its element.
221macro_rules! iterator_methods {
222    // $map_elt is the mapping function from the underlying iterator's element
223    // same mapping function for both options and iterators
224    ($map_elt:expr) => {
225        fn next(&mut self) -> Option<Self::Item> {
226            self.iter.next().map($map_elt)
227        }
228
229        fn size_hint(&self) -> (usize, Option<usize>) {
230            self.iter.size_hint()
231        }
232
233        fn count(self) -> usize {
234            self.iter.len()
235        }
236
237        fn nth(&mut self, n: usize) -> Option<Self::Item> {
238            self.iter.nth(n).map($map_elt)
239        }
240
241        fn last(mut self) -> Option<Self::Item> {
242            self.next_back()
243        }
244
245        fn collect<C>(self) -> C
246        where
247            C: FromIterator<Self::Item>,
248        {
249            // NB: forwarding this directly to standard iterators will
250            // allow it to leverage unstable traits like `TrustedLen`.
251            self.iter.map($map_elt).collect()
252        }
253    };
254}
255
256macro_rules! double_ended_iterator_methods {
257    // $map_elt is the mapping function from the underlying iterator's element
258    // same mapping function for both options and iterators
259    ($map_elt:expr) => {
260        fn next_back(&mut self) -> Option<Self::Item> {
261            self.iter.next_back().map($map_elt)
262        }
263
264        fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
265            self.iter.nth_back(n).map($map_elt)
266        }
267    };
268}