Skip to main content

moirai_iter/parallel/
split.rs

1use super::ParallelIterator;
2
3/// Sum type used by `ParallelIterator::partition_map`.
4#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
5pub enum Either<L, R> {
6    /// Route the value into the left output collection.
7    Left(L),
8    /// Route the value into the right output collection.
9    Right(R),
10}
11
12pub(in crate::parallel) fn partition_map<I, A, B, P, L, R>(iterator: I, predicate: P) -> (A, B)
13where
14    I: ParallelIterator,
15    A: Default + Extend<L> + Send,
16    B: Default + Extend<R> + Send,
17    P: Fn(I::Item) -> Either<L, R> + Send + Sync + Clone,
18    L: Send,
19    R: Send,
20{
21    // Measured sequential, for the reason recorded on
22    // `ParallelIterator::partition`: a pair-of-vectors accumulator moved
23    // through a fold closure per item, plus an ordered append of the shard
24    // outputs, cost more than the collect it replaced at every input size.
25    // The stream folds rather than collecting, so no intermediate vector of
26    // items is built.
27    let mut left = A::default();
28    let mut right = B::default();
29
30    iterator.seq_fold((), |(), item| match predicate(item) {
31        Either::Left(value) => left.extend(std::iter::once(value)),
32        Either::Right(value) => right.extend(std::iter::once(value)),
33    });
34
35    (left, right)
36}