1 use super::plumbing::*; 2 use super::*; 3 use std::cell::Cell; 4 use std::iter::{self, Fuse}; 5 6 /// `Intersperse` is an iterator that inserts a particular item between each 7 /// item of the adapted iterator. This struct is created by the 8 /// [`intersperse()`] method on [`ParallelIterator`] 9 /// 10 /// [`intersperse()`]: trait.ParallelIterator.html#method.intersperse 11 /// [`ParallelIterator`]: trait.ParallelIterator.html 12 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] 13 #[derive(Clone, Debug)] 14 pub struct Intersperse<I> 15 where 16 I: ParallelIterator, 17 I::Item: Clone, 18 { 19 base: I, 20 item: I::Item, 21 } 22 23 impl<I> Intersperse<I> 24 where 25 I: ParallelIterator, 26 I::Item: Clone, 27 { 28 /// Creates a new `Intersperse` iterator new(base: I, item: I::Item) -> Self29 pub(super) fn new(base: I, item: I::Item) -> Self { 30 Intersperse { base, item } 31 } 32 } 33 34 impl<I> ParallelIterator for Intersperse<I> 35 where 36 I: ParallelIterator, 37 I::Item: Clone + Send, 38 { 39 type Item = I::Item; 40 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<I::Item>,41 fn drive_unindexed<C>(self, consumer: C) -> C::Result 42 where 43 C: UnindexedConsumer<I::Item>, 44 { 45 let consumer1 = IntersperseConsumer::new(consumer, self.item); 46 self.base.drive_unindexed(consumer1) 47 } 48 opt_len(&self) -> Option<usize>49 fn opt_len(&self) -> Option<usize> { 50 match self.base.opt_len()? { 51 0 => Some(0), 52 len => len.checked_add(len - 1), 53 } 54 } 55 } 56 57 impl<I> IndexedParallelIterator for Intersperse<I> 58 where 59 I: IndexedParallelIterator, 60 I::Item: Clone + 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 = IntersperseConsumer::new(consumer, self.item); 67 self.base.drive(consumer1) 68 } 69 len(&self) -> usize70 fn len(&self) -> usize { 71 let len = self.base.len(); 72 if len > 0 { 73 len.checked_add(len - 1).expect("overflow") 74 } else { 75 0 76 } 77 } 78 with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,79 fn with_producer<CB>(self, callback: CB) -> CB::Output 80 where 81 CB: ProducerCallback<Self::Item>, 82 { 83 let len = self.len(); 84 return self.base.with_producer(Callback { 85 callback, 86 item: self.item, 87 len, 88 }); 89 90 struct Callback<CB, T> { 91 callback: CB, 92 item: T, 93 len: usize, 94 } 95 96 impl<T, CB> ProducerCallback<T> for Callback<CB, T> 97 where 98 CB: ProducerCallback<T>, 99 T: Clone + Send, 100 { 101 type Output = CB::Output; 102 103 fn callback<P>(self, base: P) -> CB::Output 104 where 105 P: Producer<Item = T>, 106 { 107 let producer = IntersperseProducer::new(base, self.item, self.len); 108 self.callback.callback(producer) 109 } 110 } 111 } 112 } 113 114 struct IntersperseProducer<P> 115 where 116 P: Producer, 117 { 118 base: P, 119 item: P::Item, 120 len: usize, 121 clone_first: bool, 122 } 123 124 impl<P> IntersperseProducer<P> 125 where 126 P: Producer, 127 { new(base: P, item: P::Item, len: usize) -> Self128 fn new(base: P, item: P::Item, len: usize) -> Self { 129 IntersperseProducer { 130 base, 131 item, 132 len, 133 clone_first: false, 134 } 135 } 136 } 137 138 impl<P> Producer for IntersperseProducer<P> 139 where 140 P: Producer, 141 P::Item: Clone + Send, 142 { 143 type Item = P::Item; 144 type IntoIter = IntersperseIter<P::IntoIter>; 145 into_iter(self) -> Self::IntoIter146 fn into_iter(self) -> Self::IntoIter { 147 IntersperseIter { 148 base: self.base.into_iter().fuse(), 149 item: self.item, 150 clone_first: self.len > 0 && self.clone_first, 151 152 // If there's more than one item, then even lengths end the opposite 153 // of how they started with respect to interspersed clones. 154 clone_last: self.len > 1 && ((self.len & 1 == 0) ^ self.clone_first), 155 } 156 } 157 min_len(&self) -> usize158 fn min_len(&self) -> usize { 159 self.base.min_len() 160 } max_len(&self) -> usize161 fn max_len(&self) -> usize { 162 self.base.max_len() 163 } 164 split_at(self, index: usize) -> (Self, Self)165 fn split_at(self, index: usize) -> (Self, Self) { 166 debug_assert!(index <= self.len); 167 168 // The left needs half of the items from the base producer, and the 169 // other half will be our interspersed item. If we're not leading with 170 // a cloned item, then we need to round up the base number of items, 171 // otherwise round down. 172 let base_index = (index + !self.clone_first as usize) / 2; 173 let (left_base, right_base) = self.base.split_at(base_index); 174 175 let left = IntersperseProducer { 176 base: left_base, 177 item: self.item.clone(), 178 len: index, 179 clone_first: self.clone_first, 180 }; 181 182 let right = IntersperseProducer { 183 base: right_base, 184 item: self.item, 185 len: self.len - index, 186 187 // If the index is odd, the right side toggles `clone_first`. 188 clone_first: (index & 1 == 1) ^ self.clone_first, 189 }; 190 191 (left, right) 192 } 193 fold_with<F>(self, folder: F) -> F where F: Folder<Self::Item>,194 fn fold_with<F>(self, folder: F) -> F 195 where 196 F: Folder<Self::Item>, 197 { 198 let folder1 = IntersperseFolder { 199 base: folder, 200 item: self.item, 201 clone_first: self.clone_first, 202 }; 203 self.base.fold_with(folder1).base 204 } 205 } 206 207 struct IntersperseIter<I> 208 where 209 I: Iterator, 210 { 211 base: Fuse<I>, 212 item: I::Item, 213 clone_first: bool, 214 clone_last: bool, 215 } 216 217 impl<I> Iterator for IntersperseIter<I> 218 where 219 I: DoubleEndedIterator + ExactSizeIterator, 220 I::Item: Clone, 221 { 222 type Item = I::Item; 223 next(&mut self) -> Option<Self::Item>224 fn next(&mut self) -> Option<Self::Item> { 225 if self.clone_first { 226 self.clone_first = false; 227 Some(self.item.clone()) 228 } else if let next @ Some(_) = self.base.next() { 229 // If there are any items left, we'll need another clone in front. 230 self.clone_first = self.base.len() != 0; 231 next 232 } else if self.clone_last { 233 self.clone_last = false; 234 Some(self.item.clone()) 235 } else { 236 None 237 } 238 } 239 size_hint(&self) -> (usize, Option<usize>)240 fn size_hint(&self) -> (usize, Option<usize>) { 241 let len = self.len(); 242 (len, Some(len)) 243 } 244 } 245 246 impl<I> DoubleEndedIterator for IntersperseIter<I> 247 where 248 I: DoubleEndedIterator + ExactSizeIterator, 249 I::Item: Clone, 250 { next_back(&mut self) -> Option<Self::Item>251 fn next_back(&mut self) -> Option<Self::Item> { 252 if self.clone_last { 253 self.clone_last = false; 254 Some(self.item.clone()) 255 } else if let next_back @ Some(_) = self.base.next_back() { 256 // If there are any items left, we'll need another clone in back. 257 self.clone_last = self.base.len() != 0; 258 next_back 259 } else if self.clone_first { 260 self.clone_first = false; 261 Some(self.item.clone()) 262 } else { 263 None 264 } 265 } 266 } 267 268 impl<I> ExactSizeIterator for IntersperseIter<I> 269 where 270 I: DoubleEndedIterator + ExactSizeIterator, 271 I::Item: Clone, 272 { len(&self) -> usize273 fn len(&self) -> usize { 274 let len = self.base.len(); 275 len + len.saturating_sub(1) + self.clone_first as usize + self.clone_last as usize 276 } 277 } 278 279 struct IntersperseConsumer<C, T> { 280 base: C, 281 item: T, 282 clone_first: Cell<bool>, 283 } 284 285 impl<C, T> IntersperseConsumer<C, T> 286 where 287 C: Consumer<T>, 288 { new(base: C, item: T) -> Self289 fn new(base: C, item: T) -> Self { 290 IntersperseConsumer { 291 base, 292 item, 293 clone_first: false.into(), 294 } 295 } 296 } 297 298 impl<C, T> Consumer<T> for IntersperseConsumer<C, T> 299 where 300 C: Consumer<T>, 301 T: Clone + Send, 302 { 303 type Folder = IntersperseFolder<C::Folder, T>; 304 type Reducer = C::Reducer; 305 type Result = C::Result; 306 split_at(mut self, index: usize) -> (Self, Self, Self::Reducer)307 fn split_at(mut self, index: usize) -> (Self, Self, Self::Reducer) { 308 // We'll feed twice as many items to the base consumer, except if we're 309 // not currently leading with a cloned item, then it's one less. 310 let base_index = index + index.saturating_sub(!self.clone_first.get() as usize); 311 let (left, right, reducer) = self.base.split_at(base_index); 312 313 let right = IntersperseConsumer { 314 base: right, 315 item: self.item.clone(), 316 clone_first: true.into(), 317 }; 318 self.base = left; 319 (self, right, reducer) 320 } 321 into_folder(self) -> Self::Folder322 fn into_folder(self) -> Self::Folder { 323 IntersperseFolder { 324 base: self.base.into_folder(), 325 item: self.item, 326 clone_first: self.clone_first.get(), 327 } 328 } 329 full(&self) -> bool330 fn full(&self) -> bool { 331 self.base.full() 332 } 333 } 334 335 impl<C, T> UnindexedConsumer<T> for IntersperseConsumer<C, T> 336 where 337 C: UnindexedConsumer<T>, 338 T: Clone + Send, 339 { split_off_left(&self) -> Self340 fn split_off_left(&self) -> Self { 341 let left = IntersperseConsumer { 342 base: self.base.split_off_left(), 343 item: self.item.clone(), 344 clone_first: self.clone_first.clone(), 345 }; 346 self.clone_first.set(true); 347 left 348 } 349 to_reducer(&self) -> Self::Reducer350 fn to_reducer(&self) -> Self::Reducer { 351 self.base.to_reducer() 352 } 353 } 354 355 struct IntersperseFolder<C, T> { 356 base: C, 357 item: T, 358 clone_first: bool, 359 } 360 361 impl<C, T> Folder<T> for IntersperseFolder<C, T> 362 where 363 C: Folder<T>, 364 T: Clone, 365 { 366 type Result = C::Result; 367 consume(mut self, item: T) -> Self368 fn consume(mut self, item: T) -> Self { 369 if self.clone_first { 370 self.base = self.base.consume(self.item.clone()); 371 if self.base.full() { 372 return self; 373 } 374 } else { 375 self.clone_first = true; 376 } 377 self.base = self.base.consume(item); 378 self 379 } 380 consume_iter<I>(self, iter: I) -> Self where I: IntoIterator<Item = T>,381 fn consume_iter<I>(self, iter: I) -> Self 382 where 383 I: IntoIterator<Item = T>, 384 { 385 let mut clone_first = self.clone_first; 386 let between_item = self.item; 387 let base = self.base.consume_iter(iter.into_iter().flat_map(|item| { 388 let first = if clone_first { 389 Some(between_item.clone()) 390 } else { 391 clone_first = true; 392 None 393 }; 394 first.into_iter().chain(iter::once(item)) 395 })); 396 IntersperseFolder { 397 base, 398 item: between_item, 399 clone_first, 400 } 401 } 402 complete(self) -> C::Result403 fn complete(self) -> C::Result { 404 self.base.complete() 405 } 406 full(&self) -> bool407 fn full(&self) -> bool { 408 self.base.full() 409 } 410 } 411