Skip to main content

calc_lib/
lending_iterator.rs

1/// Unit tests.
2#[cfg(test)]
3mod tests;
4/// Generalizes [`Iterator`] by allowing one to yield references.
5pub trait LendingIterator {
6    /// Read [`Iterator::Item`].
7    type Item<'a>
8    where
9        Self: 'a;
10    /// Read [`Iterator::next`].
11    fn lend_next(&mut self) -> Option<Self::Item<'_>>;
12    /// Read [`Iterator::size_hint`].
13    #[inline]
14    fn size_hint(&self) -> (usize, Option<usize>) {
15        (0, None)
16    }
17    /// Read [`Iterator::count`].
18    #[expect(
19        clippy::arithmetic_side_effects,
20        reason = "must, and overflow is no worry"
21    )]
22    #[inline]
23    fn count(self) -> usize
24    where
25        Self: Sized,
26    {
27        self.lend_fold(0, |count, _| count + 1)
28    }
29    /// Read [`Iterator::advance_by`].
30    ///
31    /// # Errors
32    ///
33    /// Read [`Iterator::advance_by`].
34    #[inline]
35    fn advance_by(&mut self, n: usize) -> Result<(), usize> {
36        for i in 0..n {
37            drop(self.lend_next().ok_or(i)?);
38        }
39        Ok(())
40    }
41    /// Read [`Iterator::by_ref`].
42    #[inline]
43    fn by_ref(&mut self) -> &mut Self
44    where
45        Self: Sized,
46    {
47        self
48    }
49    /// Read [`Iterator::try_fold`].
50    /// # Errors
51    ///
52    /// Read [`Iterator::try_fold`].
53    #[inline]
54    fn lend_try_fold<B, E, F>(&mut self, init: B, mut f: F) -> Result<B, E>
55    where
56        Self: Sized,
57        F: FnMut(B, Self::Item<'_>) -> Result<B, E>,
58    {
59        let mut accum = init;
60        while let Some(x) = self.lend_next() {
61            accum = f(accum, x)?;
62        }
63        Ok(accum)
64    }
65    /// Read [`Iterator::fold`].
66    #[inline]
67    fn lend_fold<B, F>(mut self, init: B, mut f: F) -> B
68    where
69        Self: Sized,
70        F: FnMut(B, Self::Item<'_>) -> B,
71    {
72        let mut accum = init;
73        while let Some(x) = self.lend_next() {
74            accum = f(accum, x);
75        }
76        accum
77    }
78}
79impl<T> LendingIterator for T
80where
81    T: Iterator,
82{
83    type Item<'a>
84        = T::Item
85    where
86        Self: 'a;
87    #[inline]
88    fn lend_next(&mut self) -> Option<Self::Item<'_>> {
89        self.next()
90    }
91    #[inline]
92    fn size_hint(&self) -> (usize, Option<usize>) {
93        self.size_hint()
94    }
95    #[inline]
96    fn count(self) -> usize
97    where
98        Self: Sized,
99    {
100        self.count()
101    }
102    #[inline]
103    fn advance_by(&mut self, n: usize) -> Result<(), usize> {
104        for i in 0..n {
105            drop(self.lend_next().ok_or(i)?);
106        }
107        Ok(())
108    }
109    #[inline]
110    fn by_ref(&mut self) -> &mut Self
111    where
112        Self: Sized,
113    {
114        self
115    }
116    // Due to a bug in GATs, fold and try_fold cannot be
117    // implemented.
118}