1use crate::{
2 DoubleEndedLender, ExactSizeLender, FallibleLend, FallibleLender, FallibleLending, FusedFallibleLender, FusedLender,
3 IntoLender, Lend, Lender, Lending,
4};
5
6pub fn zip<A, B>(a: A, b: B) -> Zip<A::Lender, B::Lender>
7where
8 A: IntoLender,
9 B: IntoLender,
10{
11 Zip::new(a.into_lender(), b.into_lender())
12}
13
14#[derive(Clone)]
15#[must_use = "lenders are lazy and do nothing unless consumed"]
16pub struct Zip<A, B> {
17 a: A,
18 b: B,
19}
20impl<A, B> Zip<A, B> {
21 pub(crate) fn new(a: A, b: B) -> Self {
22 Self { a, b }
23 }
24 pub fn into_inner(self) -> (A, B) {
25 (self.a, self.b)
26 }
27}
28impl<'lend, A, B> Lending<'lend> for Zip<A, B>
29where
30 A: Lender,
31 B: Lender,
32{
33 type Lend = (Lend<'lend, A>, Lend<'lend, B>);
34}
35impl<A, B> Lender for Zip<A, B>
36where
37 A: Lender,
38 B: Lender,
39{
40 #[inline]
41 fn next(&mut self) -> Option<Lend<'_, Self>> {
42 Some((self.a.next()?, self.b.next()?))
43 }
44 #[inline]
45 fn size_hint(&self) -> (usize, Option<usize>) {
46 let (a_lower, a_upper) = self.a.size_hint();
47 let (b_lower, b_upper) = self.b.size_hint();
48
49 let lower = core::cmp::min(a_lower, b_lower);
50
51 let upper = match (a_upper, b_upper) {
52 (Some(x), Some(y)) => Some(core::cmp::min(x, y)),
53 (Some(x), None) => Some(x),
54 (None, Some(y)) => Some(y),
55 (None, None) => None,
56 };
57
58 (lower, upper)
59 }
60}
61impl<A, B> DoubleEndedLender for Zip<A, B>
62where
63 A: DoubleEndedLender + ExactSizeIterator,
64 B: DoubleEndedLender + ExactSizeIterator,
65{
66 #[inline]
67 fn next_back(&mut self) -> Option<Lend<'_, Self>> {
68 let a_sz = self.a.len();
69 let b_sz = self.b.len();
70 if a_sz != b_sz {
71 if a_sz > b_sz {
73 for _ in 0..a_sz - b_sz {
74 self.a.next_back();
75 }
76 } else {
77 for _ in 0..b_sz - a_sz {
78 self.b.next_back();
79 }
80 }
81 }
82 match (self.a.next_back(), self.b.next_back()) {
83 (Some(x), Some(y)) => Some((x, y)),
84 (None, None) => None,
85 _ => unreachable!(),
86 }
87 }
88}
89impl<A, B> ExactSizeLender for Zip<A, B>
90where
91 A: ExactSizeLender,
92 B: ExactSizeLender,
93{
94}
95impl<A, B> FusedLender for Zip<A, B>
96where
97 A: FusedLender,
98 B: FusedLender,
99{
100}
101
102impl<'lend, A, B> FallibleLending<'lend> for Zip<A, B>
103where
104 A: FallibleLender,
105 B: FallibleLender<Error = A::Error>,
106{
107 type Lend = (FallibleLend<'lend, A>, FallibleLend<'lend, B>);
108}
109impl<A, B> FallibleLender for Zip<A, B>
110where
111 A: FallibleLender,
112 B: FallibleLender<Error = A::Error>,
113{
114 type Error = A::Error;
115
116 #[inline]
117 fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
118 let Some(value_a) = self.a.next()? else { return Ok(None) };
119 let Some(value_b) = self.b.next()? else { return Ok(None) };
120 Ok(Some((value_a, value_b)))
121 }
122 #[inline]
123 fn size_hint(&self) -> (usize, Option<usize>) {
124 let (a_lower, a_upper) = self.a.size_hint();
125 let (b_lower, b_upper) = self.b.size_hint();
126
127 let lower = core::cmp::min(a_lower, b_lower);
128
129 let upper = match (a_upper, b_upper) {
130 (Some(x), Some(y)) => Some(core::cmp::min(x, y)),
131 (Some(x), None) => Some(x),
132 (None, Some(y)) => Some(y),
133 (None, None) => None,
134 };
135
136 (lower, upper)
137 }
138}
139impl<A, B> FusedFallibleLender for Zip<A, B>
140where
141 A: FusedFallibleLender,
142 B: FusedFallibleLender<Error = A::Error>,
143{
144}