|
1 | 1 | use crate::fmt;
|
2 | 2 | use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen};
|
3 |
| -use crate::ops::Try; |
| 3 | +use crate::ops::{ControlFlow, Try}; |
4 | 4 |
|
5 | 5 | /// An iterator that maps each element to an iterator, and yields the elements
|
6 | 6 | /// of the produced iterators.
|
|
73 | 73 | {
|
74 | 74 | self.inner.fold(init, fold)
|
75 | 75 | }
|
| 76 | + |
| 77 | + #[inline] |
| 78 | + fn advance_by(&mut self, n: usize) -> Result<(), usize> { |
| 79 | + self.inner.advance_by(n) |
| 80 | + } |
76 | 81 | }
|
77 | 82 |
|
78 | 83 | #[stable(feature = "rust1", since = "1.0.0")]
|
@@ -214,6 +219,11 @@ where
|
214 | 219 | {
|
215 | 220 | self.inner.fold(init, fold)
|
216 | 221 | }
|
| 222 | + |
| 223 | + #[inline] |
| 224 | + fn advance_by(&mut self, n: usize) -> Result<(), usize> { |
| 225 | + self.inner.advance_by(n) |
| 226 | + } |
217 | 227 | }
|
218 | 228 |
|
219 | 229 | #[stable(feature = "iterator_flatten", since = "1.29.0")]
|
@@ -280,6 +290,46 @@ where
|
280 | 290 | }
|
281 | 291 | }
|
282 | 292 |
|
| 293 | +impl<I, U> FlattenCompat<I, U> |
| 294 | +where |
| 295 | + I: Iterator<Item: IntoIterator<IntoIter = U>>, |
| 296 | +{ |
| 297 | + /// Folds over the inner iterators as long as the given function returns successfully, |
| 298 | + /// always storing the most recent inner iterator in `self.frontiter`. |
| 299 | + /// |
| 300 | + /// Folds over the inner iterators, not over their elements. Is used by the `try_fold` and |
| 301 | + /// `advance_by` methods. |
| 302 | + #[inline] |
| 303 | + fn iter_try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, mut fold: Fold) -> R |
| 304 | + where |
| 305 | + Fold: FnMut(Acc, &mut U) -> R, |
| 306 | + R: Try<Output = Acc>, |
| 307 | + { |
| 308 | + #[inline] |
| 309 | + fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>( |
| 310 | + frontiter: &'a mut Option<T::IntoIter>, |
| 311 | + fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R, |
| 312 | + ) -> impl FnMut(Acc, T) -> R + 'a { |
| 313 | + move |acc, iter| fold(acc, frontiter.insert(iter.into_iter())) |
| 314 | + } |
| 315 | + |
| 316 | + if let Some(iter) = &mut self.frontiter { |
| 317 | + acc = fold(acc, iter)?; |
| 318 | + } |
| 319 | + self.frontiter = None; |
| 320 | + |
| 321 | + acc = self.iter.try_fold(acc, flatten(&mut self.frontiter, &mut fold))?; |
| 322 | + self.frontiter = None; |
| 323 | + |
| 324 | + if let Some(iter) = &mut self.backiter { |
| 325 | + acc = fold(acc, iter)?; |
| 326 | + } |
| 327 | + self.backiter = None; |
| 328 | + |
| 329 | + try { acc } |
| 330 | + } |
| 331 | +} |
| 332 | + |
283 | 333 | impl<I, U> Iterator for FlattenCompat<I, U>
|
284 | 334 | where
|
285 | 335 | I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
|
@@ -323,39 +373,20 @@ where
|
323 | 373 | }
|
324 | 374 |
|
325 | 375 | #[inline]
|
326 |
| - fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R |
| 376 | + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R |
327 | 377 | where
|
328 | 378 | Self: Sized,
|
329 | 379 | Fold: FnMut(Acc, Self::Item) -> R,
|
330 | 380 | R: Try<Output = Acc>,
|
331 | 381 | {
|
332 | 382 | #[inline]
|
333 |
| - fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>( |
334 |
| - frontiter: &'a mut Option<T::IntoIter>, |
335 |
| - fold: &'a mut impl FnMut(Acc, T::Item) -> R, |
336 |
| - ) -> impl FnMut(Acc, T) -> R + 'a { |
337 |
| - move |acc, x| { |
338 |
| - let mut mid = x.into_iter(); |
339 |
| - let r = mid.try_fold(acc, &mut *fold); |
340 |
| - *frontiter = Some(mid); |
341 |
| - r |
342 |
| - } |
343 |
| - } |
344 |
| - |
345 |
| - if let Some(ref mut front) = self.frontiter { |
346 |
| - init = front.try_fold(init, &mut fold)?; |
| 383 | + fn flatten<U: Iterator, Acc, R: Try<Output = Acc>>( |
| 384 | + mut fold: impl FnMut(Acc, U::Item) -> R, |
| 385 | + ) -> impl FnMut(Acc, &mut U) -> R { |
| 386 | + move |acc, iter| iter.try_fold(acc, &mut fold) |
347 | 387 | }
|
348 |
| - self.frontiter = None; |
349 |
| - |
350 |
| - init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?; |
351 |
| - self.frontiter = None; |
352 | 388 |
|
353 |
| - if let Some(ref mut back) = self.backiter { |
354 |
| - init = back.try_fold(init, &mut fold)?; |
355 |
| - } |
356 |
| - self.backiter = None; |
357 |
| - |
358 |
| - try { init } |
| 389 | + self.iter_try_fold(init, flatten(fold)) |
359 | 390 | }
|
360 | 391 |
|
361 | 392 | #[inline]
|
@@ -386,36 +417,19 @@ where
|
386 | 417 | #[inline]
|
387 | 418 | #[rustc_inherit_overflow_checks]
|
388 | 419 | fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
389 |
| - let mut rem = n; |
390 |
| - loop { |
391 |
| - if let Some(ref mut front) = self.frontiter { |
392 |
| - match front.advance_by(rem) { |
393 |
| - ret @ Ok(_) => return ret, |
394 |
| - Err(advanced) => rem -= advanced, |
395 |
| - } |
396 |
| - } |
397 |
| - self.frontiter = match self.iter.next() { |
398 |
| - Some(iterable) => Some(iterable.into_iter()), |
399 |
| - _ => break, |
400 |
| - } |
401 |
| - } |
402 |
| - |
403 |
| - self.frontiter = None; |
404 |
| - |
405 |
| - if let Some(ref mut back) = self.backiter { |
406 |
| - match back.advance_by(rem) { |
407 |
| - ret @ Ok(_) => return ret, |
408 |
| - Err(advanced) => rem -= advanced, |
| 420 | + #[inline] |
| 421 | + #[rustc_inherit_overflow_checks] |
| 422 | + fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> { |
| 423 | + match iter.advance_by(n) { |
| 424 | + Ok(()) => ControlFlow::BREAK, |
| 425 | + Err(advanced) => ControlFlow::Continue(n - advanced), |
409 | 426 | }
|
410 | 427 | }
|
411 | 428 |
|
412 |
| - if rem > 0 { |
413 |
| - return Err(n - rem); |
| 429 | + match self.iter_try_fold(n, advance) { |
| 430 | + ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining), |
| 431 | + _ => Ok(()), |
414 | 432 | }
|
415 |
| - |
416 |
| - self.backiter = None; |
417 |
| - |
418 |
| - Ok(()) |
419 | 433 | }
|
420 | 434 | }
|
421 | 435 |
|
|
0 commit comments