| 1 | use super::plumbing::*; | 
| 2 | use super::*; | 
| 3 |  | 
| 4 | use std::fmt::{self, Debug}; | 
| 5 |  | 
| 6 | /// `FlatMapIter` maps each element to a serial iterator, then flattens these iterators together. | 
| 7 | /// This struct is created by the [`flat_map_iter()`] method on [`ParallelIterator`] | 
| 8 | /// | 
| 9 | /// [`flat_map_iter()`]: trait.ParallelIterator.html#method.flat_map_iter | 
| 10 | /// [`ParallelIterator`]: trait.ParallelIterator.html | 
| 11 | #[must_use  = "iterator adaptors are lazy and do nothing unless consumed" ] | 
| 12 | #[derive (Clone)] | 
| 13 | pub struct FlatMapIter<I: ParallelIterator, F> { | 
| 14 |     base: I, | 
| 15 |     map_op: F, | 
| 16 | } | 
| 17 |  | 
| 18 | impl<I: ParallelIterator + Debug, F> Debug for FlatMapIter<I, F> { | 
| 19 |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
| 20 |         f&mut DebugStruct<'_, '_>.debug_struct("FlatMapIter" ) | 
| 21 |             .field(name:"base" , &self.base) | 
| 22 |             .finish() | 
| 23 |     } | 
| 24 | } | 
| 25 |  | 
| 26 | impl<I: ParallelIterator, F> FlatMapIter<I, F> { | 
| 27 |     /// Creates a new `FlatMapIter` iterator. | 
| 28 |     pub(super) fn new(base: I, map_op: F) -> Self { | 
| 29 |         FlatMapIter { base, map_op } | 
| 30 |     } | 
| 31 | } | 
| 32 |  | 
| 33 | impl<I, F, SI> ParallelIterator for FlatMapIter<I, F> | 
| 34 | where | 
| 35 |     I: ParallelIterator, | 
| 36 |     F: Fn(I::Item) -> SI + Sync + Send, | 
| 37 |     SI: IntoIterator, | 
| 38 |     SI::Item: Send, | 
| 39 | { | 
| 40 |     type Item = SI::Item; | 
| 41 |  | 
| 42 |     fn drive_unindexed<C>(self, consumer: C) -> C::Result | 
| 43 |     where | 
| 44 |         C: UnindexedConsumer<Self::Item>, | 
| 45 |     { | 
| 46 |         let consumer: FlatMapIterConsumer<'_, C, …> = FlatMapIterConsumer::new(base:consumer, &self.map_op); | 
| 47 |         self.base.drive_unindexed(consumer) | 
| 48 |     } | 
| 49 | } | 
| 50 |  | 
| 51 | /// //////////////////////////////////////////////////////////////////////// | 
| 52 | /// Consumer implementation | 
| 53 |  | 
| 54 | struct FlatMapIterConsumer<'f, C, F> { | 
| 55 |     base: C, | 
| 56 |     map_op: &'f F, | 
| 57 | } | 
| 58 |  | 
| 59 | impl<'f, C, F> FlatMapIterConsumer<'f, C, F> { | 
| 60 |     fn new(base: C, map_op: &'f F) -> Self { | 
| 61 |         FlatMapIterConsumer { base, map_op } | 
| 62 |     } | 
| 63 | } | 
| 64 |  | 
| 65 | impl<'f, T, U, C, F> Consumer<T> for FlatMapIterConsumer<'f, C, F> | 
| 66 | where | 
| 67 |     C: UnindexedConsumer<U::Item>, | 
| 68 |     F: Fn(T) -> U + Sync, | 
| 69 |     U: IntoIterator, | 
| 70 | { | 
| 71 |     type Folder = FlatMapIterFolder<'f, C::Folder, F>; | 
| 72 |     type Reducer = C::Reducer; | 
| 73 |     type Result = C::Result; | 
| 74 |  | 
| 75 |     fn split_at(self, index: usize) -> (Self, Self, C::Reducer) { | 
| 76 |         let (left, right, reducer) = self.base.split_at(index); | 
| 77 |         ( | 
| 78 |             FlatMapIterConsumer::new(left, self.map_op), | 
| 79 |             FlatMapIterConsumer::new(right, self.map_op), | 
| 80 |             reducer, | 
| 81 |         ) | 
| 82 |     } | 
| 83 |  | 
| 84 |     fn into_folder(self) -> Self::Folder { | 
| 85 |         FlatMapIterFolder { | 
| 86 |             base: self.base.into_folder(), | 
| 87 |             map_op: self.map_op, | 
| 88 |         } | 
| 89 |     } | 
| 90 |  | 
| 91 |     fn full(&self) -> bool { | 
| 92 |         self.base.full() | 
| 93 |     } | 
| 94 | } | 
| 95 |  | 
| 96 | impl<'f, T, U, C, F> UnindexedConsumer<T> for FlatMapIterConsumer<'f, C, F> | 
| 97 | where | 
| 98 |     C: UnindexedConsumer<U::Item>, | 
| 99 |     F: Fn(T) -> U + Sync, | 
| 100 |     U: IntoIterator, | 
| 101 | { | 
| 102 |     fn split_off_left(&self) -> Self { | 
| 103 |         FlatMapIterConsumer::new(self.base.split_off_left(), self.map_op) | 
| 104 |     } | 
| 105 |  | 
| 106 |     fn to_reducer(&self) -> Self::Reducer { | 
| 107 |         self.base.to_reducer() | 
| 108 |     } | 
| 109 | } | 
| 110 |  | 
| 111 | struct FlatMapIterFolder<'f, C, F> { | 
| 112 |     base: C, | 
| 113 |     map_op: &'f F, | 
| 114 | } | 
| 115 |  | 
| 116 | impl<'f, T, U, C, F> Folder<T> for FlatMapIterFolder<'f, C, F> | 
| 117 | where | 
| 118 |     C: Folder<U::Item>, | 
| 119 |     F: Fn(T) -> U, | 
| 120 |     U: IntoIterator, | 
| 121 | { | 
| 122 |     type Result = C::Result; | 
| 123 |  | 
| 124 |     fn consume(self, item: T) -> Self { | 
| 125 |         let map_op = self.map_op; | 
| 126 |         let base = self.base.consume_iter(map_op(item)); | 
| 127 |         FlatMapIterFolder { base, map_op } | 
| 128 |     } | 
| 129 |  | 
| 130 |     fn consume_iter<I>(self, iter: I) -> Self | 
| 131 |     where | 
| 132 |         I: IntoIterator<Item = T>, | 
| 133 |     { | 
| 134 |         let map_op = self.map_op; | 
| 135 |         let iter = iter.into_iter().flat_map(map_op); | 
| 136 |         let base = self.base.consume_iter(iter); | 
| 137 |         FlatMapIterFolder { base, map_op } | 
| 138 |     } | 
| 139 |  | 
| 140 |     fn complete(self) -> Self::Result { | 
| 141 |         self.base.complete() | 
| 142 |     } | 
| 143 |  | 
| 144 |     fn full(&self) -> bool { | 
| 145 |         self.base.full() | 
| 146 |     } | 
| 147 | } | 
| 148 |  |