/rust/registry/src/index.crates.io-6f17d22bba15001f/generic-array-0.14.7/src/iter.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! `GenericArray` iterator implementation. |
2 | | |
3 | | use super::{ArrayLength, GenericArray}; |
4 | | use core::iter::FusedIterator; |
5 | | use core::mem::ManuallyDrop; |
6 | | use core::{cmp, fmt, mem, ptr}; |
7 | | |
8 | | /// An iterator that moves out of a `GenericArray` |
9 | | pub struct GenericArrayIter<T, N: ArrayLength<T>> { |
10 | | // Invariants: index <= index_back <= N |
11 | | // Only values in array[index..index_back] are alive at any given time. |
12 | | // Values from array[..index] and array[index_back..] are already moved/dropped. |
13 | | array: ManuallyDrop<GenericArray<T, N>>, |
14 | | index: usize, |
15 | | index_back: usize, |
16 | | } |
17 | | |
18 | | #[cfg(test)] |
19 | | mod test { |
20 | | use super::*; |
21 | | |
22 | | fn send<I: Send>(_iter: I) {} |
23 | | |
24 | | #[test] |
25 | | fn test_send_iter() { |
26 | | send(GenericArray::from([1, 2, 3, 4]).into_iter()); |
27 | | } |
28 | | } |
29 | | |
30 | | impl<T, N> GenericArrayIter<T, N> |
31 | | where |
32 | | N: ArrayLength<T>, |
33 | | { |
34 | | /// Returns the remaining items of this iterator as a slice |
35 | | #[inline] |
36 | 0 | pub fn as_slice(&self) -> &[T] { |
37 | 0 | &self.array.as_slice()[self.index..self.index_back] |
38 | 0 | } |
39 | | |
40 | | /// Returns the remaining items of this iterator as a mutable slice |
41 | | #[inline] |
42 | 0 | pub fn as_mut_slice(&mut self) -> &mut [T] { |
43 | 0 | &mut self.array.as_mut_slice()[self.index..self.index_back] |
44 | 0 | } |
45 | | } |
46 | | |
47 | | impl<T, N> IntoIterator for GenericArray<T, N> |
48 | | where |
49 | | N: ArrayLength<T>, |
50 | | { |
51 | | type Item = T; |
52 | | type IntoIter = GenericArrayIter<T, N>; |
53 | | |
54 | 0 | fn into_iter(self) -> Self::IntoIter { |
55 | 0 | GenericArrayIter { |
56 | 0 | array: ManuallyDrop::new(self), |
57 | 0 | index: 0, |
58 | 0 | index_back: N::USIZE, |
59 | 0 | } |
60 | 0 | } |
61 | | } |
62 | | |
63 | | // Based on work in rust-lang/rust#49000 |
64 | | impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N> |
65 | | where |
66 | | N: ArrayLength<T>, |
67 | | { |
68 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
69 | 0 | f.debug_tuple("GenericArrayIter") |
70 | 0 | .field(&self.as_slice()) |
71 | 0 | .finish() |
72 | 0 | } |
73 | | } |
74 | | |
75 | | impl<T, N> Drop for GenericArrayIter<T, N> |
76 | | where |
77 | | N: ArrayLength<T>, |
78 | | { |
79 | | #[inline] |
80 | 0 | fn drop(&mut self) { |
81 | 0 | if mem::needs_drop::<T>() { |
82 | | // Drop values that are still alive. |
83 | 0 | for p in self.as_mut_slice() { |
84 | 0 | unsafe { |
85 | 0 | ptr::drop_in_place(p); |
86 | 0 | } |
87 | | } |
88 | 0 | } |
89 | 0 | } |
90 | | } |
91 | | |
92 | | // Based on work in rust-lang/rust#49000 |
93 | | impl<T: Clone, N> Clone for GenericArrayIter<T, N> |
94 | | where |
95 | | N: ArrayLength<T>, |
96 | | { |
97 | 0 | fn clone(&self) -> Self { |
98 | 0 | // This places all cloned elements at the start of the new array iterator, |
99 | 0 | // not at their original indices. |
100 | 0 |
|
101 | 0 | let mut array = unsafe { ptr::read(&self.array) }; |
102 | 0 | let mut index_back = 0; |
103 | | |
104 | 0 | for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) { |
105 | 0 | unsafe { ptr::write(dst, src.clone()) }; |
106 | 0 | index_back += 1; |
107 | 0 | } |
108 | | |
109 | 0 | GenericArrayIter { |
110 | 0 | array, |
111 | 0 | index: 0, |
112 | 0 | index_back, |
113 | 0 | } |
114 | 0 | } |
115 | | } |
116 | | |
117 | | impl<T, N> Iterator for GenericArrayIter<T, N> |
118 | | where |
119 | | N: ArrayLength<T>, |
120 | | { |
121 | | type Item = T; |
122 | | |
123 | | #[inline] |
124 | 0 | fn next(&mut self) -> Option<T> { |
125 | 0 | if self.index < self.index_back { |
126 | 0 | let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) }; |
127 | 0 |
|
128 | 0 | self.index += 1; |
129 | 0 |
|
130 | 0 | p |
131 | | } else { |
132 | 0 | None |
133 | | } |
134 | 0 | } |
135 | | |
136 | 0 | fn fold<B, F>(mut self, init: B, mut f: F) -> B |
137 | 0 | where |
138 | 0 | F: FnMut(B, Self::Item) -> B, |
139 | 0 | { |
140 | 0 | let ret = unsafe { |
141 | 0 | let GenericArrayIter { |
142 | 0 | ref array, |
143 | 0 | ref mut index, |
144 | 0 | index_back, |
145 | 0 | } = self; |
146 | 0 |
|
147 | 0 | let remaining = &array[*index..index_back]; |
148 | 0 |
|
149 | 0 | remaining.iter().fold(init, |acc, src| { |
150 | 0 | let value = ptr::read(src); |
151 | 0 |
|
152 | 0 | *index += 1; |
153 | 0 |
|
154 | 0 | f(acc, value) |
155 | 0 | }) |
156 | 0 | }; |
157 | 0 |
|
158 | 0 | // ensure the drop happens here after iteration |
159 | 0 | drop(self); |
160 | 0 |
|
161 | 0 | ret |
162 | 0 | } |
163 | | |
164 | | #[inline] |
165 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
166 | 0 | let len = self.len(); |
167 | 0 | (len, Some(len)) |
168 | 0 | } |
169 | | |
170 | | #[inline] |
171 | 0 | fn count(self) -> usize { |
172 | 0 | self.len() |
173 | 0 | } |
174 | | |
175 | 0 | fn nth(&mut self, n: usize) -> Option<T> { |
176 | 0 | // First consume values prior to the nth. |
177 | 0 | let ndrop = cmp::min(n, self.len()); |
178 | | |
179 | 0 | for p in &mut self.array[self.index..self.index + ndrop] { |
180 | 0 | self.index += 1; |
181 | 0 |
|
182 | 0 | unsafe { |
183 | 0 | ptr::drop_in_place(p); |
184 | 0 | } |
185 | | } |
186 | | |
187 | 0 | self.next() |
188 | 0 | } |
189 | | |
190 | | #[inline] |
191 | 0 | fn last(mut self) -> Option<T> { |
192 | 0 | // Note, everything else will correctly drop first as `self` leaves scope. |
193 | 0 | self.next_back() |
194 | 0 | } |
195 | | } |
196 | | |
197 | | impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N> |
198 | | where |
199 | | N: ArrayLength<T>, |
200 | | { |
201 | 0 | fn next_back(&mut self) -> Option<T> { |
202 | 0 | if self.index < self.index_back { |
203 | 0 | self.index_back -= 1; |
204 | 0 |
|
205 | 0 | unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) } |
206 | | } else { |
207 | 0 | None |
208 | | } |
209 | 0 | } |
210 | | |
211 | 0 | fn rfold<B, F>(mut self, init: B, mut f: F) -> B |
212 | 0 | where |
213 | 0 | F: FnMut(B, Self::Item) -> B, |
214 | 0 | { |
215 | 0 | let ret = unsafe { |
216 | 0 | let GenericArrayIter { |
217 | 0 | ref array, |
218 | 0 | index, |
219 | 0 | ref mut index_back, |
220 | 0 | } = self; |
221 | 0 |
|
222 | 0 | let remaining = &array[index..*index_back]; |
223 | 0 |
|
224 | 0 | remaining.iter().rfold(init, |acc, src| { |
225 | 0 | let value = ptr::read(src); |
226 | 0 |
|
227 | 0 | *index_back -= 1; |
228 | 0 |
|
229 | 0 | f(acc, value) |
230 | 0 | }) |
231 | 0 | }; |
232 | 0 |
|
233 | 0 | // ensure the drop happens here after iteration |
234 | 0 | drop(self); |
235 | 0 |
|
236 | 0 | ret |
237 | 0 | } |
238 | | } |
239 | | |
240 | | impl<T, N> ExactSizeIterator for GenericArrayIter<T, N> |
241 | | where |
242 | | N: ArrayLength<T>, |
243 | | { |
244 | 0 | fn len(&self) -> usize { |
245 | 0 | self.index_back - self.index |
246 | 0 | } |
247 | | } |
248 | | |
249 | | impl<T, N> FusedIterator for GenericArrayIter<T, N> where N: ArrayLength<T> {} |
250 | | |
251 | | // TODO: Implement `TrustedLen` when stabilized |