1use crate::fmt;
2use crate::iter::{adapters::SourceIter, InPlaceIterable};
3use crate::num::NonZeroUsize;
4use crate::ops::{ControlFlow, Try};
5
6/// An iterator to maintain state while iterating another iterator.
7///
8/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its
9/// documentation for more.
10///
11/// [`scan`]: Iterator::scan
12/// [`Iterator`]: trait.Iterator.html
13#[must_use = "iterators are lazy and do nothing unless consumed"]
14#[stable(feature = "rust1", since = "1.0.0")]
15#[derive(Clone)]
16pub struct Scan<I, St, F> {
17 iter: I,
18 f: F,
19 state: St,
20}
21
22impl<I, St, F> Scan<I, St, F> {
23 pub(in crate::iter) fn new(iter: I, state: St, f: F) -> Scan<I, St, F> {
24 Scan { iter, state, f }
25 }
26}
27
28#[stable(feature = "core_impl_debug", since = "1.9.0")]
29impl<I: fmt::Debug, St: fmt::Debug, F> fmt::Debug for Scan<I, St, F> {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 f.debug_struct("Scan").field("iter", &self.iter).field(name:"state", &self.state).finish()
32 }
33}
34
35#[stable(feature = "rust1", since = "1.0.0")]
36impl<B, I, St, F> Iterator for Scan<I, St, F>
37where
38 I: Iterator,
39 F: FnMut(&mut St, I::Item) -> Option<B>,
40{
41 type Item = B;
42
43 #[inline]
44 fn next(&mut self) -> Option<B> {
45 let a = self.iter.next()?;
46 (self.f)(&mut self.state, a)
47 }
48
49 #[inline]
50 fn size_hint(&self) -> (usize, Option<usize>) {
51 let (_, upper) = self.iter.size_hint();
52 (0, upper) // can't know a lower bound, due to the scan function
53 }
54
55 #[inline]
56 fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
57 where
58 Self: Sized,
59 Fold: FnMut(Acc, Self::Item) -> R,
60 R: Try<Output = Acc>,
61 {
62 fn scan<'a, T, St, B, Acc, R: Try<Output = Acc>>(
63 state: &'a mut St,
64 f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
65 mut fold: impl FnMut(Acc, B) -> R + 'a,
66 ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
67 move |acc, x| match f(state, x) {
68 None => ControlFlow::Break(try { acc }),
69 Some(x) => ControlFlow::from_try(fold(acc, x)),
70 }
71 }
72
73 let state = &mut self.state;
74 let f = &mut self.f;
75 self.iter.try_fold(init, scan(state, f, fold)).into_try()
76 }
77
78 impl_fold_via_try_fold! { fold -> try_fold }
79}
80
81#[unstable(issue = "none", feature = "inplace_iteration")]
82unsafe impl<St, F, I> SourceIter for Scan<I, St, F>
83where
84 I: SourceIter,
85{
86 type Source = I::Source;
87
88 #[inline]
89 unsafe fn as_inner(&mut self) -> &mut I::Source {
90 // SAFETY: unsafe function forwarding to unsafe function with the same requirements
91 unsafe { SourceIter::as_inner(&mut self.iter) }
92 }
93}
94
95#[unstable(issue = "none", feature = "inplace_iteration")]
96unsafe impl<St, F, I: InPlaceIterable> InPlaceIterable for Scan<I, St, F> {
97 const EXPAND_BY: Option<NonZeroUsize> = I::EXPAND_BY;
98 const MERGE_BY: Option<NonZeroUsize> = I::MERGE_BY;
99}
100