Skip to main content

lender/fallible_sources/
from_iter.rs

1use fallible_iterator::{DoubleEndedFallibleIterator, FallibleIterator, IntoFallibleIterator};
2
3use crate::{
4    CovariantFallibleLending, DoubleEndedFallibleLender, FallibleLend, FallibleLender,
5    FallibleLending, IntoFallibleLender, prelude::*,
6};
7
8/// Creates a lender from a fallible iterator.
9///
10/// This function can be conveniently accessed using the
11/// [`into_fallible_lender`][ifl] method added to
12/// [`FallibleIterator`] by this crate.
13///
14/// [ifl]: crate::traits::FallibleIteratorExt::into_fallible_lender
15///
16/// Does not change the behavior of the iterator: the resulting
17/// lender will yield the same items and can be adapted back into
18/// an iterator.
19///
20/// # Examples
21/// ```rust
22/// # use lender::prelude::*; let data = [1, 2, 3];
23/// let mut lender = data.iter().into_lender().into_fallible();
24/// assert_eq!(lender.next().unwrap(), Some(&1));
25/// ```
26#[inline]
27pub fn from_iter<I: FallibleIterator>(iter: I) -> FromIter<I> {
28    FromIter { iter }
29}
30
31/// A lender that yields elements from a fallible iterator.
32///
33/// This `struct` is created by the
34/// [`from_fallible_iter()`](crate::from_fallible_iter)
35/// function.
36#[derive(Clone, Debug)]
37#[repr(transparent)]
38#[must_use = "lenders are lazy and do nothing unless consumed"]
39pub struct FromIter<I> {
40    iter: I,
41}
42
43impl<I: FallibleIterator> FallibleLending<'_> for FromIter<I> {
44    type Lend = I::Item;
45}
46
47impl<I: FallibleIterator> FallibleLender for FromIter<I> {
48    type Error = I::Error;
49    crate::check_covariance_fallible!();
50    #[inline(always)]
51    fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
52        self.iter.next()
53    }
54
55    #[inline(always)]
56    fn size_hint(&self) -> (usize, Option<usize>) {
57        self.iter.size_hint()
58    }
59
60    #[inline(always)]
61    fn nth(&mut self, n: usize) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
62        self.iter.nth(n)
63    }
64
65    #[inline(always)]
66    fn count(self) -> Result<usize, Self::Error>
67    where
68        Self: Sized,
69    {
70        self.iter.count()
71    }
72
73    #[inline(always)]
74    fn fold<B, F>(self, init: B, f: F) -> Result<B, Self::Error>
75    where
76        Self: Sized,
77        F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
78    {
79        self.iter.fold(init, f)
80    }
81}
82
83impl<I: DoubleEndedFallibleIterator> DoubleEndedFallibleLender for FromIter<I> {
84    #[inline(always)]
85    fn next_back(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
86        self.iter.next_back()
87    }
88
89    #[inline(always)]
90    fn rfold<B, F>(self, init: B, f: F) -> Result<B, Self::Error>
91    where
92        Self: Sized,
93        F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
94    {
95        self.iter.rfold(init, f)
96    }
97}
98
99// Note: FusedFallibleLender and ExactSizeFallibleLender are not
100// implemented for FromIter because the fallible_iterator crate
101// does not expose FusedFallibleIterator or
102// ExactSizeFallibleIterator marker traits.
103
104impl<I: FallibleIterator> From<I> for FromIter<I> {
105    #[inline(always)]
106    fn from(iter: I) -> Self {
107        from_iter(iter)
108    }
109}
110
111/// Creates an [`IntoFallibleLender`] from an
112/// [`IntoFallibleIterator`].
113///
114/// This function can be conveniently accessed using the
115/// [`into_into_fallible_lender`][iifl] method added to
116/// [`IntoFallibleIterator`] by this crate.
117///
118/// [iifl]: crate::traits::IntoFallibleIteratorExt::into_into_fallible_lender
119///
120/// The lenders returned are obtained by applying
121/// [`from_fallible_iter()`](crate::from_fallible_iter) to
122/// the iterators returned by the wrapped
123/// [`IntoFallibleIterator`].
124///
125/// # Examples
126/// ```rust
127/// # use lender::prelude::*;
128/// # use fallible_iterator::IteratorExt;
129/// let data = [1, 2, 3];
130/// let into_lender = lender::from_into_fallible_iter(
131///     data.iter().into_fallible(),
132/// );
133/// let mut lender = into_lender.into_fallible_lender();
134/// assert_eq!(lender.next().unwrap(), Some(&1));
135/// ```
136#[inline]
137pub fn from_into_iter<I: IntoFallibleIterator>(into_iter: I) -> FromIntoIter<I> {
138    FromIntoIter { into_iter }
139}
140
141/// An [`IntoFallibleLender`] that returns lenders obtained
142/// by applying
143/// [`from_fallible_iter()`](crate::from_fallible_iter) to
144/// the iterators returned by the wrapped
145/// [`IntoFallibleIterator`].
146///
147/// This `struct` is created by the
148/// [`from_into_fallible_iter()`](crate::from_into_fallible_iter)
149/// function.
150#[repr(transparent)]
151#[derive(Clone, Debug)]
152pub struct FromIntoIter<I> {
153    into_iter: I,
154}
155
156impl<I: IntoFallibleIterator> IntoFallibleLender for FromIntoIter<I> {
157    type Error = I::Error;
158
159    type FallibleLender = FromIter<I::IntoFallibleIter>;
160
161    #[inline(always)]
162    fn into_fallible_lender(self) -> <Self as IntoFallibleLender>::FallibleLender {
163        self.into_iter.into_fallible_iter().into_fallible_lender()
164    }
165}
166
167impl<I: IntoFallibleIterator> From<I> for FromIntoIter<I> {
168    #[inline(always)]
169    fn from(into_iter: I) -> Self {
170        from_into_iter(into_iter)
171    }
172}
173
174/// Creates a fallible lender from a fallible iterator `I`,
175/// safely shortening the items' lifetimes with the given
176/// lending type `L`.
177///
178/// If `I::Item` is 'static, behaves like [`from_iter()`].
179///
180/// # Examples
181/// ```rust
182/// # use lender::prelude::*;
183/// # use fallible_iterator::IteratorExt;
184/// let mut data = [1, 2, 3];
185///
186/// // properly shortens the lifetime of non-static items and lends them
187/// let mut lender = lender::lend_fallible_iter::<
188///     '_, fallible_lend!(&'lend i32), _,
189/// >(data.iter().into_fallible());
190/// let lend: Option<&'_ i32> = lender.next().unwrap();
191/// let lend: &'_ i32 = lend.unwrap();
192///
193/// // does not shorten the lifetime of 'static items
194/// let mut lender = lender::lend_fallible_iter::<
195///     '_, fallible_lend!(i32), _,
196/// >([1, 2, 3].into_iter().into_fallible());
197/// let item: Option<i32> = lender.next().unwrap();
198/// let item: i32 = item.unwrap();
199/// let item2: Option<i32> = lender.next().unwrap();
200/// let item2: i32 = item2.unwrap();
201/// ```
202#[inline]
203pub fn lend_iter<'a, L, I>(iter: I) -> LendIter<'a, L, I>
204where
205    L: ?Sized + CovariantFallibleLending + 'a,
206    I: FallibleIterator<Item = FallibleLend<'a, L>>,
207{
208    let _ = L::__check_covariance(crate::CovariantProof::new());
209    LendIter {
210        iter,
211        _marker: core::marker::PhantomData,
212    }
213}
214
215/// A lender that lends elements from a fallible iterator by
216/// shortening their lifetime.
217///
218/// If `I::Item` is 'static, behaves like [`FromIter`].
219///
220/// This `struct` is created by the
221/// [`lend_fallible_iter()`](crate::lend_fallible_iter)
222/// function.
223#[derive(Clone, Debug)]
224#[must_use = "lenders are lazy and do nothing unless consumed"]
225pub struct LendIter<'a, L: ?Sized, I> {
226    iter: I,
227    _marker: core::marker::PhantomData<&'a L>,
228}
229
230impl<'a, 'lend, L, I> FallibleLending<'lend> for LendIter<'a, L, I>
231where
232    L: ?Sized + CovariantFallibleLending + 'a,
233    I: FallibleIterator<Item = FallibleLend<'a, L>>,
234{
235    type Lend = FallibleLend<'lend, L>;
236}
237
238impl<'a, L, I> FallibleLender for LendIter<'a, L, I>
239where
240    L: ?Sized + CovariantFallibleLending + 'a,
241    I: FallibleIterator<Item = FallibleLend<'a, L>>,
242{
243    type Error = I::Error;
244    // SAFETY: the lend is the type parameter L
245    crate::unsafe_assume_covariance_fallible!();
246
247    #[inline]
248    fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
249        let next = self.iter.next()?;
250        Ok(
251            // SAFETY: 'a: 'lend
252            unsafe {
253                core::mem::transmute::<Option<FallibleLend<'a, L>>, Option<FallibleLend<'_, L>>>(
254                    next,
255                )
256            },
257        )
258    }
259
260    #[inline(always)]
261    fn size_hint(&self) -> (usize, Option<usize>) {
262        self.iter.size_hint()
263    }
264
265    #[inline]
266    fn nth(&mut self, n: usize) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
267        let nth = self.iter.nth(n)?;
268        Ok(
269            // SAFETY: 'a: 'lend
270            unsafe {
271                core::mem::transmute::<Option<FallibleLend<'a, L>>, Option<FallibleLend<'_, L>>>(
272                    nth,
273                )
274            },
275        )
276    }
277
278    #[inline(always)]
279    fn count(self) -> Result<usize, Self::Error>
280    where
281        Self: Sized,
282    {
283        self.iter.count()
284    }
285
286    #[inline]
287    fn fold<B, F>(self, init: B, mut f: F) -> Result<B, Self::Error>
288    where
289        Self: Sized,
290        F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
291    {
292        self.iter.fold(init, |acc, x| {
293            // SAFETY: 'a: 'lend, and FallibleLend<'a, L> is covariant in 'a
294            f(acc, unsafe {
295                core::mem::transmute::<FallibleLend<'a, L>, FallibleLend<'_, L>>(x)
296            })
297        })
298    }
299}
300
301impl<'a, L, I> DoubleEndedFallibleLender for LendIter<'a, L, I>
302where
303    L: ?Sized + CovariantFallibleLending + 'a,
304    I: DoubleEndedFallibleIterator<Item = FallibleLend<'a, L>>,
305{
306    #[inline]
307    fn next_back(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
308        let next = self.iter.next_back()?;
309        Ok(
310            // SAFETY: 'a: 'lend
311            unsafe {
312                core::mem::transmute::<Option<FallibleLend<'a, L>>, Option<FallibleLend<'_, L>>>(
313                    next,
314                )
315            },
316        )
317    }
318
319    #[inline]
320    fn rfold<B, F>(self, init: B, mut f: F) -> Result<B, Self::Error>
321    where
322        Self: Sized,
323        F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
324    {
325        self.iter.rfold(init, |acc, x| {
326            // SAFETY: 'a: 'lend, and FallibleLend<'a, L> is covariant in 'a
327            f(acc, unsafe {
328                core::mem::transmute::<FallibleLend<'a, L>, FallibleLend<'_, L>>(x)
329            })
330        })
331    }
332}
333
334// Note: FusedFallibleLender and ExactSizeFallibleLender are not
335// implemented for LendIter because the fallible_iterator crate
336// does not expose FusedFallibleIterator or
337// ExactSizeFallibleIterator marker traits.