Coverage Report

Created: 2025-10-10 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/itertools-0.12.1/src/rciter_impl.rs
Line
Count
Source
1
use alloc::rc::Rc;
2
use std::cell::RefCell;
3
use std::iter::{FusedIterator, IntoIterator};
4
5
/// A wrapper for `Rc<RefCell<I>>`, that implements the `Iterator` trait.
6
#[derive(Debug)]
7
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
8
pub struct RcIter<I> {
9
    /// The boxed iterator.
10
    pub rciter: Rc<RefCell<I>>,
11
}
12
13
/// Return an iterator inside a `Rc<RefCell<_>>` wrapper.
14
///
15
/// The returned `RcIter` can be cloned, and each clone will refer back to the
16
/// same original iterator.
17
///
18
/// `RcIter` allows doing interesting things like using `.zip()` on an iterator with
19
/// itself, at the cost of runtime borrow checking which may have a performance
20
/// penalty.
21
///
22
/// Iterator element type is `Self::Item`.
23
///
24
/// ```
25
/// use itertools::rciter;
26
/// use itertools::zip;
27
///
28
/// // In this example a range iterator is created and we iterate it using
29
/// // three separate handles (two of them given to zip).
30
/// // We also use the IntoIterator implementation for `&RcIter`.
31
///
32
/// let mut iter = rciter(0..9);
33
/// let mut z = zip(&iter, &iter);
34
///
35
/// assert_eq!(z.next(), Some((0, 1)));
36
/// assert_eq!(z.next(), Some((2, 3)));
37
/// assert_eq!(z.next(), Some((4, 5)));
38
/// assert_eq!(iter.next(), Some(6));
39
/// assert_eq!(z.next(), Some((7, 8)));
40
/// assert_eq!(z.next(), None);
41
/// ```
42
///
43
/// **Panics** in iterator methods if a borrow error is encountered in the
44
/// iterator methods. It can only happen if the `RcIter` is reentered in
45
/// `.next()`, i.e. if it somehow participates in an “iterator knot”
46
/// where it is an adaptor of itself.
47
0
pub fn rciter<I>(iterable: I) -> RcIter<I::IntoIter>
48
0
where
49
0
    I: IntoIterator,
50
{
51
0
    RcIter {
52
0
        rciter: Rc::new(RefCell::new(iterable.into_iter())),
53
0
    }
54
0
}
55
56
impl<I> Clone for RcIter<I> {
57
    clone_fields!(rciter);
58
}
59
60
impl<A, I> Iterator for RcIter<I>
61
where
62
    I: Iterator<Item = A>,
63
{
64
    type Item = A;
65
    #[inline]
66
0
    fn next(&mut self) -> Option<Self::Item> {
67
0
        self.rciter.borrow_mut().next()
68
0
    }
69
70
    #[inline]
71
0
    fn size_hint(&self) -> (usize, Option<usize>) {
72
        // To work sanely with other API that assume they own an iterator,
73
        // so it can't change in other places, we can't guarantee as much
74
        // in our size_hint. Other clones may drain values under our feet.
75
0
        (0, self.rciter.borrow().size_hint().1)
76
0
    }
77
}
78
79
impl<I> DoubleEndedIterator for RcIter<I>
80
where
81
    I: DoubleEndedIterator,
82
{
83
    #[inline]
84
0
    fn next_back(&mut self) -> Option<Self::Item> {
85
0
        self.rciter.borrow_mut().next_back()
86
0
    }
87
}
88
89
/// Return an iterator from `&RcIter<I>` (by simply cloning it).
90
impl<'a, I> IntoIterator for &'a RcIter<I>
91
where
92
    I: Iterator,
93
{
94
    type Item = I::Item;
95
    type IntoIter = RcIter<I>;
96
97
0
    fn into_iter(self) -> RcIter<I> {
98
0
        self.clone()
99
0
    }
100
}
101
102
impl<A, I> FusedIterator for RcIter<I> where I: FusedIterator<Item = A> {}