@@ -317,6 +317,108 @@ impl<I: Iterator> Peekable<I> {
317
317
{
318
318
self . next_if ( |next| next == expected)
319
319
}
320
+
321
+ /// Consumes the next value of this iterator and applies a function `f` on it,
322
+ /// returning the result if the closure returns `Ok`.
323
+ ///
324
+ /// Otherwise if the closure returns `Err` the value is put back for the next iteration.
325
+ ///
326
+ /// The content of the `Err` variant is typically the original value of the closure,
327
+ /// but this is not required. If a different value is returned,
328
+ /// the next `peek()` or `next()` call will result in this new value.
329
+ /// This is similar to modifying the output of `peek_mut()`.
330
+ ///
331
+ /// If the closure panics, the next value will always be consumed and dropped
332
+ /// even if the panic is caught, because the closure never returned an `Err` value to put back.
333
+ ///
334
+ /// # Examples
335
+ ///
336
+ /// Parse the leading decimal number from an iterator of characters.
337
+ /// ```
338
+ /// #![feature(peekable_next_if_map)]
339
+ /// let mut iter = "125 GOTO 10".chars().peekable();
340
+ /// let mut line_num = 0_u32;
341
+ /// while let Some(digit) = iter.next_if_map(|c| c.to_digit(10).ok_or(c)) {
342
+ /// line_num = line_num * 10 + digit;
343
+ /// }
344
+ /// assert_eq!(line_num, 125);
345
+ /// assert_eq!(iter.collect::<String>(), " GOTO 10");
346
+ /// ```
347
+ ///
348
+ /// Matching custom types.
349
+ /// ```
350
+ /// #![feature(peekable_next_if_map)]
351
+ ///
352
+ /// #[derive(Debug, PartialEq, Eq)]
353
+ /// enum Node {
354
+ /// Comment(String),
355
+ /// Red(String),
356
+ /// Green(String),
357
+ /// Blue(String),
358
+ /// }
359
+ ///
360
+ /// /// Combines all consecutive `Comment` nodes into a single one.
361
+ /// fn combine_comments(nodes: Vec<Node>) -> Vec<Node> {
362
+ /// let mut result = Vec::with_capacity(nodes.len());
363
+ /// let mut iter = nodes.into_iter().peekable();
364
+ /// let mut comment_text = None::<String>;
365
+ /// loop {
366
+ /// // Typically the closure in .next_if_map() matches on the input,
367
+ /// // extracts the desired pattern into an `Ok`,
368
+ /// // and puts the rest into an `Err`.
369
+ /// while let Some(text) = iter.next_if_map(|node| match node {
370
+ /// Node::Comment(text) => Ok(text),
371
+ /// other => Err(other),
372
+ /// }) {
373
+ /// comment_text.get_or_insert_default().push_str(&text);
374
+ /// }
375
+ ///
376
+ /// if let Some(text) = comment_text.take() {
377
+ /// result.push(Node::Comment(text));
378
+ /// }
379
+ /// if let Some(node) = iter.next() {
380
+ /// result.push(node);
381
+ /// } else {
382
+ /// break;
383
+ /// }
384
+ /// }
385
+ /// result
386
+ /// }
387
+ ///# assert_eq!( // hiding the test to avoid cluttering the documentation.
388
+ ///# combine_comments(vec![
389
+ ///# Node::Comment("The".to_owned()),
390
+ ///# Node::Comment("Quick".to_owned()),
391
+ ///# Node::Comment("Brown".to_owned()),
392
+ ///# Node::Red("Fox".to_owned()),
393
+ ///# Node::Green("Jumped".to_owned()),
394
+ ///# Node::Comment("Over".to_owned()),
395
+ ///# Node::Blue("The".to_owned()),
396
+ ///# Node::Comment("Lazy".to_owned()),
397
+ ///# Node::Comment("Dog".to_owned()),
398
+ ///# ]),
399
+ ///# vec![
400
+ ///# Node::Comment("TheQuickBrown".to_owned()),
401
+ ///# Node::Red("Fox".to_owned()),
402
+ ///# Node::Green("Jumped".to_owned()),
403
+ ///# Node::Comment("Over".to_owned()),
404
+ ///# Node::Blue("The".to_owned()),
405
+ ///# Node::Comment("LazyDog".to_owned()),
406
+ ///# ],
407
+ ///# )
408
+ /// ```
409
+ #[ unstable( feature = "peekable_next_if_map" , issue = "143702" ) ]
410
+ pub fn next_if_map < R > ( & mut self , f : impl FnOnce ( I :: Item ) -> Result < R , I :: Item > ) -> Option < R > {
411
+ let unpeek = if let Some ( item) = self . next ( ) {
412
+ match f ( item) {
413
+ Ok ( result) => return Some ( result) ,
414
+ Err ( item) => Some ( item) ,
415
+ }
416
+ } else {
417
+ None
418
+ } ;
419
+ self . peeked = Some ( unpeek) ;
420
+ None
421
+ }
320
422
}
321
423
322
424
#[ unstable( feature = "trusted_len" , issue = "37572" ) ]
0 commit comments