1 use super::plumbing
::*;
4 use std
::fmt
::{self, Debug}
;
6 /// `FlatMap` maps each element to an iterator, then flattens these iterators together.
7 /// This struct is created by the [`flat_map()`] method on [`ParallelIterator`]
9 /// [`flat_map()`]: trait.ParallelIterator.html#method.flat_map
10 /// [`ParallelIterator`]: trait.ParallelIterator.html
11 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
13 pub struct FlatMap
<I
: ParallelIterator
, F
> {
18 impl<I
: ParallelIterator
+ Debug
, F
> Debug
for FlatMap
<I
, F
> {
19 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
20 f
.debug_struct("FlatMap").field("base", &self.base
).finish()
24 impl<I
: ParallelIterator
, F
> FlatMap
<I
, F
> {
25 /// Create a new `FlatMap` iterator.
26 pub(super) fn new(base
: I
, map_op
: F
) -> Self {
27 FlatMap { base, map_op }
31 impl<I
, F
, PI
> ParallelIterator
for FlatMap
<I
, F
>
34 F
: Fn(I
::Item
) -> PI
+ Sync
+ Send
,
35 PI
: IntoParallelIterator
,
39 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
41 C
: UnindexedConsumer
<Self::Item
>,
43 let consumer
= FlatMapConsumer
{
47 self.base
.drive_unindexed(consumer
)
51 /// ////////////////////////////////////////////////////////////////////////
52 /// Consumer implementation
54 struct FlatMapConsumer
<'f
, C
, F
> {
59 impl<'f
, C
, F
> FlatMapConsumer
<'f
, C
, F
> {
60 fn new(base
: C
, map_op
: &'f F
) -> Self {
61 FlatMapConsumer { base, map_op }
65 impl<'f
, T
, U
, C
, F
> Consumer
<T
> for FlatMapConsumer
<'f
, C
, F
>
67 C
: UnindexedConsumer
<U
::Item
>,
69 U
: IntoParallelIterator
,
71 type Folder
= FlatMapFolder
<'f
, C
, F
, C
::Result
>;
72 type Reducer
= C
::Reducer
;
73 type Result
= C
::Result
;
75 fn split_at(self, index
: usize) -> (Self, Self, C
::Reducer
) {
76 let (left
, right
, reducer
) = self.base
.split_at(index
);
78 FlatMapConsumer
::new(left
, self.map_op
),
79 FlatMapConsumer
::new(right
, self.map_op
),
84 fn into_folder(self) -> Self::Folder
{
92 fn full(&self) -> bool
{
97 impl<'f
, T
, U
, C
, F
> UnindexedConsumer
<T
> for FlatMapConsumer
<'f
, C
, F
>
99 C
: UnindexedConsumer
<U
::Item
>,
100 F
: Fn(T
) -> U
+ Sync
,
101 U
: IntoParallelIterator
,
103 fn split_off_left(&self) -> Self {
104 FlatMapConsumer
::new(self.base
.split_off_left(), self.map_op
)
107 fn to_reducer(&self) -> Self::Reducer
{
108 self.base
.to_reducer()
112 struct FlatMapFolder
<'f
, C
, F
, R
> {
118 impl<'f
, T
, U
, C
, F
> Folder
<T
> for FlatMapFolder
<'f
, C
, F
, C
::Result
>
120 C
: UnindexedConsumer
<U
::Item
>,
121 F
: Fn(T
) -> U
+ Sync
,
122 U
: IntoParallelIterator
,
124 type Result
= C
::Result
;
126 fn consume(self, item
: T
) -> Self {
127 let map_op
= self.map_op
;
128 let par_iter
= map_op(item
).into_par_iter();
129 let result
= par_iter
.drive_unindexed(self.base
.split_off_left());
131 // We expect that `previous` is `None`, because we drive
132 // the cost up so high, but just in case.
133 let previous
= match self.previous
{
134 None
=> Some(result
),
136 let reducer
= self.base
.to_reducer();
137 Some(reducer
.reduce(previous
, result
))
148 fn complete(self) -> Self::Result
{
149 match self.previous
{
150 Some(previous
) => previous
,
151 None
=> self.base
.into_folder().complete(),
155 fn full(&self) -> bool
{