1#[macro_export]
2macro_rules! izip_eq_lazy {
12 ( @closure $p:pat => $tup:expr ) => {
16 |$p| $tup
17 };
18
19 ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => {
21 $crate::izip_eq_lazy!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*)
22 };
23
24 ($first:expr $(,)*) => {
26 std::iter::IntoIterator::into_iter($first)
27 };
28
29 ($first:expr, $second:expr $(,)*) => {
31 itertools::zip_eq(
32 std::iter::IntoIterator::into_iter($first),
33 $second,
34 )
35 };
36
37 ( $first:expr $( , $rest:expr )* $(,)* ) => {
39 {
40 let iter = std::iter::IntoIterator::into_iter($first);
41 $(
42 let iter = itertools::zip_eq(iter, $rest);
43 )*
44 std::iter::Iterator::map(
45 iter,
46 $crate::izip_eq_lazy!(@closure a => (a) $( , $rest )*)
47 )
48 }
49 };
50}
51
52#[macro_export]
53macro_rules! izip_eq {
61 (@assert_eq_len $first:expr, $second:expr) => {
62 assert!($first.len() == $second.len(), "iterator length mismatch: {} vs {}", $first.len(), $second.len());
63 };
64
65 ($first:expr $(,)*) => {
67 std::iter::IntoIterator::into_iter($first)
68 };
69
70 ($first:expr, $second:expr $(,)*) => {
72 {
73 let iter = std::iter::IntoIterator::into_iter($first);
74 let second = std::iter::IntoIterator::into_iter($second);
75 $crate::izip_eq!(@assert_eq_len iter, second);
76 let iter = std::iter::Iterator::zip(iter, second);
77 iter
78 }
79 };
80
81 ( $first:expr $( , $rest:expr )* $(,)* ) => {
83 {
84 let iter = std::iter::IntoIterator::into_iter($first);
85 $(
86 let rest = std::iter::IntoIterator::into_iter($rest);
87 $crate::izip_eq!(@assert_eq_len iter, rest);
88 let iter = std::iter::Iterator::zip(iter, rest);
89 )*
90 std::iter::Iterator::map(
91 iter,
92 $crate::izip_eq_lazy!(@closure a => (a) $( , $rest )*)
93 )
94 }
95 };
96}
97
98#[macro_export]
99macro_rules! chain_eq {
104 ($first:expr $( , $rest:expr )* $(,)*) => {{
105 let it = itertools::chain!($first, $($rest, )*);
106 let vec = <std::vec::Vec<_> as std::iter::FromIterator<_>>::from_iter(it);
107 <std::vec::Vec<_> as std::iter::IntoIterator>::into_iter(vec)
108 }
109 };
110}
111
112#[macro_export]
113macro_rules! zip_maps {
116 ($keys:expr, $($map:expr),+ $(,)?) => {
117 $keys.into_iter().map(move |key| {
118 (
119 key,
120 $(
121 $map.remove(&key).expect(&format!(
122 "Key `{:?}` not found in map `{}`",
123 key,
124 stringify!($map),
125 )),
126 )+
127 )
128 })
129 };
130}
131
132pub trait IntoExactSizeIterator:
133 IntoIterator<IntoIter: ExactSizeIterator<Item = <Self as IntoIterator>::Item>>
134{
135}
136
137impl<T: IntoIterator<IntoIter = S>, S: ExactSizeIterator<Item = <T as IntoIterator>::Item>>
138 IntoExactSizeIterator for T
139{
140}
141
142pub trait TakeExact: Iterator {
145 fn take_exact(self, n: usize) -> TakeExactIter<Self>
148 where
149 Self: Sized,
150 {
151 TakeExactIter {
152 iter: self,
153 remaining: n,
154 }
155 }
156}
157
158impl<I: Iterator> TakeExact for I {}
159
160#[derive(Clone, Debug)]
162pub struct TakeExactIter<I> {
163 iter: I,
164 remaining: usize,
165}
166
167impl<I: Iterator> Iterator for TakeExactIter<I> {
168 type Item = I::Item;
169
170 fn next(&mut self) -> Option<Self::Item> {
171 if self.remaining == 0 {
172 return None;
173 }
174 self.remaining -= 1;
175 match self.iter.next() {
176 Some(item) => Some(item),
177 None => panic!("iterator shorter than expected length"),
178 }
179 }
180
181 fn size_hint(&self) -> (usize, Option<usize>) {
182 (self.remaining, Some(self.remaining))
183 }
184}
185
186impl<I: Iterator> ExactSizeIterator for TakeExactIter<I> {}
187
188#[cfg(test)]
189mod tests {
190 use crate::{izip_eq, izip_eq_lazy, utils::TakeExact};
191
192 #[test]
193 fn test_izip_eq() {
194 let a = [1, 2, 3];
195 let b = [4, 5, 6];
196 let c = [7, 8, 9];
197
198 {
199 let mut results = [0, 0, 0];
200 for (r, aa, bb, cc) in izip_eq_lazy!(&mut results, &a, &b, &c) {
201 *r = aa + bb + cc;
202 }
203
204 assert_eq!(results, [1 + 4 + 7, 2 + 5 + 8, 3 + 6 + 9]);
205 }
206 {
207 let mut results = [0, 0, 0];
208 for (r, aa, bb) in izip_eq_lazy!(&mut results, &a, &b) {
209 *r = aa + bb;
210 }
211
212 assert_eq!(results, [1 + 4, 2 + 5, 3 + 6]);
213 }
214 {
215 let mut results = [0, 0, 0];
216 for (r, aa) in izip_eq_lazy!(&mut results, &a) {
217 *r = *aa;
218 }
219
220 assert_eq!(results, [1, 2, 3]);
221 }
222 {
223 let mut result = 0;
224 for aa in izip_eq_lazy!(&a) {
225 result += *aa;
226 }
227
228 assert_eq!(result, 1 + 2 + 3);
229 }
230 {
231 let mut results = [0, 0, 0];
232 for (r, aa, bb, cc) in izip_eq!(&mut results, &a, &b, &c) {
233 *r = aa + bb + cc;
234 }
235
236 assert_eq!(results, [1 + 4 + 7, 2 + 5 + 8, 3 + 6 + 9]);
237 }
238 {
239 let mut results = [0, 0, 0];
240 for (r, aa, bb) in izip_eq!(&mut results, &a, &b) {
241 *r = aa + bb;
242 }
243
244 assert_eq!(results, [1 + 4, 2 + 5, 3 + 6]);
245 }
246 {
247 let mut results = [0, 0, 0];
248 for (r, aa) in izip_eq!(&mut results, &a) {
249 *r = *aa;
250 }
251
252 assert_eq!(results, [1, 2, 3]);
253 }
254 {
255 let mut result = 0;
256 for aa in izip_eq!(&a) {
257 result += *aa;
258 }
259
260 assert_eq!(result, 1 + 2 + 3);
261 }
262 }
263
264 #[test]
265 #[should_panic(expected = "itertools: .zip_eq() reached end of one iterator before the other")]
266 fn test_izip_eq_lazy_panic() {
267 let a = [1, 2, 3];
268 let b = [4, 5];
269 let c = [7, 8, 9];
270
271 let mut results = [0, 0, 0];
272 for (r, aa, bb, cc) in izip_eq_lazy!(&mut results, &a, &b, &c) {
273 *r = aa + bb + cc;
274 }
275 unreachable!()
276 }
277
278 #[test]
279 #[should_panic(expected = "itertools: .zip_eq() reached end of one iterator before the other")]
280 fn test_izip_eq_lazy_panic_2() {
281 let a = [1, 2, 3];
282 let b = [4, 5, 6];
283 let c = [7, 8, 9];
284
285 let mut results = [0, 0];
286 for (r, aa, bb, cc) in izip_eq_lazy!(&mut results, &a, &b, &c) {
287 *r = aa + bb + cc;
288 }
289 unreachable!()
290 }
291
292 #[test]
293 #[should_panic(expected = "iterator length mismatch: 3 vs 2")]
294 fn test_izip_eq_eager_panic() {
295 let a = [1, 2, 3];
296 let b = [4, 5];
297 let c = [7, 8, 9];
298
299 let mut results = [0, 0, 0];
300 for (r, aa, bb, cc) in izip_eq!(&mut results, &a, &b, &c) {
301 *r = aa + bb + cc;
302 }
303 unreachable!()
304 }
305
306 #[test]
307 #[should_panic(expected = "iterator length mismatch: 2 vs 3")]
308 fn test_izip_eq_eager_panic_2() {
309 let a = [1, 2, 3];
310 let b = [4, 5, 6];
311 let c = [7, 8, 9];
312
313 let mut results = [0, 0];
314 for (r, aa, bb, cc) in izip_eq!(&mut results, &a, &b, &c) {
315 *r = aa + bb + cc;
316 }
317 unreachable!()
318 }
319
320 #[test]
321 #[should_panic(expected = "iterator length mismatch: 2 vs 3")]
322 fn test_izip_eq_eager_panic_3() {
323 let a = [1, 2, 3];
324
325 let mut results = [0, 0];
326 for (r, aa) in izip_eq!(&mut results, &a) {
327 *r = *aa;
328 }
329 unreachable!()
330 }
331
332 #[test]
333 #[should_panic(expected = "iterator length mismatch: 3 vs 2")]
334 fn test_izip_eq_eager_panic_4() {
335 let a = [1, 2];
336
337 let mut results = [0, 0, 0];
338 for (r, aa) in izip_eq!(&mut results, &a) {
339 *r = *aa;
340 }
341 unreachable!()
342 }
343
344 #[test]
345 fn test_zip_maps() {
346 let keys = vec![1, 2, 3];
347 let mut map1: std::collections::HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into();
348 let mut map2: std::collections::HashMap<_, _> = [(1, "x"), (2, "y"), (3, "z")].into();
349
350 let result: Vec<_> = zip_maps!(keys, map1, map2).collect();
351
352 assert_eq!(result, vec![(1, "a", "x"), (2, "b", "y"), (3, "c", "z"),]);
353 }
354
355 #[test]
356 #[should_panic(expected = "Key `4` not found in map `map1`")]
357 fn test_zip_maps_missing_key_panic() {
358 let keys = vec![1, 2, 3, 4];
359 let mut map1: std::collections::HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into();
360 let mut map2: std::collections::HashMap<_, _> = [(1, "x"), (2, "y"), (3, "z")].into();
361
362 let _result: Vec<_> = zip_maps!(keys, map1, map2).collect();
363 }
364
365 #[test]
366 fn test_take_exact() {
367 let v = vec![1, 2, 3, 4, 5];
368 let mut iter = v.into_iter().take_exact(3);
369
370 assert_eq!(iter.len(), 3);
371 assert_eq!(iter.next(), Some(1));
372 assert_eq!(iter.len(), 2);
373 assert_eq!(iter.next(), Some(2));
374 assert_eq!(iter.len(), 1);
375 assert_eq!(iter.next(), Some(3));
376 assert_eq!(iter.len(), 0);
377 assert_eq!(iter.next(), None);
378 }
379
380 #[test]
381 #[should_panic(expected = "iterator shorter than expected length")]
382 fn test_take_exact_panic() {
383 let v = vec![1, 2];
384 let mut iter = v.into_iter().take_exact(3);
385
386 assert_eq!(iter.next(), Some(1));
387 assert_eq!(iter.next(), Some(2));
388 iter.next(); }
390
391 #[test]
392 fn test_take_exact_collect() {
393 let v = vec![1, 2, 3, 4, 5];
394 let result: Vec<_> = v.into_iter().take_exact(3).collect();
395 assert_eq!(result, vec![1, 2, 3]);
396 }
397
398 #[test]
399 fn test_take_exact_size_hint() {
400 let v = vec![1, 2, 3, 4, 5];
401 let iter = v.into_iter().take_exact(3);
402 assert_eq!(iter.size_hint(), (3, Some(3)));
403 }
404}