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