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)]
19#[ferrocene::prevalidated]
20pub struct Copied<I> {
21 it: I,
22}
23
24impl<I> Copied<I> {
25 #[ferrocene::prevalidated]
26 pub(in crate::iter) fn new(it: I) -> Copied<I> {
27 Copied { it }
28 }
29
30 #[doc(hidden)]
31 #[unstable(feature = "copied_into_inner", issue = "none")]
32 pub fn into_inner(self) -> I {
33 self.it
34 }
35}
36
37#[ferrocene::prevalidated]
38fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc {
39 move |acc, &elt| f(acc, elt)
40}
41
42#[ferrocene::prevalidated]
43fn copy_try_fold<T: Copy, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
44 move |acc, &elt| f(acc, elt)
45}
46
47#[stable(feature = "iter_copied", since = "1.36.0")]
48impl<'a, I, T: 'a> Iterator for Copied<I>
49where
50 I: Iterator<Item = &'a T>,
51 T: Copy,
52{
53 type Item = T;
54
55 #[ferrocene::prevalidated]
56 fn next(&mut self) -> Option<T> {
57 self.it.next().copied()
58 }
59
60 fn next_chunk<const N: usize>(
61 &mut self,
62 ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
63 where
64 Self: Sized,
65 {
66 <I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
67 }
68
69 #[ferrocene::prevalidated]
70 fn size_hint(&self) -> (usize, Option<usize>) {
71 self.it.size_hint()
72 }
73
74 #[ferrocene::prevalidated]
75 fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
76 where
77 Self: Sized,
78 F: FnMut(B, Self::Item) -> R,
79 R: Try<Output = B>,
80 {
81 self.it.try_fold(init, copy_try_fold(f))
82 }
83
84 #[ferrocene::prevalidated]
85 fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
86 where
87 F: FnMut(Acc, Self::Item) -> Acc,
88 {
89 self.it.fold(init, copy_fold(f))
90 }
91
92 #[ferrocene::prevalidated]
93 fn nth(&mut self, n: usize) -> Option<T> {
94 self.it.nth(n).copied()
95 }
96
97 #[ferrocene::prevalidated]
98 fn last(self) -> Option<T> {
99 self.it.last().copied()
100 }
101
102 #[ferrocene::prevalidated]
103 fn count(self) -> usize {
104 self.it.count()
105 }
106
107 #[inline]
108 #[ferrocene::prevalidated]
109 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
110 self.it.advance_by(n)
111 }
112
113 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
114 where
115 Self: TrustedRandomAccessNoCoerce,
116 {
117 *unsafe { try_get_unchecked(&mut self.it, idx) }
120 }
121}
122
123#[stable(feature = "iter_copied", since = "1.36.0")]
124impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
125where
126 I: DoubleEndedIterator<Item = &'a T>,
127 T: Copy,
128{
129 #[ferrocene::prevalidated]
130 fn next_back(&mut self) -> Option<T> {
131 self.it.next_back().copied()
132 }
133
134 #[ferrocene::prevalidated]
135 fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
136 where
137 Self: Sized,
138 F: FnMut(B, Self::Item) -> R,
139 R: Try<Output = B>,
140 {
141 self.it.try_rfold(init, copy_try_fold(f))
142 }
143
144 #[ferrocene::prevalidated]
145 fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
146 where
147 F: FnMut(Acc, Self::Item) -> Acc,
148 {
149 self.it.rfold(init, copy_fold(f))
150 }
151
152 #[inline]
153 #[ferrocene::prevalidated]
154 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
155 self.it.advance_back_by(n)
156 }
157}
158
159#[stable(feature = "iter_copied", since = "1.36.0")]
160impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
161where
162 I: ExactSizeIterator<Item = &'a T>,
163 T: Copy,
164{
165 #[ferrocene::prevalidated]
166 fn len(&self) -> usize {
167 self.it.len()
168 }
169
170 #[ferrocene::prevalidated]
171 fn is_empty(&self) -> bool {
172 self.it.is_empty()
173 }
174}
175
176#[stable(feature = "iter_copied", since = "1.36.0")]
177impl<'a, I, T: 'a> FusedIterator for Copied<I>
178where
179 I: FusedIterator<Item = &'a T>,
180 T: Copy,
181{
182}
183
184#[doc(hidden)]
185#[unstable(feature = "trusted_random_access", issue = "none")]
186unsafe impl<I> TrustedRandomAccess for Copied<I> where I: TrustedRandomAccess {}
187
188#[doc(hidden)]
189#[unstable(feature = "trusted_random_access", issue = "none")]
190unsafe impl<I> TrustedRandomAccessNoCoerce for Copied<I>
191where
192 I: TrustedRandomAccessNoCoerce,
193{
194 const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
195}
196
197#[stable(feature = "iter_copied", since = "1.36.0")]
198unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
199where
200 I: TrustedLen<Item = &'a T>,
201 T: Copy,
202{
203}
204
205trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T>
206where
207 T: Copy,
208{
209 fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>;
210}
211
212impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I
213where
214 I: Iterator<Item = &'a T>,
215 T: Copy,
216{
217 default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
218 array::iter_next_chunk(&mut self.copied())
219 }
220}
221
222impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T>
223where
224 T: Copy,
225{
226 fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
227 let mut raw_array = [const { MaybeUninit::uninit() }; N];
228
229 let len = self.len();
230
231 if T::IS_ZST {
232 if len < N {
233 let _ = self.advance_by(len);
234 return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) });
236 }
237
238 let _ = self.advance_by(N);
239 return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) });
241 }
242
243 if len < N {
244 unsafe {
247 ptr::copy_nonoverlapping(
248 self.as_ref().as_ptr(),
249 raw_array.as_mut_ptr() as *mut T,
250 len,
251 );
252 let _ = self.advance_by(len);
253 return Err(array::IntoIter::new_unchecked(raw_array, 0..len));
254 }
255 }
256
257 unsafe {
260 ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N);
261 let _ = self.advance_by(N);
262 Ok(MaybeUninit::array_assume_init(raw_array))
263 }
264 }
265}
266
267#[stable(feature = "default_iters", since = "1.70.0")]
268impl<I: Default> Default for Copied<I> {
269 fn default() -> Self {
277 Self::new(Default::default())
278 }
279}
280
281#[unstable(issue = "none", feature = "inplace_iteration")]
282unsafe impl<I> SourceIter for Copied<I>
283where
284 I: SourceIter,
285{
286 type Source = I::Source;
287
288 #[inline]
289 unsafe fn as_inner(&mut self) -> &mut I::Source {
290 unsafe { SourceIter::as_inner(&mut self.it) }
292 }
293}
294
295#[unstable(issue = "none", feature = "inplace_iteration")]
296unsafe impl<I: InPlaceIterable> InPlaceIterable for Copied<I> {
297 const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
298 const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
299}