1use crate::cmp::Ordering;
2use crate::iter::adapters::zip::try_get_unchecked;
3use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
4use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
5use crate::mem::{MaybeUninit, SizedTypeProperties};
6use crate::num::NonZero;
7use crate::ops::Try;
8use crate::{array, ptr};
9
10#[stable(feature = "iter_copied", since = "1.36.0")]
18#[must_use = "iterators are lazy and do nothing unless consumed"]
19#[derive(Clone, Debug)]
20pub struct Copied<I> {
21 it: I,
22}
23
24impl<I> Copied<I> {
25 pub(in crate::iter) fn new(it: I) -> Copied<I> {
26 Copied { it }
27 }
28}
29
30fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc {
31 move |acc, &elt| f(acc, elt)
32}
33
34fn copy_try_fold<T: Copy, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
35 move |acc, &elt| f(acc, elt)
36}
37
38#[stable(feature = "iter_copied", since = "1.36.0")]
39impl<'a, I, T: 'a> Iterator for Copied<I>
40where
41 I: Iterator<Item = &'a T>,
42 T: Copy,
43{
44 type Item = T;
45
46 fn next(&mut self) -> Option<T> {
47 self.it.next().copied()
48 }
49
50 fn next_chunk<const N: usize>(
51 &mut self,
52 ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
53 <I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
54 }
55
56 #[inline]
57 fn size_hint(&self) -> (usize, Option<usize>) {
58 self.it.size_hint()
59 }
60
61 #[inline]
62 fn count(self) -> usize {
63 self.it.count()
64 }
65
66 fn last(self) -> Option<T> {
67 self.it.last().copied()
68 }
69
70 #[inline]
71 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
72 self.it.advance_by(n)
73 }
74
75 fn nth(&mut self, n: usize) -> Option<T> {
76 self.it.nth(n).copied()
77 }
78
79 fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
80 where
81 F: FnMut(B, Self::Item) -> R,
82 R: Try<Output = B>,
83 {
84 self.it.try_fold(init, copy_try_fold(f))
85 }
86
87 fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
88 where
89 F: FnMut(Acc, Self::Item) -> Acc,
90 {
91 self.it.fold(init, copy_fold(f))
92 }
93
94 fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
95 where
96 P: FnMut(&Self::Item) -> bool,
97 {
98 self.it.find(move |x| predicate(&x)).copied()
99 }
100
101 fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
102 where
103 F: FnMut(&Self::Item, &Self::Item) -> Ordering,
104 {
105 self.it.max_by(move |&x, &y| compare(x, y)).copied()
106 }
107
108 fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
109 where
110 F: FnMut(&Self::Item, &Self::Item) -> Ordering,
111 {
112 self.it.min_by(move |&x, &y| compare(x, y)).copied()
113 }
114
115 fn cmp<O>(self, other: O) -> Ordering
116 where
117 O: IntoIterator<Item = Self::Item>,
118 Self::Item: Ord,
119 {
120 self.it.cmp_by(other, |x, y| x.cmp(&y))
121 }
122
123 fn partial_cmp<O>(self, other: O) -> Option<Ordering>
124 where
125 O: IntoIterator,
126 Self::Item: PartialOrd<O::Item>,
127 {
128 self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
129 }
130
131 fn eq<O>(self, other: O) -> bool
132 where
133 O: IntoIterator,
134 Self::Item: PartialEq<O::Item>,
135 {
136 self.it.eq_by(other, |x, y| x == &y)
137 }
138
139 fn is_sorted_by<F>(self, mut compare: F) -> bool
140 where
141 F: FnMut(&Self::Item, &Self::Item) -> bool,
142 {
143 self.it.is_sorted_by(move |&x, &y| compare(x, y))
144 }
145
146 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
147 where
148 Self: TrustedRandomAccessNoCoerce,
149 {
150 *unsafe { try_get_unchecked(&mut self.it, idx) }
153 }
154}
155
156#[stable(feature = "iter_copied", since = "1.36.0")]
157impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
158where
159 I: DoubleEndedIterator<Item = &'a T>,
160 T: Copy,
161{
162 fn next_back(&mut self) -> Option<T> {
163 self.it.next_back().copied()
164 }
165
166 #[inline]
167 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
168 self.it.advance_back_by(n)
169 }
170
171 fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
172 where
173 F: FnMut(B, Self::Item) -> R,
174 R: Try<Output = B>,
175 {
176 self.it.try_rfold(init, copy_try_fold(f))
177 }
178
179 fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
180 where
181 F: FnMut(Acc, Self::Item) -> Acc,
182 {
183 self.it.rfold(init, copy_fold(f))
184 }
185
186 fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
187 where
188 P: FnMut(&Self::Item) -> bool,
189 {
190 self.it.rfind(move |x| predicate(&x)).copied()
191 }
192}
193
194#[stable(feature = "iter_copied", since = "1.36.0")]
195impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
196where
197 I: ExactSizeIterator<Item = &'a T>,
198 T: Copy,
199{
200 #[inline]
201 fn len(&self) -> usize {
202 self.it.len()
203 }
204
205 #[inline]
206 fn is_empty(&self) -> bool {
207 self.it.is_empty()
208 }
209}
210
211#[stable(feature = "iter_copied", since = "1.36.0")]
212impl<'a, I, T: 'a> FusedIterator for Copied<I>
213where
214 I: FusedIterator<Item = &'a T>,
215 T: Copy,
216{
217}
218
219#[doc(hidden)]
220#[unstable(feature = "trusted_random_access", issue = "none")]
221unsafe impl<I> TrustedRandomAccess for Copied<I> where I: TrustedRandomAccess {}
222
223#[doc(hidden)]
224#[unstable(feature = "trusted_random_access", issue = "none")]
225unsafe impl<I> TrustedRandomAccessNoCoerce for Copied<I>
226where
227 I: TrustedRandomAccessNoCoerce,
228{
229 const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
230}
231
232#[stable(feature = "iter_copied", since = "1.36.0")]
233unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
234where
235 I: TrustedLen<Item = &'a T>,
236 T: Copy,
237{
238}
239
240trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T>
241where
242 T: Copy,
243{
244 fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>;
245}
246
247impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I
248where
249 I: Iterator<Item = &'a T>,
250 T: Copy,
251{
252 default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
253 array::iter_next_chunk(&mut self.copied())
254 }
255}
256
257impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T>
258where
259 T: Copy,
260{
261 fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
262 let mut raw_array = [const { MaybeUninit::uninit() }; N];
263
264 let len = self.len();
265
266 if T::IS_ZST {
267 if len < N {
268 let _ = self.advance_by(len);
269 return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) });
271 }
272
273 let _ = self.advance_by(N);
274 return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) });
276 }
277
278 if len < N {
279 unsafe {
282 ptr::copy_nonoverlapping(
283 self.as_ref().as_ptr(),
284 raw_array.as_mut_ptr() as *mut T,
285 len,
286 );
287 let _ = self.advance_by(len);
288 return Err(array::IntoIter::new_unchecked(raw_array, 0..len));
289 }
290 }
291
292 unsafe {
295 ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N);
296 let _ = self.advance_by(N);
297 Ok(MaybeUninit::array_assume_init(raw_array))
298 }
299 }
300}
301
302#[stable(feature = "default_iters", since = "1.70.0")]
303impl<I: Default> Default for Copied<I> {
304 fn default() -> Self {
312 Self::new(Default::default())
313 }
314}
315
316#[unstable(issue = "none", feature = "inplace_iteration")]
317unsafe impl<I> SourceIter for Copied<I>
318where
319 I: SourceIter,
320{
321 type Source = I::Source;
322
323 #[inline]
324 unsafe fn as_inner(&mut self) -> &mut I::Source {
325 unsafe { SourceIter::as_inner(&mut self.it) }
327 }
328}
329
330#[unstable(issue = "none", feature = "inplace_iteration")]
331unsafe impl<I: InPlaceIterable> InPlaceIterable for Copied<I> {
332 const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
333 const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
334}