Coverage Report

Created: 2025-07-04 06:57

/rust/registry/src/index.crates.io-6f17d22bba15001f/rayon-1.10.0/src/iter/flatten.rs
Line
Count
Source (jump to first uncovered line)
1
use super::plumbing::*;
2
use super::*;
3
4
/// `Flatten` turns each element to a parallel iterator, then flattens these iterators
5
/// together. This struct is created by the [`flatten()`] method on [`ParallelIterator`].
6
///
7
/// [`flatten()`]: trait.ParallelIterator.html#method.flatten
8
/// [`ParallelIterator`]: trait.ParallelIterator.html
9
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
10
#[derive(Debug, Clone)]
11
pub struct Flatten<I: ParallelIterator> {
12
    base: I,
13
}
14
15
impl<I> Flatten<I>
16
where
17
    I: ParallelIterator,
18
    I::Item: IntoParallelIterator,
19
{
20
    /// Creates a new `Flatten` iterator.
21
0
    pub(super) fn new(base: I) -> Self {
22
0
        Flatten { base }
23
0
    }
24
}
25
26
impl<I> ParallelIterator for Flatten<I>
27
where
28
    I: ParallelIterator,
29
    I::Item: IntoParallelIterator,
30
{
31
    type Item = <I::Item as IntoParallelIterator>::Item;
32
33
0
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
34
0
    where
35
0
        C: UnindexedConsumer<Self::Item>,
36
0
    {
37
0
        let consumer = FlattenConsumer::new(consumer);
38
0
        self.base.drive_unindexed(consumer)
39
0
    }
40
}
41
42
/// ////////////////////////////////////////////////////////////////////////
43
/// Consumer implementation
44
45
struct FlattenConsumer<C> {
46
    base: C,
47
}
48
49
impl<C> FlattenConsumer<C> {
50
0
    fn new(base: C) -> Self {
51
0
        FlattenConsumer { base }
52
0
    }
53
}
54
55
impl<T, C> Consumer<T> for FlattenConsumer<C>
56
where
57
    C: UnindexedConsumer<T::Item>,
58
    T: IntoParallelIterator,
59
{
60
    type Folder = FlattenFolder<C, C::Result>;
61
    type Reducer = C::Reducer;
62
    type Result = C::Result;
63
64
0
    fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {
65
0
        let (left, right, reducer) = self.base.split_at(index);
66
0
        (
67
0
            FlattenConsumer::new(left),
68
0
            FlattenConsumer::new(right),
69
0
            reducer,
70
0
        )
71
0
    }
72
73
0
    fn into_folder(self) -> Self::Folder {
74
0
        FlattenFolder {
75
0
            base: self.base,
76
0
            previous: None,
77
0
        }
78
0
    }
79
80
0
    fn full(&self) -> bool {
81
0
        self.base.full()
82
0
    }
83
}
84
85
impl<T, C> UnindexedConsumer<T> for FlattenConsumer<C>
86
where
87
    C: UnindexedConsumer<T::Item>,
88
    T: IntoParallelIterator,
89
{
90
0
    fn split_off_left(&self) -> Self {
91
0
        FlattenConsumer::new(self.base.split_off_left())
92
0
    }
93
94
0
    fn to_reducer(&self) -> Self::Reducer {
95
0
        self.base.to_reducer()
96
0
    }
97
}
98
99
struct FlattenFolder<C, R> {
100
    base: C,
101
    previous: Option<R>,
102
}
103
104
impl<T, C> Folder<T> for FlattenFolder<C, C::Result>
105
where
106
    C: UnindexedConsumer<T::Item>,
107
    T: IntoParallelIterator,
108
{
109
    type Result = C::Result;
110
111
0
    fn consume(self, item: T) -> Self {
112
0
        let par_iter = item.into_par_iter();
113
0
        let consumer = self.base.split_off_left();
114
0
        let result = par_iter.drive_unindexed(consumer);
115
116
0
        let previous = match self.previous {
117
0
            None => Some(result),
118
0
            Some(previous) => {
119
0
                let reducer = self.base.to_reducer();
120
0
                Some(reducer.reduce(previous, result))
121
            }
122
        };
123
124
0
        FlattenFolder {
125
0
            base: self.base,
126
0
            previous,
127
0
        }
128
0
    }
129
130
0
    fn complete(self) -> Self::Result {
131
0
        match self.previous {
132
0
            Some(previous) => previous,
133
0
            None => self.base.into_folder().complete(),
134
        }
135
0
    }
136
137
0
    fn full(&self) -> bool {
138
0
        self.base.full()
139
0
    }
140
}