use super::plumbing::*; use super::*; use std::cmp; use std::iter; /// `Zip` is an iterator that zips up `a` and `b` into a single iterator /// of pairs. This struct is created by the [`zip()`] method on /// [`IndexedParallelIterator`] /// /// [`zip()`]: trait.IndexedParallelIterator.html#method.zip /// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Debug, Clone)] pub struct Zip { a: A, b: B, } impl Zip where A: IndexedParallelIterator, B: IndexedParallelIterator, { /// Creates a new `Zip` iterator. pub(super) fn new(a: A, b: B) -> Self { Zip { a, b } } } impl ParallelIterator for Zip where A: IndexedParallelIterator, B: IndexedParallelIterator, { type Item = (A::Item, B::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 Zip where A: IndexedParallelIterator, B: IndexedParallelIterator, { fn drive(self, consumer: C) -> C::Result where C: Consumer, { bridge(self, consumer) } fn len(&self) -> usize { cmp::min(self.a.len(), self.b.len()) } fn with_producer(self, callback: CB) -> CB::Output where CB: ProducerCallback, { return self.a.with_producer(CallbackA { callback, b: self.b, }); struct CallbackA { callback: CB, b: B, } impl ProducerCallback for CallbackA where B: IndexedParallelIterator, CB: ProducerCallback<(ITEM, B::Item)>, { type Output = CB::Output; fn callback(self, a_producer: A) -> Self::Output where A: Producer, { self.b.with_producer(CallbackB { a_producer, callback: self.callback, }) } } struct CallbackB { a_producer: A, callback: CB, } impl ProducerCallback for CallbackB where A: Producer, CB: ProducerCallback<(A::Item, ITEM)>, { type Output = CB::Output; fn callback(self, b_producer: B) -> Self::Output where B: Producer, { self.callback.callback(ZipProducer { a: self.a_producer, b: b_producer, }) } } } } /// //////////////////////////////////////////////////////////////////////// struct ZipProducer { a: A, b: B, } impl Producer for ZipProducer { type Item = (A::Item, B::Item); type IntoIter = iter::Zip; fn into_iter(self) -> Self::IntoIter { self.a.into_iter().zip(self.b.into_iter()) } fn min_len(&self) -> usize { cmp::max(self.a.min_len(), self.b.min_len()) } fn max_len(&self) -> usize { cmp::min(self.a.max_len(), self.b.max_len()) } fn split_at(self, index: usize) -> (Self, Self) { let (a_left, a_right) = self.a.split_at(index); let (b_left, b_right) = self.b.split_at(index); ( ZipProducer { a: a_left, b: b_left, }, ZipProducer { a: a_right, b: b_right, }, ) } }