1 | use crate::iter::adapters::zip::try_get_unchecked; |
2 | use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; |
3 | use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; |
4 | use crate::mem::{MaybeUninit, SizedTypeProperties}; |
5 | use crate::num::NonZero; |
6 | use crate::ops::Try; |
7 | use crate::{array, ptr}; |
8 | |
9 | /// An iterator that copies the elements of an underlying iterator. |
10 | /// |
11 | /// This `struct` is created by the [`copied`] method on [`Iterator`]. See its |
12 | /// documentation for more. |
13 | /// |
14 | /// [`copied`]: Iterator::copied |
15 | /// [`Iterator`]: trait.Iterator.html |
16 | #[stable (feature = "iter_copied" , since = "1.36.0" )] |
17 | #[must_use = "iterators are lazy and do nothing unless consumed" ] |
18 | #[derive (Clone, Debug)] |
19 | pub struct Copied<I> { |
20 | it: I, |
21 | } |
22 | |
23 | impl<I> Copied<I> { |
24 | pub(in crate::iter) fn new(it: I) -> Copied<I> { |
25 | Copied { it } |
26 | } |
27 | } |
28 | |
29 | fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc { |
30 | move |acc: Acc, &elt: T| f(acc, elt) |
31 | } |
32 | |
33 | fn copy_try_fold<T: Copy, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R { |
34 | move |acc: Acc, &elt: T| f(acc, elt) |
35 | } |
36 | |
37 | #[stable (feature = "iter_copied" , since = "1.36.0" )] |
38 | impl<'a, I, T: 'a> Iterator for Copied<I> |
39 | where |
40 | I: Iterator<Item = &'a T>, |
41 | T: Copy, |
42 | { |
43 | type Item = T; |
44 | |
45 | fn next(&mut self) -> Option<T> { |
46 | self.it.next().copied() |
47 | } |
48 | |
49 | fn next_chunk<const N: usize>( |
50 | &mut self, |
51 | ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> |
52 | where |
53 | Self: Sized, |
54 | { |
55 | <I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it) |
56 | } |
57 | |
58 | fn size_hint(&self) -> (usize, Option<usize>) { |
59 | self.it.size_hint() |
60 | } |
61 | |
62 | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R |
63 | where |
64 | Self: Sized, |
65 | F: FnMut(B, Self::Item) -> R, |
66 | R: Try<Output = B>, |
67 | { |
68 | self.it.try_fold(init, copy_try_fold(f)) |
69 | } |
70 | |
71 | fn fold<Acc, F>(self, init: Acc, f: F) -> Acc |
72 | where |
73 | F: FnMut(Acc, Self::Item) -> Acc, |
74 | { |
75 | self.it.fold(init, copy_fold(f)) |
76 | } |
77 | |
78 | fn nth(&mut self, n: usize) -> Option<T> { |
79 | self.it.nth(n).copied() |
80 | } |
81 | |
82 | fn last(self) -> Option<T> { |
83 | self.it.last().copied() |
84 | } |
85 | |
86 | fn count(self) -> usize { |
87 | self.it.count() |
88 | } |
89 | |
90 | #[inline ] |
91 | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { |
92 | self.it.advance_by(n) |
93 | } |
94 | |
95 | unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T |
96 | where |
97 | Self: TrustedRandomAccessNoCoerce, |
98 | { |
99 | // SAFETY: the caller must uphold the contract for |
100 | // `Iterator::__iterator_get_unchecked`. |
101 | *unsafe { try_get_unchecked(&mut self.it, idx) } |
102 | } |
103 | } |
104 | |
105 | #[stable (feature = "iter_copied" , since = "1.36.0" )] |
106 | impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I> |
107 | where |
108 | I: DoubleEndedIterator<Item = &'a T>, |
109 | T: Copy, |
110 | { |
111 | fn next_back(&mut self) -> Option<T> { |
112 | self.it.next_back().copied() |
113 | } |
114 | |
115 | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R |
116 | where |
117 | Self: Sized, |
118 | F: FnMut(B, Self::Item) -> R, |
119 | R: Try<Output = B>, |
120 | { |
121 | self.it.try_rfold(init, copy_try_fold(f)) |
122 | } |
123 | |
124 | fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc |
125 | where |
126 | F: FnMut(Acc, Self::Item) -> Acc, |
127 | { |
128 | self.it.rfold(init, copy_fold(f)) |
129 | } |
130 | |
131 | #[inline ] |
132 | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { |
133 | self.it.advance_back_by(n) |
134 | } |
135 | } |
136 | |
137 | #[stable (feature = "iter_copied" , since = "1.36.0" )] |
138 | impl<'a, I, T: 'a> ExactSizeIterator for Copied<I> |
139 | where |
140 | I: ExactSizeIterator<Item = &'a T>, |
141 | T: Copy, |
142 | { |
143 | fn len(&self) -> usize { |
144 | self.it.len() |
145 | } |
146 | |
147 | fn is_empty(&self) -> bool { |
148 | self.it.is_empty() |
149 | } |
150 | } |
151 | |
152 | #[stable (feature = "iter_copied" , since = "1.36.0" )] |
153 | impl<'a, I, T: 'a> FusedIterator for Copied<I> |
154 | where |
155 | I: FusedIterator<Item = &'a T>, |
156 | T: Copy, |
157 | { |
158 | } |
159 | |
160 | #[doc (hidden)] |
161 | #[unstable (feature = "trusted_random_access" , issue = "none" )] |
162 | unsafe impl<I> TrustedRandomAccess for Copied<I> where I: TrustedRandomAccess {} |
163 | |
164 | #[doc (hidden)] |
165 | #[unstable (feature = "trusted_random_access" , issue = "none" )] |
166 | unsafe impl<I> TrustedRandomAccessNoCoerce for Copied<I> |
167 | where |
168 | I: TrustedRandomAccessNoCoerce, |
169 | { |
170 | const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT; |
171 | } |
172 | |
173 | #[stable (feature = "iter_copied" , since = "1.36.0" )] |
174 | unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I> |
175 | where |
176 | I: TrustedLen<Item = &'a T>, |
177 | T: Copy, |
178 | { |
179 | } |
180 | |
181 | trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T> |
182 | where |
183 | T: Copy, |
184 | { |
185 | fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>; |
186 | } |
187 | |
188 | impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I |
189 | where |
190 | I: Iterator<Item = &'a T>, |
191 | T: Copy, |
192 | { |
193 | default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> { |
194 | array::iter_next_chunk(&mut self.copied()) |
195 | } |
196 | } |
197 | |
198 | impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T> |
199 | where |
200 | T: Copy, |
201 | { |
202 | fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> { |
203 | let mut raw_array = [const { MaybeUninit::uninit() }; N]; |
204 | |
205 | let len = self.len(); |
206 | |
207 | if T::IS_ZST { |
208 | if len < N { |
209 | let _ = self.advance_by(len); |
210 | // SAFETY: ZSTs can be conjured ex nihilo; only the amount has to be correct |
211 | return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) }); |
212 | } |
213 | |
214 | let _ = self.advance_by(N); |
215 | // SAFETY: ditto |
216 | return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) }); |
217 | } |
218 | |
219 | if len < N { |
220 | // SAFETY: `len` indicates that this many elements are available and we just checked that |
221 | // it fits into the array. |
222 | unsafe { |
223 | ptr::copy_nonoverlapping( |
224 | self.as_ref().as_ptr(), |
225 | raw_array.as_mut_ptr() as *mut T, |
226 | len, |
227 | ); |
228 | let _ = self.advance_by(len); |
229 | return Err(array::IntoIter::new_unchecked(raw_array, 0..len)); |
230 | } |
231 | } |
232 | |
233 | // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize |
234 | // the array. |
235 | unsafe { |
236 | ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N); |
237 | let _ = self.advance_by(N); |
238 | Ok(MaybeUninit::array_assume_init(raw_array)) |
239 | } |
240 | } |
241 | } |
242 | |
243 | #[stable (feature = "default_iters" , since = "1.70.0" )] |
244 | impl<I: Default> Default for Copied<I> { |
245 | /// Creates a `Copied` iterator from the default value of `I` |
246 | /// ``` |
247 | /// # use core::slice; |
248 | /// # use core::iter::Copied; |
249 | /// let iter: Copied<slice::Iter<'_, u8>> = Default::default(); |
250 | /// assert_eq!(iter.len(), 0); |
251 | /// ``` |
252 | fn default() -> Self { |
253 | Self::new(it:Default::default()) |
254 | } |
255 | } |
256 | |
257 | #[unstable (issue = "none" , feature = "inplace_iteration" )] |
258 | unsafe impl<I> SourceIter for Copied<I> |
259 | where |
260 | I: SourceIter, |
261 | { |
262 | type Source = I::Source; |
263 | |
264 | #[inline ] |
265 | unsafe fn as_inner(&mut self) -> &mut I::Source { |
266 | // SAFETY: unsafe function forwarding to unsafe function with the same requirements |
267 | unsafe { SourceIter::as_inner(&mut self.it) } |
268 | } |
269 | } |
270 | |
271 | #[unstable (issue = "none" , feature = "inplace_iteration" )] |
272 | unsafe impl<I: InPlaceIterable> InPlaceIterable for Copied<I> { |
273 | const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY; |
274 | const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY; |
275 | } |
276 | |