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> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 23 f.debug_struct("Inspect").field("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. new(base: I, inspect_op: F) -> Self32 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 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,44 fn drive_unindexed<C>(self, consumer: C) -> C::Result 45 where 46 C: UnindexedConsumer<Self::Item>, 47 { 48 let consumer1 = InspectConsumer::new(consumer, &self.inspect_op); 49 self.base.drive_unindexed(consumer1) 50 } 51 opt_len(&self) -> Option<usize>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 { drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,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 len(&self) -> usize70 fn len(&self) -> usize { 71 self.base.len() 72 } 73 with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,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 into_iter(self) -> Self::IntoIter124 fn into_iter(self) -> Self::IntoIter { 125 self.base.into_iter().inspect(self.inspect_op) 126 } 127 min_len(&self) -> usize128 fn min_len(&self) -> usize { 129 self.base.min_len() 130 } 131 max_len(&self) -> usize132 fn max_len(&self) -> usize { 133 self.base.max_len() 134 } 135 split_at(self, index: usize) -> (Self, Self)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 fold_with<G>(self, folder: G) -> G where G: Folder<Self::Item>,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> { new(base: C, inspect_op: &'f F) -> Self171 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 split_at(self, index: usize) -> (Self, Self, Self::Reducer)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 into_folder(self) -> Self::Folder194 fn into_folder(self) -> Self::Folder { 195 InspectFolder { 196 base: self.base.into_folder(), 197 inspect_op: self.inspect_op, 198 } 199 } 200 full(&self) -> bool201 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 { split_off_left(&self) -> Self211 fn split_off_left(&self) -> Self { 212 InspectConsumer::new(self.base.split_off_left(), &self.inspect_op) 213 } 214 to_reducer(&self) -> Self::Reducer215 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 consume(self, item: T) -> Self232 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 consume_iter<I>(mut self, iter: I) -> Self where I: IntoIterator<Item = T>,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 complete(self) -> C::Result250 fn complete(self) -> C::Result { 251 self.base.complete() 252 } 253 full(&self) -> bool254 fn full(&self) -> bool { 255 self.base.full() 256 } 257 } 258