use super::plumbing::*; use super::*; /// `FlattenIter` turns each element to a serial iterator, then flattens these iterators /// together. This struct is created by the [`flatten_iter()`] method on [`ParallelIterator`]. /// /// [`flatten_iter()`]: trait.ParallelIterator.html#method.flatten_iter /// [`ParallelIterator`]: trait.ParallelIterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Debug, Clone)] pub struct FlattenIter { base: I, } impl FlattenIter where I: ParallelIterator, I::Item: IntoIterator, ::Item: Send, { /// Creates a new `FlattenIter` iterator. pub(super) fn new(base: I) -> Self { FlattenIter { base } } } impl ParallelIterator for FlattenIter where I: ParallelIterator, I::Item: IntoIterator, ::Item: Send, { type Item = ::Item; fn drive_unindexed(self, consumer: C) -> C::Result where C: UnindexedConsumer, { let consumer = FlattenIterConsumer::new(consumer); self.base.drive_unindexed(consumer) } } /// //////////////////////////////////////////////////////////////////////// /// Consumer implementation struct FlattenIterConsumer { base: C, } impl FlattenIterConsumer { fn new(base: C) -> Self { FlattenIterConsumer { base } } } impl Consumer for FlattenIterConsumer where C: UnindexedConsumer, T: IntoIterator, { type Folder = FlattenIterFolder; type Reducer = C::Reducer; type Result = C::Result; fn split_at(self, index: usize) -> (Self, Self, C::Reducer) { let (left, right, reducer) = self.base.split_at(index); ( FlattenIterConsumer::new(left), FlattenIterConsumer::new(right), reducer, ) } fn into_folder(self) -> Self::Folder { FlattenIterFolder { base: self.base.into_folder(), } } fn full(&self) -> bool { self.base.full() } } impl UnindexedConsumer for FlattenIterConsumer where C: UnindexedConsumer, T: IntoIterator, { fn split_off_left(&self) -> Self { FlattenIterConsumer::new(self.base.split_off_left()) } fn to_reducer(&self) -> Self::Reducer { self.base.to_reducer() } } struct FlattenIterFolder { base: C, } impl Folder for FlattenIterFolder where C: Folder, T: IntoIterator, { type Result = C::Result; fn consume(self, item: T) -> Self { let base = self.base.consume_iter(item); FlattenIterFolder { base } } fn consume_iter(self, iter: I) -> Self where I: IntoIterator, { let iter = iter.into_iter().flatten(); let base = self.base.consume_iter(iter); FlattenIterFolder { base } } fn complete(self) -> Self::Result { self.base.complete() } fn full(&self) -> bool { self.base.full() } }