gat_lending_iterator/adapters/
fuse.rs

1use crate::LendingIterator;
2use core::fmt;
3
4/// A lending iterator that yields `None` forever after the underlying iterator
5/// yields `None` once.
6///
7/// This `struct` is created by the [`fuse`] method on [`LendingIterator`]. See
8/// its documentation for more.
9///
10/// [`LendingIterator`]: crate::LendingIterator
11/// [`fuse`]: crate::LendingIterator::fuse
12#[derive(Clone)]
13#[must_use = "iterators are lazy and do nothing unless consumed"]
14pub struct Fuse<I> {
15    iter: Option<I>,
16}
17
18impl<I> Fuse<I> {
19    pub(crate) fn new(iter: I) -> Self {
20        Self { iter: Some(iter) }
21    }
22}
23
24impl<I: fmt::Debug> fmt::Debug for Fuse<I> {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        f.debug_struct("Fuse").field("iter", &self.iter).finish()
27    }
28}
29
30impl<I> LendingIterator for Fuse<I>
31where
32    I: LendingIterator,
33{
34    type Item<'a>
35        = I::Item<'a>
36    where
37        Self: 'a;
38
39    #[inline]
40    fn next(&mut self) -> Option<Self::Item<'_>> {
41        // SAFETY: see https://docs.rs/polonius-the-crab/0.3.1/polonius_the_crab/#the-arcanemagic
42        let self_ = unsafe { &mut *(self as *mut Self) };
43        let iter = self_.iter.as_mut()?;
44        if let Some(item) = iter.next() {
45            Some(item)
46        } else {
47            self.iter = None;
48            None
49        }
50    }
51
52    #[inline]
53    #[allow(clippy::redundant_closure_for_method_calls)]
54    fn size_hint(&self) -> (usize, Option<usize>) {
55        self.iter
56            .as_ref()
57            .map_or((0, Some(0)), |iter| iter.size_hint())
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use crate::{LendingIterator, ToLendingIterator};
64
65    struct OneThenError {
66        yielded: bool,
67    }
68
69    impl OneThenError {
70        fn new() -> Self {
71            Self { yielded: false }
72        }
73    }
74
75    impl LendingIterator for OneThenError {
76        type Item<'a>
77            = i32
78        where
79            Self: 'a;
80
81        fn next(&mut self) -> Option<Self::Item<'_>> {
82            if self.yielded {
83                None
84            } else {
85                self.yielded = true;
86                Some(1)
87            }
88        }
89    }
90
91    fn identity(x: i32) -> i32 {
92        x
93    }
94
95    #[test]
96    fn fuse_basic() {
97        let mut iter = OneThenError::new().fuse();
98        assert_eq!(iter.next(), Some(1));
99        assert_eq!(iter.next(), None);
100        assert_eq!(iter.next(), None);
101        assert_eq!(iter.next(), None);
102    }
103
104    #[test]
105    fn fuse_regular_iter() {
106        let result: Vec<_> = (0..5)
107            .into_lending()
108            .fuse()
109            .map(identity)
110            .into_iter()
111            .collect();
112        assert_eq!(result, vec![0, 1, 2, 3, 4]);
113    }
114}