Skip to main content

lender/adapters/
enumerate.rs

1use core::num::NonZeroUsize;
2
3use crate::{
4    DoubleEndedLender, ExactSizeLender, FusedLender, Lend, Lender, Lending, try_trait_v2::Try,
5};
6
7/// A lender that yields the current count and the element during iteration.
8///
9/// This `struct` is created by the [`enumerate()`](crate::Lender::enumerate)
10/// method on [`Lender`].
11#[derive(Clone, Debug)]
12#[must_use = "lenders are lazy and do nothing unless consumed"]
13pub struct Enumerate<L> {
14    pub(crate) lender: L,
15    pub(crate) count: usize,
16}
17
18impl<L> Enumerate<L> {
19    /// Returns the inner lender.
20    #[inline(always)]
21    pub fn into_inner(self) -> L {
22        self.lender
23    }
24
25    /// Returns the inner lender and the current count.
26    #[inline(always)]
27    pub fn into_parts(self) -> (L, usize) {
28        (self.lender, self.count)
29    }
30}
31
32impl<L: Lender> Enumerate<L> {
33    #[inline(always)]
34    pub(crate) fn new(lender: L) -> Enumerate<L> {
35        let _ = L::__check_covariance(crate::CovariantProof::new());
36        Enumerate { lender, count: 0 }
37    }
38}
39
40impl<'lend, L> Lending<'lend> for Enumerate<L>
41where
42    L: Lender,
43{
44    type Lend = (usize, Lend<'lend, L>);
45}
46
47impl<L> Lender for Enumerate<L>
48where
49    L: Lender,
50{
51    // SAFETY: the lend is a pair of usize and the lend of L
52    crate::unsafe_assume_covariance!();
53    #[inline]
54    fn next(&mut self) -> Option<Lend<'_, Self>> {
55        self.lender.next().map(|x| {
56            let count = self.count;
57            self.count += 1;
58            (count, x)
59        })
60    }
61
62    #[inline(always)]
63    fn size_hint(&self) -> (usize, Option<usize>) {
64        self.lender.size_hint()
65    }
66
67    #[inline]
68    fn nth(&mut self, n: usize) -> Option<Lend<'_, Self>> {
69        let a = self.lender.nth(n)?;
70        // May overflow on very large indices; matches std::iter::Enumerate.
71        let i = self.count + n;
72        self.count = i + 1;
73        Some((i, a))
74    }
75
76    #[inline(always)]
77    fn count(self) -> usize {
78        self.lender.count()
79    }
80
81    #[inline]
82    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
83    where
84        Self: Sized,
85        F: FnMut(B, Lend<'_, Self>) -> R,
86        R: Try<Output = B>,
87    {
88        let count = &mut self.count;
89        self.lender.try_fold(init, |acc, x| {
90            let elt = (*count, x);
91            *count += 1;
92            f(acc, elt)
93        })
94    }
95
96    #[inline]
97    fn fold<B, F>(self, init: B, mut f: F) -> B
98    where
99        Self: Sized,
100        F: FnMut(B, Lend<'_, Self>) -> B,
101    {
102        let mut count = self.count;
103        self.lender.fold(init, |acc, x| {
104            let elt = (count, x);
105            count += 1;
106            f(acc, elt)
107        })
108    }
109
110    #[inline]
111    fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
112        let remaining = self.lender.advance_by(n);
113        let advanced = match remaining {
114            Ok(()) => n,
115            Err(rem) => n - rem.get(),
116        };
117        self.count += advanced;
118        remaining
119    }
120}
121
122impl<L> DoubleEndedLender for Enumerate<L>
123where
124    L: ExactSizeLender + DoubleEndedLender,
125{
126    #[inline]
127    fn next_back(&mut self) -> Option<Lend<'_, Self>> {
128        let len = self.lender.len();
129        let x = self.lender.next_back()?;
130        Some((self.count + len - 1, x))
131    }
132
133    #[inline]
134    fn nth_back(&mut self, n: usize) -> Option<Lend<'_, Self>> {
135        let len = self.lender.len();
136        let x = self.lender.nth_back(n)?;
137        Some((self.count + len - n - 1, x))
138    }
139
140    #[inline]
141    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
142    where
143        Self: Sized,
144        F: FnMut(B, Lend<'_, Self>) -> R,
145        R: Try<Output = B>,
146    {
147        let mut count = self.count + self.lender.len();
148        self.lender.try_rfold(init, move |acc, x| {
149            count -= 1;
150            f(acc, (count, x))
151        })
152    }
153
154    #[inline]
155    fn rfold<B, F>(self, init: B, mut f: F) -> B
156    where
157        Self: Sized,
158        F: FnMut(B, Lend<'_, Self>) -> B,
159    {
160        let mut count = self.count + self.lender.len();
161        self.lender.rfold(init, move |acc, x| {
162            count -= 1;
163            f(acc, (count, x))
164        })
165    }
166
167    #[inline(always)]
168    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
169        self.lender.advance_back_by(n)
170    }
171}
172
173impl<L> ExactSizeLender for Enumerate<L>
174where
175    L: ExactSizeLender,
176{
177    #[inline(always)]
178    fn len(&self) -> usize {
179        self.lender.len()
180    }
181
182    #[inline(always)]
183    fn is_empty(&self) -> bool {
184        self.lender.is_empty()
185    }
186}
187
188impl<L> FusedLender for Enumerate<L> where L: FusedLender {}
189
190impl<L: Default + Lender> Default for Enumerate<L> {
191    #[inline(always)]
192    fn default() -> Self {
193        Enumerate::new(Default::default())
194    }
195}