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

#
core/iter/adapters/
copied.rs

    1use crate::iter::adapters::zip::try_get_unchecked;
    2use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
    3use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
    4use crate::mem::{MaybeUninit, SizedTypeProperties};
    5use crate::num::NonZero;
    6use crate::ops::Try;
    7use crate::{array, ptr};
    8
    9/// An iterator that copies the elements of an underlying iterator.
    10///
    11/// This `struct` is created by the [`copied`] method on [`Iterator`]. See its
    12/// documentation for more.
    13///
    14/// [`copied`]: Iterator::copied
    15/// [`Iterator`]: trait.Iterator.html
    16#[stable(feature = "iter_copied", since = "1.36.0")]
    17#[must_use = "iterators are lazy and do nothing unless consumed"]
    18#[derive(Clone, Debug)]
    19pub struct Copied<I> {
    20    it: I,
    21}
    22
    23impl<I> Copied<I> {
    24    pub(in crate::iter) fn new(it: I) -> Copied<I> {
    25        Copied { it }
    26    }
    27
    28    #[doc(hidden)]
    29    #[unstable(feature = "copied_into_inner", issue = "none")]
    30    pub fn into_inner(self) -> I {
    31        self.it
    32    }
    33}
    34
    35fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc {
    36    move |acc, &elt| f(acc, elt)
    37}
    38
    39fn copy_try_fold<T: Copy, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
    40    move |acc, &elt| f(acc, elt)
    41}
    42
    43#[stable(feature = "iter_copied", since = "1.36.0")]
    44impl<'a, I, T: 'a> Iterator for Copied<I>
    45where
    46    I: Iterator<Item = &'a T>,
    47    T: Copy,
    48{
    49    type Item = T;
    50
    51    fn next(&mut self) -> Option<T> {
    52        self.it.next().copied()
    53    }
    54
    55    fn next_chunk<const N: usize>(
    56        &mut self,
    57    ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
    58    where
    59        Self: Sized,
    60    {
    61        <I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
    62    }
    63
    64    fn size_hint(&self) -> (usize, Option<usize>) {
    65        self.it.size_hint()
    66    }
    67
    68    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
    69    where
    70        Self: Sized,
    71        F: FnMut(B, Self::Item) -> R,
    72        R: Try<Output = B>,
    73    {
    74        self.it.try_fold(init, copy_try_fold(f))
    75    }
    76
    77    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
    78    where
    79        F: FnMut(Acc, Self::Item) -> Acc,
    80    {
    81        self.it.fold(init, copy_fold(f))
    82    }
    83
    84    fn nth(&mut self, n: usize) -> Option<T> {
    85        self.it.nth(n).copied()
    86    }
    87
    88    fn last(self) -> Option<T> {
    89        self.it.last().copied()
    90    }
    91
    92    fn count(self) -> usize {
    93        self.it.count()
    94    }
    95
    96    #[inline]
    97    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
    98        self.it.advance_by(n)
    99    }
    100
    101    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
    102    where
    103        Self: TrustedRandomAccessNoCoerce,
    104    {
    105        // SAFETY: the caller must uphold the contract for
    106        // `Iterator::__iterator_get_unchecked`.
    107        *unsafe { try_get_unchecked(&mut self.it, idx) }
    108    }
    109}
    110
    111#[stable(feature = "iter_copied", since = "1.36.0")]
    112impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
    113where
    114    I: DoubleEndedIterator<Item = &'a T>,
    115    T: Copy,
    116{
    117    fn next_back(&mut self) -> Option<T> {
    118        self.it.next_back().copied()
    119    }
    120
    121    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
    122    where
    123        Self: Sized,
    124        F: FnMut(B, Self::Item) -> R,
    125        R: Try<Output = B>,
    126    {
    127        self.it.try_rfold(init, copy_try_fold(f))
    128    }
    129
    130    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
    131    where
    132        F: FnMut(Acc, Self::Item) -> Acc,
    133    {
    134        self.it.rfold(init, copy_fold(f))
    135    }
    136
    137    #[inline]
    138    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
    139        self.it.advance_back_by(n)
    140    }
    141}
    142
    143#[stable(feature = "iter_copied", since = "1.36.0")]
    144impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
    145where
    146    I: ExactSizeIterator<Item = &'a T>,
    147    T: Copy,
    148{
    149    fn len(&self) -> usize {
    150        self.it.len()
    151    }
    152
    153    fn is_empty(&self) -> bool {
    154        self.it.is_empty()
    155    }
    156}
    157
    158#[stable(feature = "iter_copied", since = "1.36.0")]
    159impl<'a, I, T: 'a> FusedIterator for Copied<I>
    160where
    161    I: FusedIterator<Item = &'a T>,
    162    T: Copy,
    163{
    164}
    165
    166#[doc(hidden)]
    167#[unstable(feature = "trusted_random_access", issue = "none")]
    168unsafe impl<I> TrustedRandomAccess for Copied<I> where I: TrustedRandomAccess {}
    169
    170#[doc(hidden)]
    171#[unstable(feature = "trusted_random_access", issue = "none")]
    172unsafe impl<I> TrustedRandomAccessNoCoerce for Copied<I>
    173where
    174    I: TrustedRandomAccessNoCoerce,
    175{
    176    const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
    177}
    178
    179#[stable(feature = "iter_copied", since = "1.36.0")]
    180unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
    181where
    182    I: TrustedLen<Item = &'a T>,
    183    T: Copy,
    184{
    185}
    186
    187trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T>
    188where
    189    T: Copy,
    190{
    191    fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>;
    192}
    193
    194impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I
    195where
    196    I: Iterator<Item = &'a T>,
    197    T: Copy,
    198{
    199    default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
    200        array::iter_next_chunk(&mut self.copied())
    201    }
    202}
    203
    204impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T>
    205where
    206    T: Copy,
    207{
    208    fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
    209        let mut raw_array = [const { MaybeUninit::uninit() }; N];
    210
    211        let len = self.len();
    212
    213        if T::IS_ZST {
    214            if len < N {
    215                let _ = self.advance_by(len);
    216                // SAFETY: ZSTs can be conjured ex nihilo; only the amount has to be correct
    217                return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) });
    218            }
    219
    220            let _ = self.advance_by(N);
    221            // SAFETY: ditto
    222            return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) });
    223        }
    224
    225        if len < N {
    226            // SAFETY: `len` indicates that this many elements are available and we just checked that
    227            // it fits into the array.
    228            unsafe {
    229                ptr::copy_nonoverlapping(
    230                    self.as_ref().as_ptr(),
    231                    raw_array.as_mut_ptr() as *mut T,
    232                    len,
    233                );
    234                let _ = self.advance_by(len);
    235                return Err(array::IntoIter::new_unchecked(raw_array, 0..len));
    236            }
    237        }
    238
    239        // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize
    240        // the array.
    241        unsafe {
    242            ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N);
    243            let _ = self.advance_by(N);
    244            Ok(MaybeUninit::array_assume_init(raw_array))
    245        }
    246    }
    247}
    248
    249#[stable(feature = "default_iters", since = "1.70.0")]
    250impl<I: Default> Default for Copied<I> {
    251    /// Creates a `Copied` iterator from the default value of `I`
    252    /// ```
    253    /// # use core::slice;
    254    /// # use core::iter::Copied;
    255    /// let iter: Copied<slice::Iter<'_, u8>> = Default::default();
    256    /// assert_eq!(iter.len(), 0);
    257    /// ```
    258    fn default() -> Self {
    259        Self::new(Default::default())
    260    }
    261}
    262
    263#[unstable(issue = "none", feature = "inplace_iteration")]
    264unsafe impl<I> SourceIter for Copied<I>
    265where
    266    I: SourceIter,
    267{
    268    type Source = I::Source;
    269
    270    #[inline]
    271    unsafe fn as_inner(&mut self) -> &mut I::Source {
    272        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
    273        unsafe { SourceIter::as_inner(&mut self.it) }
    274    }
    275}
    276
    277#[unstable(issue = "none", feature = "inplace_iteration")]
    278unsafe impl<I: InPlaceIterable> InPlaceIterable for Copied<I> {
    279    const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
    280    const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
    281}