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