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