inspect.rs - source
Description: Source of the Rust file `library/core/src/iter/adapters/inspect.rs`.

#
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}