use std::iter::Zip; use std::ops::Range; use crate::{ Consumer, Executor, ExecutorCallback, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, ParallelIterator, Producer, Reducer, Setup, WithIndexedProducer, WithSetup, }; /* Enumerate */ pub struct Enumerate { base: X, } impl Enumerate { pub fn new(base: X) -> Self { Self { base } } } impl<'a, X, I> ParallelIterator<'a> for Enumerate where X: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, I: Send + 'a, { type Item = (usize, I); fn drive(self, executor: E, consumer: C) -> E::Result where E: Executor<'a, D>, C: Consumer + 'a, D: Send + 'a, R: Reducer + Send + 'a, { self.with_indexed_producer(ExecutorCallback::new(executor, consumer)) } fn len_hint_opt(&self) -> Option { self.base.len_hint_opt() } } impl<'a, X, I> IndexedParallelIterator<'a> for Enumerate where X: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>, I: Send + 'a, { fn drive_indexed(self, executor: E, consumer: C) -> E::Result where E: Executor<'a, D>, C: Consumer + 'a, D: Send + 'a, R: Reducer + Send + 'a, { self.with_indexed_producer(ExecutorCallback::new(executor, consumer)) } fn len_hint(&self) -> usize { self.base.len_hint() } } impl<'a, X> WithIndexedProducer<'a> for Enumerate where X: WithIndexedProducer<'a>, { type Item = (usize, X::Item); fn with_indexed_producer(self, base: CB) -> CB::Output where CB: IndexedProducerCallback<'a, Self::Item>, { self.base.with_indexed_producer(EnumerateCallback { base }) } } /* EnumerateCallback */ struct EnumerateCallback { base: CB, } impl<'a, CB, I> IndexedProducerCallback<'a, I> for EnumerateCallback where CB: IndexedProducerCallback<'a, (usize, I)>, { type Output = CB::Output; fn callback

(self, base: P) -> Self::Output where P: IndexedProducer + 'a, { self.base.callback(EnumerateProducer { base, offset: 0 }) } } /* EnumerateProducer */ struct EnumerateProducer

{ base: P, offset: usize, } impl

WithSetup for EnumerateProducer

where P: WithSetup, { fn setup(&self) -> Setup { self.base.setup() } } impl

Producer for EnumerateProducer

where P: IndexedProducer, { type Item = (usize, P::Item); type IntoIter = Zip, P::IntoIter>; fn into_iter(self) -> Self::IntoIter { let base = self.base.into_iter(); let start = self.offset; let end = start + base.len(); (start..end).zip(base) } fn split(self) -> (Self, Option) { let len = self.base.len(); if len < 2 { return (self, None); } let (left, right) = self.split_at(len / 2); (left, Some(right)) } } impl

IndexedProducer for EnumerateProducer

where P: IndexedProducer, { type Item = (usize, P::Item); type IntoIter = Zip, P::IntoIter>; fn into_iter(self) -> Self::IntoIter { let base = self.base.into_iter(); let start = self.offset; let end = start + base.len(); (start..end).zip(base) } fn len(&self) -> usize { self.base.len() } fn split_at(self, index: usize) -> (Self, Self) { let (left, right) = self.base.split_at(index); let left = Self { base: left, offset: self.offset, }; let right = Self { base: right, offset: self.offset + index, }; (left, right) } }