use super::plumbing::*; use super::*; use std::iter; use std::ops::Range; use std::usize; /// `Enumerate` is an iterator that returns the current count along with the element. /// This struct is created by the [`enumerate()`] method on [`IndexedParallelIterator`] /// /// [`enumerate()`]: trait.IndexedParallelIterator.html#method.enumerate /// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Debug, Clone)] pub struct Enumerate { base: I, } impl Enumerate where I: IndexedParallelIterator, { /// Creates a new `Enumerate` iterator. pub(super) fn new(base: I) -> Self { Enumerate { base } } } impl ParallelIterator for Enumerate where I: IndexedParallelIterator, { type Item = (usize, I::Item); fn drive_unindexed(self, consumer: C) -> C::Result where C: UnindexedConsumer, { bridge(self, consumer) } fn opt_len(&self) -> Option { Some(self.len()) } } impl IndexedParallelIterator for Enumerate where I: IndexedParallelIterator, { fn drive>(self, consumer: C) -> C::Result { bridge(self, consumer) } fn len(&self) -> usize { self.base.len() } fn with_producer(self, callback: CB) -> CB::Output where CB: ProducerCallback, { return self.base.with_producer(Callback { callback }); struct Callback { callback: CB, } impl ProducerCallback for Callback where CB: ProducerCallback<(usize, I)>, { type Output = CB::Output; fn callback

(self, base: P) -> CB::Output where P: Producer, { let producer = EnumerateProducer { base, offset: 0 }; self.callback.callback(producer) } } } } /// //////////////////////////////////////////////////////////////////////// /// Producer implementation struct EnumerateProducer

{ base: P, offset: usize, } impl

Producer for EnumerateProducer

where P: Producer, { type Item = (usize, P::Item); type IntoIter = iter::Zip, P::IntoIter>; fn into_iter(self) -> Self::IntoIter { // Enumerate only works for IndexedParallelIterators. Since those // have a max length of usize::MAX, their max index is // usize::MAX - 1, so the range 0..usize::MAX includes all // possible indices. // // However, we should to use a precise end to the range, otherwise // reversing the iterator may have to walk back a long ways before // `Zip::next_back` can produce anything. let base = self.base.into_iter(); let end = self.offset + base.len(); (self.offset..end).zip(base) } fn min_len(&self) -> usize { self.base.min_len() } fn max_len(&self) -> usize { self.base.max_len() } fn split_at(self, index: usize) -> (Self, Self) { let (left, right) = self.base.split_at(index); ( EnumerateProducer { base: left, offset: self.offset, }, EnumerateProducer { base: right, offset: self.offset + index, }, ) } }