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 fnv::FnvHasher; |
9 | /// |
10 | /// let map = indexmap_with_default!{ |
11 | /// FnvHasher; |
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 | #[macro_export ] |
23 | macro_rules! indexmap_with_default { |
24 | ($H:ty; $($key:expr => $value:expr,)+) => { $crate::indexmap_with_default!($H; $($key => $value),+) }; |
25 | ($H:ty; $($key:expr => $value:expr),*) => {{ |
26 | let builder = ::core::hash::BuildHasherDefault::<$H>::default(); |
27 | const CAP: usize = <[()]>::len(&[$({ stringify!($key); }),*]); |
28 | #[allow(unused_mut)] |
29 | // Specify your custom `H` (must implement Default + Hasher) as the hasher: |
30 | let mut map = $crate::IndexMap::with_capacity_and_hasher(CAP, builder); |
31 | $( |
32 | map.insert($key, $value); |
33 | )* |
34 | map |
35 | }}; |
36 | } |
37 | |
38 | #[cfg (feature = "std" )] |
39 | #[cfg_attr (docsrs, doc(cfg(feature = "std" )))] |
40 | #[macro_export ] |
41 | /// Create an [`IndexMap`][crate::IndexMap] from a list of key-value pairs |
42 | /// |
43 | /// ## Example |
44 | /// |
45 | /// ``` |
46 | /// use indexmap::indexmap; |
47 | /// |
48 | /// let map = indexmap!{ |
49 | /// "a" => 1, |
50 | /// "b" => 2, |
51 | /// }; |
52 | /// assert_eq!(map["a" ], 1); |
53 | /// assert_eq!(map["b" ], 2); |
54 | /// assert_eq!(map.get("c" ), None); |
55 | /// |
56 | /// // "a" is the first key |
57 | /// assert_eq!(map.keys().next(), Some(&"a" )); |
58 | /// ``` |
59 | macro_rules! indexmap { |
60 | ($($key:expr => $value:expr,)+) => { $crate::indexmap!($($key => $value),+) }; |
61 | ($($key:expr => $value:expr),*) => { |
62 | { |
63 | // Note: `stringify!($key)` is just here to consume the repetition, |
64 | // but we throw away that string literal during constant evaluation. |
65 | const CAP: usize = <[()]>::len(&[$({ stringify!($key); }),*]); |
66 | let mut map = $crate::IndexMap::with_capacity(CAP); |
67 | $( |
68 | map.insert($key, $value); |
69 | )* |
70 | map |
71 | } |
72 | }; |
73 | } |
74 | |
75 | /// Create an [`IndexSet`][crate::IndexSet] from a list of values |
76 | /// and a [`BuildHasherDefault`][core::hash::BuildHasherDefault]-wrapped custom hasher. |
77 | /// |
78 | /// ## Example |
79 | /// |
80 | /// ``` |
81 | /// use indexmap::indexset_with_default; |
82 | /// use fnv::FnvHasher; |
83 | /// |
84 | /// let set = indexset_with_default!{ |
85 | /// FnvHasher; |
86 | /// "a" , |
87 | /// "b" , |
88 | /// }; |
89 | /// assert!(set.contains("a" )); |
90 | /// assert!(set.contains("b" )); |
91 | /// assert!(!set.contains("c" )); |
92 | /// |
93 | /// // "a" is the first value |
94 | /// assert_eq!(set.iter().next(), Some(&"a" )); |
95 | /// ``` |
96 | #[macro_export ] |
97 | macro_rules! indexset_with_default { |
98 | ($H:ty; $($value:expr,)+) => { $crate::indexset_with_default!($H; $($value),+) }; |
99 | ($H:ty; $($value:expr),*) => {{ |
100 | let builder = ::core::hash::BuildHasherDefault::<$H>::default(); |
101 | const CAP: usize = <[()]>::len(&[$({ stringify!($value); }),*]); |
102 | #[allow(unused_mut)] |
103 | // Specify your custom `H` (must implement Default + Hash) as the hasher: |
104 | let mut set = $crate::IndexSet::with_capacity_and_hasher(CAP, builder); |
105 | $( |
106 | set.insert($value); |
107 | )* |
108 | set |
109 | }}; |
110 | } |
111 | |
112 | #[cfg (feature = "std" )] |
113 | #[cfg_attr (docsrs, doc(cfg(feature = "std" )))] |
114 | #[macro_export ] |
115 | /// Create an [`IndexSet`][crate::IndexSet] from a list of values |
116 | /// |
117 | /// ## Example |
118 | /// |
119 | /// ``` |
120 | /// use indexmap::indexset; |
121 | /// |
122 | /// let set = indexset!{ |
123 | /// "a" , |
124 | /// "b" , |
125 | /// }; |
126 | /// assert!(set.contains("a" )); |
127 | /// assert!(set.contains("b" )); |
128 | /// assert!(!set.contains("c" )); |
129 | /// |
130 | /// // "a" is the first value |
131 | /// assert_eq!(set.iter().next(), Some(&"a" )); |
132 | /// ``` |
133 | macro_rules! indexset { |
134 | ($($value:expr,)+) => { $crate::indexset!($($value),+) }; |
135 | ($($value:expr),*) => { |
136 | { |
137 | // Note: `stringify!($value)` is just here to consume the repetition, |
138 | // but we throw away that string literal during constant evaluation. |
139 | const CAP: usize = <[()]>::len(&[$({ stringify!($value); }),*]); |
140 | let mut set = $crate::IndexSet::with_capacity(CAP); |
141 | $( |
142 | set.insert($value); |
143 | )* |
144 | set |
145 | } |
146 | }; |
147 | } |
148 | |
149 | // generate all the Iterator methods by just forwarding to the underlying |
150 | // self.iter and mapping its element. |
151 | macro_rules! iterator_methods { |
152 | // $map_elt is the mapping function from the underlying iterator's element |
153 | // same mapping function for both options and iterators |
154 | ($map_elt:expr) => { |
155 | fn next(&mut self) -> Option<Self::Item> { |
156 | self.iter.next().map($map_elt) |
157 | } |
158 | |
159 | fn size_hint(&self) -> (usize, Option<usize>) { |
160 | self.iter.size_hint() |
161 | } |
162 | |
163 | fn count(self) -> usize { |
164 | self.iter.len() |
165 | } |
166 | |
167 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
168 | self.iter.nth(n).map($map_elt) |
169 | } |
170 | |
171 | fn last(mut self) -> Option<Self::Item> { |
172 | self.next_back() |
173 | } |
174 | |
175 | fn collect<C>(self) -> C |
176 | where |
177 | C: FromIterator<Self::Item>, |
178 | { |
179 | // NB: forwarding this directly to standard iterators will |
180 | // allow it to leverage unstable traits like `TrustedLen`. |
181 | self.iter.map($map_elt).collect() |
182 | } |
183 | }; |
184 | } |
185 | |
186 | macro_rules! double_ended_iterator_methods { |
187 | // $map_elt is the mapping function from the underlying iterator's element |
188 | // same mapping function for both options and iterators |
189 | ($map_elt:expr) => { |
190 | fn next_back(&mut self) -> Option<Self::Item> { |
191 | self.iter.next_back().map($map_elt) |
192 | } |
193 | |
194 | fn nth_back(&mut self, n: usize) -> Option<Self::Item> { |
195 | self.iter.nth_back(n).map($map_elt) |
196 | } |
197 | }; |
198 | } |
199 | |
200 | // generate `ParallelIterator` methods by just forwarding to the underlying |
201 | // self.entries and mapping its elements. |
202 | #[cfg (feature = "rayon" )] |
203 | macro_rules! parallel_iterator_methods { |
204 | // $map_elt is the mapping function from the underlying iterator's element |
205 | ($map_elt:expr) => { |
206 | fn drive_unindexed<C>(self, consumer: C) -> C::Result |
207 | where |
208 | C: UnindexedConsumer<Self::Item>, |
209 | { |
210 | self.entries |
211 | .into_par_iter() |
212 | .map($map_elt) |
213 | .drive_unindexed(consumer) |
214 | } |
215 | |
216 | // NB: This allows indexed collection, e.g. directly into a `Vec`, but the |
217 | // underlying iterator must really be indexed. We should remove this if we |
218 | // start having tombstones that must be filtered out. |
219 | fn opt_len(&self) -> Option<usize> { |
220 | Some(self.entries.len()) |
221 | } |
222 | }; |
223 | } |
224 | |
225 | // generate `IndexedParallelIterator` methods by just forwarding to the underlying |
226 | // self.entries and mapping its elements. |
227 | #[cfg (feature = "rayon" )] |
228 | macro_rules! indexed_parallel_iterator_methods { |
229 | // $map_elt is the mapping function from the underlying iterator's element |
230 | ($map_elt:expr) => { |
231 | fn drive<C>(self, consumer: C) -> C::Result |
232 | where |
233 | C: Consumer<Self::Item>, |
234 | { |
235 | self.entries.into_par_iter().map($map_elt).drive(consumer) |
236 | } |
237 | |
238 | fn len(&self) -> usize { |
239 | self.entries.len() |
240 | } |
241 | |
242 | fn with_producer<CB>(self, callback: CB) -> CB::Output |
243 | where |
244 | CB: ProducerCallback<Self::Item>, |
245 | { |
246 | self.entries |
247 | .into_par_iter() |
248 | .map($map_elt) |
249 | .with_producer(callback) |
250 | } |
251 | }; |
252 | } |
253 | |