Skip to main content

lender/sources/
from_iter_ref.rs

1use core::iter::FusedIterator;
2use core::num::NonZeroUsize;
3use core::ops::ControlFlow;
4
5use crate::try_trait_v2::Try;
6use crate::{FusedLender, prelude::*};
7
8/// Creates a lender that stores each element from an iterator
9/// and lends a reference to it.
10///
11/// This function can be conveniently accessed using the
12/// [`into_ref_lender`](crate::traits::IteratorRefExt::into_ref_lender)
13/// extension method.
14///
15/// Unlike [`from_iter`](crate::from_iter), which passes items
16/// through transparently, this source stores each element
17/// internally and lends a reference to it, turning an
18/// `Iterator<Item = T>` into a `Lender` with
19/// `Lend<'lend> = &'lend T`.
20///
21/// # Examples
22/// ```rust
23/// # use lender::prelude::*;
24/// let mut lender = lender::from_iter_ref([1, 2, 3].into_iter());
25/// let item: &i32 = lender.next().unwrap();
26/// assert_eq!(*item, 1);
27/// ```
28#[inline]
29pub fn from_iter_ref<I: Iterator>(iter: I) -> FromIterRef<I> {
30    FromIterRef {
31        iter,
32        current: None,
33    }
34}
35
36/// A lender that stores each element from an iterator and
37/// lends a reference to it.
38///
39/// This `struct` is created by the [`from_iter_ref()`]
40/// function.
41#[derive(Clone, Debug)]
42#[must_use = "lenders are lazy and do nothing unless consumed"]
43pub struct FromIterRef<I: Iterator> {
44    iter: I,
45    current: Option<I::Item>,
46}
47
48impl<'lend, I: Iterator> Lending<'lend> for FromIterRef<I> {
49    type Lend = &'lend I::Item;
50}
51
52impl<I: Iterator> Lender for FromIterRef<I> {
53    crate::check_covariance!();
54
55    #[inline]
56    fn next(&mut self) -> Option<Lend<'_, Self>> {
57        self.current = self.iter.next();
58        self.current.as_ref()
59    }
60
61    #[inline(always)]
62    fn size_hint(&self) -> (usize, Option<usize>) {
63        self.iter.size_hint()
64    }
65
66    #[inline]
67    fn nth(&mut self, n: usize) -> Option<Lend<'_, Self>> {
68        self.current = self.iter.nth(n);
69        self.current.as_ref()
70    }
71
72    #[inline(always)]
73    fn count(self) -> usize
74    where
75        Self: Sized,
76    {
77        self.iter.count()
78    }
79
80    #[inline]
81    fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
82        for i in 0..n {
83            if self.iter.next().is_none() {
84                // SAFETY: `i` is always less than `n`.
85                return Err(unsafe { NonZeroUsize::new_unchecked(n - i) });
86            }
87        }
88        Ok(())
89    }
90
91    #[inline]
92    fn last<'call>(&'call mut self) -> Option<Lend<'call, Self>>
93    where
94        Self: Sized,
95    {
96        self.current = None;
97        for x in self.iter.by_ref() {
98            self.current = Some(x);
99        }
100        self.current.as_ref()
101    }
102
103    #[inline]
104    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
105    where
106        F: FnMut(B, Lend<'_, Self>) -> R,
107        R: Try<Output = B>,
108    {
109        let mut acc = init;
110        for item in self.iter.by_ref() {
111            acc = match f(acc, &item).branch() {
112                ControlFlow::Break(x) => return R::from_residual(x),
113                ControlFlow::Continue(x) => x,
114            };
115        }
116        R::from_output(acc)
117    }
118
119    #[inline]
120    fn fold<B, F>(self, init: B, mut f: F) -> B
121    where
122        Self: Sized,
123        F: FnMut(B, Lend<'_, Self>) -> B,
124    {
125        self.iter.fold(init, |acc, item| f(acc, &item))
126    }
127}
128
129impl<I: DoubleEndedIterator> DoubleEndedLender for FromIterRef<I> {
130    #[inline]
131    fn next_back(&mut self) -> Option<Lend<'_, Self>> {
132        self.current = self.iter.next_back();
133        self.current.as_ref()
134    }
135
136    #[inline]
137    fn nth_back(&mut self, n: usize) -> Option<Lend<'_, Self>> {
138        self.current = self.iter.nth_back(n);
139        self.current.as_ref()
140    }
141
142    #[inline]
143    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
144        for i in 0..n {
145            if self.iter.next_back().is_none() {
146                // SAFETY: `i` is always less than `n`.
147                return Err(unsafe { NonZeroUsize::new_unchecked(n - i) });
148            }
149        }
150        Ok(())
151    }
152
153    #[inline]
154    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
155    where
156        F: FnMut(B, Lend<'_, Self>) -> R,
157        R: Try<Output = B>,
158    {
159        let mut acc = init;
160        while let Some(item) = self.iter.next_back() {
161            acc = match f(acc, &item).branch() {
162                ControlFlow::Break(x) => return R::from_residual(x),
163                ControlFlow::Continue(x) => x,
164            };
165        }
166        R::from_output(acc)
167    }
168
169    #[inline]
170    fn rfold<B, F>(self, init: B, mut f: F) -> B
171    where
172        Self: Sized,
173        F: FnMut(B, Lend<'_, Self>) -> B,
174    {
175        self.iter.rfold(init, |acc, item| f(acc, &item))
176    }
177}
178
179impl<I: ExactSizeIterator> ExactSizeLender for FromIterRef<I> {
180    #[inline(always)]
181    fn len(&self) -> usize {
182        self.iter.len()
183    }
184}
185
186impl<I: FusedIterator> FusedLender for FromIterRef<I> {}
187
188impl<I: Iterator> From<I> for FromIterRef<I> {
189    #[inline(always)]
190    fn from(iter: I) -> Self {
191        from_iter_ref(iter)
192    }
193}