Coverage Report

Created: 2026-02-14 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/itertools-0.10.5/src/zip_longest.rs
Line
Count
Source
1
use std::cmp::Ordering::{Equal, Greater, Less};
2
use super::size_hint;
3
use std::iter::{Fuse, FusedIterator};
4
5
use crate::either_or_both::EitherOrBoth;
6
7
// ZipLongest originally written by SimonSapin,
8
// and dedicated to itertools https://github.com/rust-lang/rust/pull/19283
9
10
/// An iterator which iterates two other iterators simultaneously
11
///
12
/// This iterator is *fused*.
13
///
14
/// See [`.zip_longest()`](crate::Itertools::zip_longest) for more information.
15
#[derive(Clone, Debug)]
16
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
17
pub struct ZipLongest<T, U> {
18
    a: Fuse<T>,
19
    b: Fuse<U>,
20
}
21
22
/// Create a new `ZipLongest` iterator.
23
0
pub fn zip_longest<T, U>(a: T, b: U) -> ZipLongest<T, U>
24
0
    where T: Iterator,
25
0
          U: Iterator
26
{
27
0
    ZipLongest {
28
0
        a: a.fuse(),
29
0
        b: b.fuse(),
30
0
    }
31
0
}
32
33
impl<T, U> Iterator for ZipLongest<T, U>
34
    where T: Iterator,
35
          U: Iterator
36
{
37
    type Item = EitherOrBoth<T::Item, U::Item>;
38
39
    #[inline]
40
0
    fn next(&mut self) -> Option<Self::Item> {
41
0
        match (self.a.next(), self.b.next()) {
42
0
            (None, None) => None,
43
0
            (Some(a), None) => Some(EitherOrBoth::Left(a)),
44
0
            (None, Some(b)) => Some(EitherOrBoth::Right(b)),
45
0
            (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
46
        }
47
0
    }
48
49
    #[inline]
50
0
    fn size_hint(&self) -> (usize, Option<usize>) {
51
0
        size_hint::max(self.a.size_hint(), self.b.size_hint())
52
0
    }
53
}
54
55
impl<T, U> DoubleEndedIterator for ZipLongest<T, U>
56
    where T: DoubleEndedIterator + ExactSizeIterator,
57
          U: DoubleEndedIterator + ExactSizeIterator
58
{
59
    #[inline]
60
0
    fn next_back(&mut self) -> Option<Self::Item> {
61
0
        match self.a.len().cmp(&self.b.len()) {
62
0
            Equal => match (self.a.next_back(), self.b.next_back()) {
63
0
                (None, None) => None,
64
0
                (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
65
                // These can only happen if .len() is inconsistent with .next_back()
66
0
                (Some(a), None) => Some(EitherOrBoth::Left(a)),
67
0
                (None, Some(b)) => Some(EitherOrBoth::Right(b)),
68
            },
69
0
            Greater => self.a.next_back().map(EitherOrBoth::Left),
70
0
            Less => self.b.next_back().map(EitherOrBoth::Right),
71
        }
72
0
    }
73
}
74
75
impl<T, U> ExactSizeIterator for ZipLongest<T, U>
76
    where T: ExactSizeIterator,
77
          U: ExactSizeIterator
78
{}
79
80
impl<T, U> FusedIterator for ZipLongest<T, U>
81
    where T: Iterator,
82
          U: Iterator
83
{}