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