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}