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