|
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