]> git.lizzy.rs Git - rust.git/blob - library/core/src/iter/sources/successors.rs
Rollup merge of #79293 - Havvy:test-eval-order-compound-assign, r=Mark-Simulacrum
[rust.git] / library / core / src / iter / sources / successors.rs
1 use crate::{fmt, iter::FusedIterator};
2
3 /// Creates a new iterator where each successive item is computed based on the preceding one.
4 ///
5 /// The iterator starts with the given first item (if any)
6 /// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
7 ///
8 /// ```
9 /// use std::iter::successors;
10 ///
11 /// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
12 /// assert_eq!(powers_of_10.collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
13 /// ```
14 #[stable(feature = "iter_successors", since = "1.34.0")]
15 pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
16 where
17     F: FnMut(&T) -> Option<T>,
18 {
19     // If this function returned `impl Iterator<Item=T>`
20     // it could be based on `unfold` and not need a dedicated type.
21     // However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
22     Successors { next: first, succ }
23 }
24
25 /// An new iterator where each successive item is computed based on the preceding one.
26 ///
27 /// This `struct` is created by the [`iter::successors()`] function.
28 /// See its documentation for more.
29 ///
30 /// [`iter::successors()`]: successors
31 #[derive(Clone)]
32 #[stable(feature = "iter_successors", since = "1.34.0")]
33 pub struct Successors<T, F> {
34     next: Option<T>,
35     succ: F,
36 }
37
38 #[stable(feature = "iter_successors", since = "1.34.0")]
39 impl<T, F> Iterator for Successors<T, F>
40 where
41     F: FnMut(&T) -> Option<T>,
42 {
43     type Item = T;
44
45     #[inline]
46     fn next(&mut self) -> Option<Self::Item> {
47         let item = self.next.take()?;
48         self.next = (self.succ)(&item);
49         Some(item)
50     }
51
52     #[inline]
53     fn size_hint(&self) -> (usize, Option<usize>) {
54         if self.next.is_some() { (1, None) } else { (0, Some(0)) }
55     }
56 }
57
58 #[stable(feature = "iter_successors", since = "1.34.0")]
59 impl<T, F> FusedIterator for Successors<T, F> where F: FnMut(&T) -> Option<T> {}
60
61 #[stable(feature = "iter_successors", since = "1.34.0")]
62 impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
63     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64         f.debug_struct("Successors").field("next", &self.next).finish()
65     }
66 }