/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> {} |