core/iter/adapters/
inspect.rs

1use crate::fmt;
2use crate::iter::adapters::SourceIter;
3use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
4use crate::num::NonZero;
5use 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)]
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        // 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")]
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}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy