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#[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) const 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 #[inline]
69 fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
70 where
71 Self: Sized,
72 F: FnMut(B, Self::Item) -> R,
73 R: Try<Output = B>,
74 {
75 self.it.try_fold(init, copy_try_fold(f))
76 }
77
78 #[inline]
79 fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
80 where
81 F: FnMut(Acc, Self::Item) -> Acc,
82 {
83 self.it.fold(init, copy_fold(f))
84 }
85
86 fn nth(&mut self, n: usize) -> Option<T> {
87 self.it.nth(n).copied()
88 }
89
90 fn last(self) -> Option<T> {
91 self.it.last().copied()
92 }
93
94 fn count(self) -> usize {
95 self.it.count()
96 }
97
98 #[inline]
99 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
100 self.it.advance_by(n)
101 }
102
103 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
104 where
105 Self: TrustedRandomAccessNoCoerce,
106 {
107 *unsafe { try_get_unchecked(&mut self.it, idx) }
110 }
111}
112
113#[stable(feature = "iter_copied", since = "1.36.0")]
114impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
115where
116 I: DoubleEndedIterator<Item = &'a T>,
117 T: Copy,
118{
119 fn next_back(&mut self) -> Option<T> {
120 self.it.next_back().copied()
121 }
122
123 #[inline]
124 fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
125 where
126 Self: Sized,
127 F: FnMut(B, Self::Item) -> R,
128 R: Try<Output = B>,
129 {
130 self.it.try_rfold(init, copy_try_fold(f))
131 }
132
133 #[inline]
134 fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
135 where
136 F: FnMut(Acc, Self::Item) -> Acc,
137 {
138 self.it.rfold(init, copy_fold(f))
139 }
140
141 #[inline]
142 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
143 self.it.advance_back_by(n)
144 }
145}
146
147#[stable(feature = "iter_copied", since = "1.36.0")]
148impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
149where
150 I: ExactSizeIterator<Item = &'a T>,
151 T: Copy,
152{
153 fn len(&self) -> usize {
154 self.it.len()
155 }
156
157 fn is_empty(&self) -> bool {
158 self.it.is_empty()
159 }
160}
161
162#[stable(feature = "iter_copied", since = "1.36.0")]
163impl<'a, I, T: 'a> FusedIterator for Copied<I>
164where
165 I: FusedIterator<Item = &'a T>,
166 T: Copy,
167{
168}
169
170#[doc(hidden)]
171#[unstable(feature = "trusted_random_access", issue = "none")]
172unsafe impl<I> TrustedRandomAccess for Copied<I> where I: TrustedRandomAccess {}
173
174#[doc(hidden)]
175#[unstable(feature = "trusted_random_access", issue = "none")]
176unsafe impl<I> TrustedRandomAccessNoCoerce for Copied<I>
177where
178 I: TrustedRandomAccessNoCoerce,
179{
180 const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
181}
182
183#[stable(feature = "iter_copied", since = "1.36.0")]
184unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
185where
186 I: TrustedLen<Item = &'a T>,
187 T: Copy,
188{
189}
190
191trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T>
192where
193 T: Copy,
194{
195 fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>;
196}
197
198impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I
199where
200 I: Iterator<Item = &'a T>,
201 T: Copy,
202{
203 default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
204 array::iter_next_chunk(&mut self.copied())
205 }
206}
207
208impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T>
209where
210 T: Copy,
211{
212 fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
213 let mut raw_array = [const { MaybeUninit::uninit() }; N];
214
215 let len = self.len();
216
217 if T::IS_ZST {
218 if len < N {
219 let _ = self.advance_by(len);
220 return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) });
222 }
223
224 let _ = self.advance_by(N);
225 return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) });
227 }
228
229 if len < N {
230 unsafe {
233 ptr::copy_nonoverlapping(
234 self.as_ref().as_ptr(),
235 raw_array.as_mut_ptr() as *mut T,
236 len,
237 );
238 let _ = self.advance_by(len);
239 return Err(array::IntoIter::new_unchecked(raw_array, 0..len));
240 }
241 }
242
243 unsafe {
246 ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N);
247 let _ = self.advance_by(N);
248 Ok(MaybeUninit::array_assume_init(raw_array))
249 }
250 }
251}
252
253#[stable(feature = "default_iters", since = "1.70.0")]
254impl<I: Default> Default for Copied<I> {
255 fn default() -> Self {
263 Self::new(Default::default())
264 }
265}
266
267#[unstable(issue = "none", feature = "inplace_iteration")]
268unsafe impl<I> SourceIter for Copied<I>
269where
270 I: SourceIter,
271{
272 type Source = I::Source;
273
274 #[inline]
275 unsafe fn as_inner(&mut self) -> &mut I::Source {
276 unsafe { SourceIter::as_inner(&mut self.it) }
278 }
279}
280
281#[unstable(issue = "none", feature = "inplace_iteration")]
282unsafe impl<I: InPlaceIterable> InPlaceIterable for Copied<I> {
283 const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
284 const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
285}