| 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 | pub fn rciter<I>(iterable: I) -> RcIter<I::IntoIter> | 
|---|
| 48 | where | 
|---|
| 49 | I: IntoIterator, | 
|---|
| 50 | { | 
|---|
| 51 | RcIter { | 
|---|
| 52 | rciter: Rc::new(RefCell::new(iterable.into_iter())), | 
|---|
| 53 | } | 
|---|
| 54 | } | 
|---|
| 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 | fn next(&mut self) -> Option<Self::Item> { | 
|---|
| 67 | self.rciter.borrow_mut().next() | 
|---|
| 68 | } | 
|---|
| 69 |  | 
|---|
| 70 | #[ inline] | 
|---|
| 71 | 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, self.rciter.borrow().size_hint().1) | 
|---|
| 76 | } | 
|---|
| 77 | } | 
|---|
| 78 |  | 
|---|
| 79 | impl<I> DoubleEndedIterator for RcIter<I> | 
|---|
| 80 | where | 
|---|
| 81 | I: DoubleEndedIterator, | 
|---|
| 82 | { | 
|---|
| 83 | #[ inline] | 
|---|
| 84 | fn next_back(&mut self) -> Option<Self::Item> { | 
|---|
| 85 | self.rciter.borrow_mut().next_back() | 
|---|
| 86 | } | 
|---|
| 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 | fn into_iter(self) -> RcIter<I> { | 
|---|
| 98 | self.clone() | 
|---|
| 99 | } | 
|---|
| 100 | } | 
|---|
| 101 |  | 
|---|
| 102 | impl<A, I> FusedIterator for RcIter<I> where I: FusedIterator<Item = A> {} | 
|---|
| 103 |  | 
|---|