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) 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 *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 return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) });
218 }
219
220 let _ = self.advance_by(N);
221 return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) });
223 }
224
225 if len < N {
226 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 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 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 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}