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#[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 fn count(self) -> usize {
100 self.it.count()
101 }
102
103 #[inline]
104 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
105 self.it.advance_by(n)
106 }
107
108 #[cfg(not(feature = "ferrocene_subset"))]
109 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
110 where
111 Self: TrustedRandomAccessNoCoerce,
112 {
113 *unsafe { try_get_unchecked(&mut self.it, idx) }
116 }
117}
118
119#[stable(feature = "iter_copied", since = "1.36.0")]
120impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
121where
122 I: DoubleEndedIterator<Item = &'a T>,
123 T: Copy,
124{
125 fn next_back(&mut self) -> Option<T> {
126 self.it.next_back().copied()
127 }
128
129 fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
130 where
131 Self: Sized,
132 F: FnMut(B, Self::Item) -> R,
133 R: Try<Output = B>,
134 {
135 self.it.try_rfold(init, copy_try_fold(f))
136 }
137
138 fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
139 where
140 F: FnMut(Acc, Self::Item) -> Acc,
141 {
142 self.it.rfold(init, copy_fold(f))
143 }
144
145 #[inline]
146 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
147 self.it.advance_back_by(n)
148 }
149}
150
151#[stable(feature = "iter_copied", since = "1.36.0")]
152impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
153where
154 I: ExactSizeIterator<Item = &'a T>,
155 T: Copy,
156{
157 fn len(&self) -> usize {
158 self.it.len()
159 }
160
161 fn is_empty(&self) -> bool {
162 self.it.is_empty()
163 }
164}
165
166#[cfg(not(feature = "ferrocene_subset"))]
167#[stable(feature = "iter_copied", since = "1.36.0")]
168impl<'a, I, T: 'a> FusedIterator for Copied<I>
169where
170 I: FusedIterator<Item = &'a T>,
171 T: Copy,
172{
173}
174
175#[cfg(not(feature = "ferrocene_subset"))]
176#[doc(hidden)]
177#[unstable(feature = "trusted_random_access", issue = "none")]
178unsafe impl<I> TrustedRandomAccess for Copied<I> where I: TrustedRandomAccess {}
179
180#[cfg(not(feature = "ferrocene_subset"))]
181#[doc(hidden)]
182#[unstable(feature = "trusted_random_access", issue = "none")]
183unsafe impl<I> TrustedRandomAccessNoCoerce for Copied<I>
184where
185 I: TrustedRandomAccessNoCoerce,
186{
187 const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
188}
189
190#[cfg(not(feature = "ferrocene_subset"))]
191#[stable(feature = "iter_copied", since = "1.36.0")]
192unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
193where
194 I: TrustedLen<Item = &'a T>,
195 T: Copy,
196{
197}
198
199#[cfg(not(feature = "ferrocene_subset"))]
200trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T>
201where
202 T: Copy,
203{
204 fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>;
205}
206
207#[cfg(not(feature = "ferrocene_subset"))]
208impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I
209where
210 I: Iterator<Item = &'a T>,
211 T: Copy,
212{
213 default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
214 array::iter_next_chunk(&mut self.copied())
215 }
216}
217
218#[cfg(not(feature = "ferrocene_subset"))]
219impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T>
220where
221 T: Copy,
222{
223 fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
224 let mut raw_array = [const { MaybeUninit::uninit() }; N];
225
226 let len = self.len();
227
228 if T::IS_ZST {
229 if len < N {
230 let _ = self.advance_by(len);
231 return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) });
233 }
234
235 let _ = self.advance_by(N);
236 return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) });
238 }
239
240 if len < N {
241 unsafe {
244 ptr::copy_nonoverlapping(
245 self.as_ref().as_ptr(),
246 raw_array.as_mut_ptr() as *mut T,
247 len,
248 );
249 let _ = self.advance_by(len);
250 return Err(array::IntoIter::new_unchecked(raw_array, 0..len));
251 }
252 }
253
254 unsafe {
257 ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N);
258 let _ = self.advance_by(N);
259 Ok(MaybeUninit::array_assume_init(raw_array))
260 }
261 }
262}
263
264#[cfg(not(feature = "ferrocene_subset"))]
265#[stable(feature = "default_iters", since = "1.70.0")]
266impl<I: Default> Default for Copied<I> {
267 fn default() -> Self {
275 Self::new(Default::default())
276 }
277}
278
279#[cfg(not(feature = "ferrocene_subset"))]
280#[unstable(issue = "none", feature = "inplace_iteration")]
281unsafe impl<I> SourceIter for Copied<I>
282where
283 I: SourceIter,
284{
285 type Source = I::Source;
286
287 #[inline]
288 unsafe fn as_inner(&mut self) -> &mut I::Source {
289 unsafe { SourceIter::as_inner(&mut self.it) }
291 }
292}
293
294#[cfg(not(feature = "ferrocene_subset"))]
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}