| 1 | use super::plumbing::*; | 
| 2 | use super::*; | 
| 3 |  | 
| 4 | use std::fmt::{self, Debug}; | 
| 5 | use std::iter; | 
| 6 |  | 
| 7 | /// `Inspect` is an iterator that calls a function with a reference to each | 
| 8 | /// element before yielding it. | 
| 9 | /// | 
| 10 | /// This struct is created by the [`inspect()`] method on [`ParallelIterator`] | 
| 11 | /// | 
| 12 | /// [`inspect()`]: trait.ParallelIterator.html#method.inspect | 
| 13 | /// [`ParallelIterator`]: trait.ParallelIterator.html | 
| 14 | #[must_use  = "iterator adaptors are lazy and do nothing unless consumed" ] | 
| 15 | #[derive (Clone)] | 
| 16 | pub struct Inspect<I: ParallelIterator, F> { | 
| 17 |     base: I, | 
| 18 |     inspect_op: F, | 
| 19 | } | 
| 20 |  | 
| 21 | impl<I: ParallelIterator + Debug, F> Debug for Inspect<I, F> { | 
| 22 |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
| 23 |         f.debug_struct("Inspect" ).field(name:"base" , &self.base).finish() | 
| 24 |     } | 
| 25 | } | 
| 26 |  | 
| 27 | impl<I, F> Inspect<I, F> | 
| 28 | where | 
| 29 |     I: ParallelIterator, | 
| 30 | { | 
| 31 |     /// Creates a new `Inspect` iterator. | 
| 32 |     pub(super) fn new(base: I, inspect_op: F) -> Self { | 
| 33 |         Inspect { base, inspect_op } | 
| 34 |     } | 
| 35 | } | 
| 36 |  | 
| 37 | impl<I, F> ParallelIterator for Inspect<I, F> | 
| 38 | where | 
| 39 |     I: ParallelIterator, | 
| 40 |     F: Fn(&I::Item) + Sync + Send, | 
| 41 | { | 
| 42 |     type Item = I::Item; | 
| 43 |  | 
| 44 |     fn drive_unindexed<C>(self, consumer: C) -> C::Result | 
| 45 |     where | 
| 46 |         C: UnindexedConsumer<Self::Item>, | 
| 47 |     { | 
| 48 |         let consumer1: InspectConsumer<'_, C, F> = InspectConsumer::new(base:consumer, &self.inspect_op); | 
| 49 |         self.base.drive_unindexed(consumer:consumer1) | 
| 50 |     } | 
| 51 |  | 
| 52 |     fn opt_len(&self) -> Option<usize> { | 
| 53 |         self.base.opt_len() | 
| 54 |     } | 
| 55 | } | 
| 56 |  | 
| 57 | impl<I, F> IndexedParallelIterator for Inspect<I, F> | 
| 58 | where | 
| 59 |     I: IndexedParallelIterator, | 
| 60 |     F: Fn(&I::Item) + Sync + Send, | 
| 61 | { | 
| 62 |     fn drive<C>(self, consumer: C) -> C::Result | 
| 63 |     where | 
| 64 |         C: Consumer<Self::Item>, | 
| 65 |     { | 
| 66 |         let consumer1 = InspectConsumer::new(consumer, &self.inspect_op); | 
| 67 |         self.base.drive(consumer1) | 
| 68 |     } | 
| 69 |  | 
| 70 |     fn len(&self) -> usize { | 
| 71 |         self.base.len() | 
| 72 |     } | 
| 73 |  | 
| 74 |     fn with_producer<CB>(self, callback: CB) -> CB::Output | 
| 75 |     where | 
| 76 |         CB: ProducerCallback<Self::Item>, | 
| 77 |     { | 
| 78 |         return self.base.with_producer(Callback { | 
| 79 |             callback, | 
| 80 |             inspect_op: self.inspect_op, | 
| 81 |         }); | 
| 82 |  | 
| 83 |         struct Callback<CB, F> { | 
| 84 |             callback: CB, | 
| 85 |             inspect_op: F, | 
| 86 |         } | 
| 87 |  | 
| 88 |         impl<T, F, CB> ProducerCallback<T> for Callback<CB, F> | 
| 89 |         where | 
| 90 |             CB: ProducerCallback<T>, | 
| 91 |             F: Fn(&T) + Sync, | 
| 92 |         { | 
| 93 |             type Output = CB::Output; | 
| 94 |  | 
| 95 |             fn callback<P>(self, base: P) -> CB::Output | 
| 96 |             where | 
| 97 |                 P: Producer<Item = T>, | 
| 98 |             { | 
| 99 |                 let producer = InspectProducer { | 
| 100 |                     base, | 
| 101 |                     inspect_op: &self.inspect_op, | 
| 102 |                 }; | 
| 103 |                 self.callback.callback(producer) | 
| 104 |             } | 
| 105 |         } | 
| 106 |     } | 
| 107 | } | 
| 108 |  | 
| 109 | /// //////////////////////////////////////////////////////////////////////// | 
| 110 |  | 
| 111 | struct InspectProducer<'f, P, F> { | 
| 112 |     base: P, | 
| 113 |     inspect_op: &'f F, | 
| 114 | } | 
| 115 |  | 
| 116 | impl<'f, P, F> Producer for InspectProducer<'f, P, F> | 
| 117 | where | 
| 118 |     P: Producer, | 
| 119 |     F: Fn(&P::Item) + Sync, | 
| 120 | { | 
| 121 |     type Item = P::Item; | 
| 122 |     type IntoIter = iter::Inspect<P::IntoIter, &'f F>; | 
| 123 |  | 
| 124 |     fn into_iter(self) -> Self::IntoIter { | 
| 125 |         self.base.into_iter().inspect(self.inspect_op) | 
| 126 |     } | 
| 127 |  | 
| 128 |     fn min_len(&self) -> usize { | 
| 129 |         self.base.min_len() | 
| 130 |     } | 
| 131 |  | 
| 132 |     fn max_len(&self) -> usize { | 
| 133 |         self.base.max_len() | 
| 134 |     } | 
| 135 |  | 
| 136 |     fn split_at(self, index: usize) -> (Self, Self) { | 
| 137 |         let (left, right) = self.base.split_at(index); | 
| 138 |         ( | 
| 139 |             InspectProducer { | 
| 140 |                 base: left, | 
| 141 |                 inspect_op: self.inspect_op, | 
| 142 |             }, | 
| 143 |             InspectProducer { | 
| 144 |                 base: right, | 
| 145 |                 inspect_op: self.inspect_op, | 
| 146 |             }, | 
| 147 |         ) | 
| 148 |     } | 
| 149 |  | 
| 150 |     fn fold_with<G>(self, folder: G) -> G | 
| 151 |     where | 
| 152 |         G: Folder<Self::Item>, | 
| 153 |     { | 
| 154 |         let folder1 = InspectFolder { | 
| 155 |             base: folder, | 
| 156 |             inspect_op: self.inspect_op, | 
| 157 |         }; | 
| 158 |         self.base.fold_with(folder1).base | 
| 159 |     } | 
| 160 | } | 
| 161 |  | 
| 162 | /// //////////////////////////////////////////////////////////////////////// | 
| 163 | /// Consumer implementation | 
| 164 |  | 
| 165 | struct InspectConsumer<'f, C, F> { | 
| 166 |     base: C, | 
| 167 |     inspect_op: &'f F, | 
| 168 | } | 
| 169 |  | 
| 170 | impl<'f, C, F> InspectConsumer<'f, C, F> { | 
| 171 |     fn new(base: C, inspect_op: &'f F) -> Self { | 
| 172 |         InspectConsumer { base, inspect_op } | 
| 173 |     } | 
| 174 | } | 
| 175 |  | 
| 176 | impl<'f, T, C, F> Consumer<T> for InspectConsumer<'f, C, F> | 
| 177 | where | 
| 178 |     C: Consumer<T>, | 
| 179 |     F: Fn(&T) + Sync, | 
| 180 | { | 
| 181 |     type Folder = InspectFolder<'f, C::Folder, F>; | 
| 182 |     type Reducer = C::Reducer; | 
| 183 |     type Result = C::Result; | 
| 184 |  | 
| 185 |     fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) { | 
| 186 |         let (left, right, reducer) = self.base.split_at(index); | 
| 187 |         ( | 
| 188 |             InspectConsumer::new(left, self.inspect_op), | 
| 189 |             InspectConsumer::new(right, self.inspect_op), | 
| 190 |             reducer, | 
| 191 |         ) | 
| 192 |     } | 
| 193 |  | 
| 194 |     fn into_folder(self) -> Self::Folder { | 
| 195 |         InspectFolder { | 
| 196 |             base: self.base.into_folder(), | 
| 197 |             inspect_op: self.inspect_op, | 
| 198 |         } | 
| 199 |     } | 
| 200 |  | 
| 201 |     fn full(&self) -> bool { | 
| 202 |         self.base.full() | 
| 203 |     } | 
| 204 | } | 
| 205 |  | 
| 206 | impl<'f, T, C, F> UnindexedConsumer<T> for InspectConsumer<'f, C, F> | 
| 207 | where | 
| 208 |     C: UnindexedConsumer<T>, | 
| 209 |     F: Fn(&T) + Sync, | 
| 210 | { | 
| 211 |     fn split_off_left(&self) -> Self { | 
| 212 |         InspectConsumer::new(self.base.split_off_left(), self.inspect_op) | 
| 213 |     } | 
| 214 |  | 
| 215 |     fn to_reducer(&self) -> Self::Reducer { | 
| 216 |         self.base.to_reducer() | 
| 217 |     } | 
| 218 | } | 
| 219 |  | 
| 220 | struct InspectFolder<'f, C, F> { | 
| 221 |     base: C, | 
| 222 |     inspect_op: &'f F, | 
| 223 | } | 
| 224 |  | 
| 225 | impl<'f, T, C, F> Folder<T> for InspectFolder<'f, C, F> | 
| 226 | where | 
| 227 |     C: Folder<T>, | 
| 228 |     F: Fn(&T), | 
| 229 | { | 
| 230 |     type Result = C::Result; | 
| 231 |  | 
| 232 |     fn consume(self, item: T) -> Self { | 
| 233 |         (self.inspect_op)(&item); | 
| 234 |         InspectFolder { | 
| 235 |             base: self.base.consume(item), | 
| 236 |             inspect_op: self.inspect_op, | 
| 237 |         } | 
| 238 |     } | 
| 239 |  | 
| 240 |     fn consume_iter<I>(mut self, iter: I) -> Self | 
| 241 |     where | 
| 242 |         I: IntoIterator<Item = T>, | 
| 243 |     { | 
| 244 |         self.base = self | 
| 245 |             .base | 
| 246 |             .consume_iter(iter.into_iter().inspect(self.inspect_op)); | 
| 247 |         self | 
| 248 |     } | 
| 249 |  | 
| 250 |     fn complete(self) -> C::Result { | 
| 251 |         self.base.complete() | 
| 252 |     } | 
| 253 |  | 
| 254 |     fn full(&self) -> bool { | 
| 255 |         self.base.full() | 
| 256 |     } | 
| 257 | } | 
| 258 |  |