#
core/iter/adapters/
cloned.rs

    1use core::num::NonZero;
    2
    3use crate::iter::adapters::zip::try_get_unchecked;
    4use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
    5use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
    6use crate::ops::Try;
    7
    8/// An iterator that clones the elements of an underlying iterator.
    9///
    10/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its
    11/// documentation for more.
    12///
    13/// [`cloned`]: Iterator::cloned
    14/// [`Iterator`]: trait.Iterator.html
    15#[stable(feature = "iter_cloned", since = "1.1.0")]
    16#[must_use = "iterators are lazy and do nothing unless consumed"]
    17#[derive(Clone, Debug)]
    18pub struct Cloned<I> {
    19    it: I,
    20}
    21
    22impl<I> Cloned<I> {
    23    pub(in crate::iter) fn new(it: I) -> Cloned<I> {
    24        Cloned { it }
    25    }
    26}
    27
    28fn clone_try_fold<T: Clone, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
    29    move |acc, elt| f(acc, elt.clone())
    30}
    31
    32#[stable(feature = "iter_cloned", since = "1.1.0")]
    33impl<'a, I, T: 'a> Iterator for Cloned<I>
    34where
    35    I: Iterator<Item = &'a T>,
    36    T: Clone,
    37{
    38    type Item = T;
    39
    40    fn next(&mut self) -> Option<T> {
    41        self.it.next().cloned()
    42    }
    43
    44    fn size_hint(&self) -> (usize, Option<usize>) {
    45        self.it.size_hint()
    46    }
    47
    48    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
    49    where
    50        Self: Sized,
    51        F: FnMut(B, Self::Item) -> R,
    52        R: Try<Output = B>,
    53    {
    54        self.it.try_fold(init, clone_try_fold(f))
    55    }
    56
    57    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
    58    where
    59        F: FnMut(Acc, Self::Item) -> Acc,
    60    {
    61        self.it.map(T::clone).fold(init, f)
    62    }
    63
    64    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
    65    where
    66        Self: TrustedRandomAccessNoCoerce,
    67    {
    68        // SAFETY: the caller must uphold the contract for
    69        // `Iterator::__iterator_get_unchecked`.
    70        unsafe { try_get_unchecked(&mut self.it, idx).clone() }
    71    }
    72}
    73
    74#[stable(feature = "iter_cloned", since = "1.1.0")]
    75impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
    76where
    77    I: DoubleEndedIterator<Item = &'a T>,
    78    T: Clone,
    79{
    80    fn next_back(&mut self) -> Option<T> {
    81        self.it.next_back().cloned()
    82    }
    83
    84    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
    85    where
    86        Self: Sized,
    87        F: FnMut(B, Self::Item) -> R,
    88        R: Try<Output = B>,
    89    {
    90        self.it.try_rfold(init, clone_try_fold(f))
    91    }
    92
    93    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
    94    where
    95        F: FnMut(Acc, Self::Item) -> Acc,
    96    {
    97        self.it.map(T::clone).rfold(init, f)
    98    }
    99}
    100
    101#[stable(feature = "iter_cloned", since = "1.1.0")]
    102impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
    103where
    104    I: ExactSizeIterator<Item = &'a T>,
    105    T: Clone,
    106{
    107    fn len(&self) -> usize {
    108        self.it.len()
    109    }
    110
    111    fn is_empty(&self) -> bool {
    112        self.it.is_empty()
    113    }
    114}
    115
    116#[stable(feature = "fused", since = "1.26.0")]
    117impl<'a, I, T: 'a> FusedIterator for Cloned<I>
    118where
    119    I: FusedIterator<Item = &'a T>,
    120    T: Clone,
    121{
    122}
    123
    124#[doc(hidden)]
    125#[unstable(feature = "trusted_random_access", issue = "none")]
    126unsafe impl<I> TrustedRandomAccess for Cloned<I> where I: TrustedRandomAccess {}
    127
    128#[doc(hidden)]
    129#[unstable(feature = "trusted_random_access", issue = "none")]
    130unsafe impl<I> TrustedRandomAccessNoCoerce for Cloned<I>
    131where
    132    I: TrustedRandomAccessNoCoerce,
    133{
    134    const MAY_HAVE_SIDE_EFFECT: bool = true;
    135}
    136
    137#[unstable(feature = "trusted_len", issue = "37572")]
    138unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
    139where
    140    I: TrustedLen<Item = &'a T>,
    141    T: Clone,
    142{
    143}
    144
    145impl<'a, I, T: 'a> UncheckedIterator for Cloned<I>
    146where
    147    I: UncheckedIterator<Item = &'a T>,
    148    T: Clone,
    149{
    150    unsafe fn next_unchecked(&mut self) -> T {
    151        // SAFETY: `Cloned` is 1:1 with the inner iterator, so if the caller promised
    152        // that there's an element left, the inner iterator has one too.
    153        let item = unsafe { self.it.next_unchecked() };
    154        item.clone()
    155    }
    156}
    157
    158#[stable(feature = "default_iters", since = "1.70.0")]
    159impl<I: Default> Default for Cloned<I> {
    160    /// Creates a `Cloned` iterator from the default value of `I`
    161    /// ```
    162    /// # use core::slice;
    163    /// # use core::iter::Cloned;
    164    /// let iter: Cloned<slice::Iter<'_, u8>> = Default::default();
    165    /// assert_eq!(iter.len(), 0);
    166    /// ```
    167    fn default() -> Self {
    168        Self::new(Default::default())
    169    }
    170}
    171
    172#[unstable(issue = "none", feature = "inplace_iteration")]
    173unsafe impl<I> SourceIter for Cloned<I>
    174where
    175    I: SourceIter,
    176{
    177    type Source = I::Source;
    178
    179    #[inline]
    180    unsafe fn as_inner(&mut self) -> &mut I::Source {
    181        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
    182        unsafe { SourceIter::as_inner(&mut self.it) }
    183    }
    184}
    185
    186#[unstable(issue = "none", feature = "inplace_iteration")]
    187unsafe impl<I: InPlaceIterable> InPlaceIterable for Cloned<I> {
    188    const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
    189    const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
    190}