1#[cfg(not(feature = "ferrocene_subset"))]
2use crate::iter::adapters::zip::try_get_unchecked;
3#[cfg(not(feature = "ferrocene_subset"))]
4use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
5#[cfg(not(feature = "ferrocene_subset"))]
6use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
7#[cfg(not(feature = "ferrocene_subset"))]
8use crate::mem::{MaybeUninit, SizedTypeProperties};
9use crate::num::NonZero;
10use crate::ops::Try;
11#[cfg(not(feature = "ferrocene_subset"))]
12use crate::{array, ptr};
13
14#[stable(feature = "iter_copied", since = "1.36.0")]
22#[must_use = "iterators are lazy and do nothing unless consumed"]
23#[cfg_attr(not(feature = "ferrocene_subset"), derive(Clone, Debug))]
24pub struct Copied<I> {
25 it: I,
26}
27
28impl<I> Copied<I> {
29 pub(in crate::iter) fn new(it: I) -> Copied<I> {
30 Copied { it }
31 }
32
33 #[cfg(not(feature = "ferrocene_subset"))]
34 #[doc(hidden)]
35 #[unstable(feature = "copied_into_inner", issue = "none")]
36 pub fn into_inner(self) -> I {
37 self.it
38 }
39}
40
41fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc {
42 move |acc, &elt| f(acc, elt)
43}
44
45fn copy_try_fold<T: Copy, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
46 move |acc, &elt| f(acc, elt)
47}
48
49#[stable(feature = "iter_copied", since = "1.36.0")]
50impl<'a, I, T: 'a> Iterator for Copied<I>
51where
52 I: Iterator<Item = &'a T>,
53 T: Copy,
54{
55 type Item = T;
56
57 fn next(&mut self) -> Option<T> {
58 self.it.next().copied()
59 }
60
61 #[cfg(not(feature = "ferrocene_subset"))]
62 fn next_chunk<const N: usize>(
63 &mut self,
64 ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
65 where
66 Self: Sized,
67 {
68 <I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
69 }
70
71 fn size_hint(&self) -> (usize, Option<usize>) {
72 self.it.size_hint()
73 }
74
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 fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
85 where
86 F: FnMut(Acc, Self::Item) -> Acc,
87 {
88 self.it.fold(init, copy_fold(f))
89 }
90
91 fn nth(&mut self, n: usize) -> Option<T> {
92 self.it.nth(n).copied()
93 }
94
95 fn last(self) -> Option<T> {
96 self.it.last().copied()
97 }
98
99 #[cfg(not(feature = "ferrocene_subset"))]
100 fn count(self) -> usize {
101 self.it.count()
102 }
103
104 #[inline]
105 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
106 self.it.advance_by(n)
107 }
108
109 #[cfg(not(feature = "ferrocene_subset"))]
110 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
111 where
112 Self: TrustedRandomAccessNoCoerce,
113 {
114 *unsafe { try_get_unchecked(&mut self.it, idx) }
117 }
118}
119
120#[cfg(not(feature = "ferrocene_subset"))]
121#[stable(feature = "iter_copied", since = "1.36.0")]
122impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
123where
124 I: DoubleEndedIterator<Item = &'a T>,
125 T: Copy,
126{
127 fn next_back(&mut self) -> Option<T> {
128 self.it.next_back().copied()
129 }
130
131 fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
132 where
133 Self: Sized,
134 F: FnMut(B, Self::Item) -> R,
135 R: Try<Output = B>,
136 {
137 self.it.try_rfold(init, copy_try_fold(f))
138 }
139
140 fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
141 where
142 F: FnMut(Acc, Self::Item) -> Acc,
143 {
144 self.it.rfold(init, copy_fold(f))
145 }
146
147 #[inline]
148 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
149 self.it.advance_back_by(n)
150 }
151}
152
153#[cfg(not(feature = "ferrocene_subset"))]
154#[stable(feature = "iter_copied", since = "1.36.0")]
155impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
156where
157 I: ExactSizeIterator<Item = &'a T>,
158 T: Copy,
159{
160 fn len(&self) -> usize {
161 self.it.len()
162 }
163
164 fn is_empty(&self) -> bool {
165 self.it.is_empty()
166 }
167}
168
169#[cfg(not(feature = "ferrocene_subset"))]
170#[stable(feature = "iter_copied", since = "1.36.0")]
171impl<'a, I, T: 'a> FusedIterator for Copied<I>
172where
173 I: FusedIterator<Item = &'a T>,
174 T: Copy,
175{
176}
177
178#[cfg(not(feature = "ferrocene_subset"))]
179#[doc(hidden)]
180#[unstable(feature = "trusted_random_access", issue = "none")]
181unsafe impl<I> TrustedRandomAccess for Copied<I> where I: TrustedRandomAccess {}
182
183#[cfg(not(feature = "ferrocene_subset"))]
184#[doc(hidden)]
185#[unstable(feature = "trusted_random_access", issue = "none")]
186unsafe impl<I> TrustedRandomAccessNoCoerce for Copied<I>
187where
188 I: TrustedRandomAccessNoCoerce,
189{
190 const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
191}
192
193#[cfg(not(feature = "ferrocene_subset"))]
194#[stable(feature = "iter_copied", since = "1.36.0")]
195unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
196where
197 I: TrustedLen<Item = &'a T>,
198 T: Copy,
199{
200}
201
202#[cfg(not(feature = "ferrocene_subset"))]
203trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T>
204where
205 T: Copy,
206{
207 fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>;
208}
209
210#[cfg(not(feature = "ferrocene_subset"))]
211impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I
212where
213 I: Iterator<Item = &'a T>,
214 T: Copy,
215{
216 default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
217 array::iter_next_chunk(&mut self.copied())
218 }
219}
220
221#[cfg(not(feature = "ferrocene_subset"))]
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#[cfg(not(feature = "ferrocene_subset"))]
268#[stable(feature = "default_iters", since = "1.70.0")]
269impl<I: Default> Default for Copied<I> {
270 fn default() -> Self {
278 Self::new(Default::default())
279 }
280}
281
282#[cfg(not(feature = "ferrocene_subset"))]
283#[unstable(issue = "none", feature = "inplace_iteration")]
284unsafe impl<I> SourceIter for Copied<I>
285where
286 I: SourceIter,
287{
288 type Source = I::Source;
289
290 #[inline]
291 unsafe fn as_inner(&mut self) -> &mut I::Source {
292 unsafe { SourceIter::as_inner(&mut self.it) }
294 }
295}
296
297#[cfg(not(feature = "ferrocene_subset"))]
298#[unstable(issue = "none", feature = "inplace_iteration")]
299unsafe impl<I: InPlaceIterable> InPlaceIterable for Copied<I> {
300 const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
301 const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
302}