1 | use crate::fmt; |
2 | use crate::iter::adapters::SourceIter; |
3 | use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; |
4 | use crate::num::NonZero; |
5 | use crate::ops::Try; |
6 | |
7 | /// An iterator that calls a function with a reference to each element before |
8 | /// yielding it. |
9 | /// |
10 | /// This `struct` is created by the [`inspect`] method on [`Iterator`]. See its |
11 | /// documentation for more. |
12 | /// |
13 | /// [`inspect`]: Iterator::inspect |
14 | /// [`Iterator`]: trait.Iterator.html |
15 | #[must_use = "iterators are lazy and do nothing unless consumed" ] |
16 | #[stable (feature = "rust1" , since = "1.0.0" )] |
17 | #[derive (Clone)] |
18 | pub struct Inspect<I, F> { |
19 | iter: I, |
20 | f: F, |
21 | } |
22 | impl<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" )] |
29 | impl<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(name:"iter" , &self.iter).finish() |
32 | } |
33 | } |
34 | |
35 | impl<I: Iterator, F> Inspect<I, F> |
36 | where |
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: &::Item) = elt { |
42 | (self.f)(a); |
43 | } |
44 | |
45 | elt |
46 | } |
47 | } |
48 | |
49 | fn 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: Acc, item: T| { |
54 | f(&item); |
55 | fold(acc, item) |
56 | } |
57 | } |
58 | |
59 | fn 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: Acc, item: T| { |
64 | f(&item); |
65 | fold(acc, item) |
66 | } |
67 | } |
68 | |
69 | #[stable (feature = "rust1" , since = "1.0.0" )] |
70 | impl<I: Iterator, F> Iterator for Inspect<I, F> |
71 | where |
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" )] |
107 | impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F> |
108 | where |
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" )] |
137 | impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F> |
138 | where |
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" )] |
151 | impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {} |
152 | |
153 | #[unstable (issue = "none" , feature = "trusted_fused" )] |
154 | unsafe impl<I: TrustedFused, F> TrustedFused for Inspect<I, F> {} |
155 | |
156 | #[unstable (issue = "none" , feature = "inplace_iteration" )] |
157 | unsafe impl<I, F> SourceIter for Inspect<I, F> |
158 | where |
159 | I: SourceIter, |
160 | { |
161 | type Source = I::Source; |
162 | |
163 | #[inline ] |
164 | unsafe fn as_inner(&mut self) -> &mut I::Source { |
165 | // SAFETY: unsafe function forwarding to unsafe function with the same requirements |
166 | unsafe { SourceIter::as_inner(&mut self.iter) } |
167 | } |
168 | } |
169 | |
170 | #[unstable (issue = "none" , feature = "inplace_iteration" )] |
171 | unsafe 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 | } |
175 | |