1use crate::fmt;
2use crate::iter::adapters::SourceIter;
3use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
4use crate::num::NonZero;
5use crate::ops::Try;
6
7#[must_use = "iterators are lazy and do nothing unless consumed"]
16#[stable(feature = "rust1", since = "1.0.0")]
17#[derive(Clone)]
18pub struct Inspect<I, F> {
19 iter: I,
20 f: F,
21}
22impl<I, F> Inspect<I, F> {
23 pub(in crate::iter) fn new(iter: I, f: F) -> Inspect<I, F> {
24 Inspect { iter, f }
25 }
26}
27
28#[stable(feature = "core_impl_debug", since = "1.9.0")]
29impl<I: fmt::Debug, F> fmt::Debug for Inspect<I, F> {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 f.debug_struct("Inspect").field("iter", &self.iter).finish()
32 }
33}
34
35impl<I: Iterator, F> Inspect<I, F>
36where
37 F: FnMut(&I::Item),
38{
39 #[inline]
40 fn do_inspect(&mut self, elt: Option<I::Item>) -> Option<I::Item> {
41 if let Some(ref a) = elt {
42 (self.f)(a);
43 }
44
45 elt
46 }
47}
48
49fn inspect_fold<T, Acc>(
50 mut f: impl FnMut(&T),
51 mut fold: impl FnMut(Acc, T) -> Acc,
52) -> impl FnMut(Acc, T) -> Acc {
53 move |acc, item| {
54 f(&item);
55 fold(acc, item)
56 }
57}
58
59fn inspect_try_fold<'a, T, Acc, R>(
60 f: &'a mut impl FnMut(&T),
61 mut fold: impl FnMut(Acc, T) -> R + 'a,
62) -> impl FnMut(Acc, T) -> R + 'a {
63 move |acc, item| {
64 f(&item);
65 fold(acc, item)
66 }
67}
68
69#[stable(feature = "rust1", since = "1.0.0")]
70impl<I: Iterator, F> Iterator for Inspect<I, F>
71where
72 F: FnMut(&I::Item),
73{
74 type Item = I::Item;
75
76 #[inline]
77 fn next(&mut self) -> Option<I::Item> {
78 let next = self.iter.next();
79 self.do_inspect(next)
80 }
81
82 #[inline]
83 fn size_hint(&self) -> (usize, Option<usize>) {
84 self.iter.size_hint()
85 }
86
87 #[inline]
88 fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
89 where
90 Self: Sized,
91 Fold: FnMut(Acc, Self::Item) -> R,
92 R: Try<Output = Acc>,
93 {
94 self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold))
95 }
96
97 #[inline]
98 fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
99 where
100 Fold: FnMut(Acc, Self::Item) -> Acc,
101 {
102 self.iter.fold(init, inspect_fold(self.f, fold))
103 }
104}
105
106#[stable(feature = "rust1", since = "1.0.0")]
107impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F>
108where
109 F: FnMut(&I::Item),
110{
111 #[inline]
112 fn next_back(&mut self) -> Option<I::Item> {
113 let next = self.iter.next_back();
114 self.do_inspect(next)
115 }
116
117 #[inline]
118 fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
119 where
120 Self: Sized,
121 Fold: FnMut(Acc, Self::Item) -> R,
122 R: Try<Output = Acc>,
123 {
124 self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold))
125 }
126
127 #[inline]
128 fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
129 where
130 Fold: FnMut(Acc, Self::Item) -> Acc,
131 {
132 self.iter.rfold(init, inspect_fold(self.f, fold))
133 }
134}
135
136#[stable(feature = "rust1", since = "1.0.0")]
137impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F>
138where
139 F: FnMut(&I::Item),
140{
141 fn len(&self) -> usize {
142 self.iter.len()
143 }
144
145 fn is_empty(&self) -> bool {
146 self.iter.is_empty()
147 }
148}
149
150#[stable(feature = "fused", since = "1.26.0")]
151impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {}
152
153#[unstable(issue = "none", feature = "trusted_fused")]
154unsafe impl<I: TrustedFused, F> TrustedFused for Inspect<I, F> {}
155
156#[unstable(issue = "none", feature = "inplace_iteration")]
157unsafe impl<I, F> SourceIter for Inspect<I, F>
158where
159 I: SourceIter,
160{
161 type Source = I::Source;
162
163 #[inline]
164 unsafe fn as_inner(&mut self) -> &mut I::Source {
165 unsafe { SourceIter::as_inner(&mut self.iter) }
167 }
168}
169
170#[unstable(issue = "none", feature = "inplace_iteration")]
171unsafe impl<I: InPlaceIterable, F> InPlaceIterable for Inspect<I, F> {
172 const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
173 const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
174}