generic_array/
iter.rs
1use super::{ArrayLength, GenericArray};
4use core::iter::FusedIterator;
5use core::mem::{MaybeUninit, ManuallyDrop};
6use core::{cmp, fmt, ptr, mem};
7
8pub struct GenericArrayIter<T, N: ArrayLength<T>> {
10 array: ManuallyDrop<GenericArray<T, N>>,
14 index: usize,
15 index_back: usize,
16}
17
18#[cfg(test)]
19mod 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
30impl<T, N> GenericArrayIter<T, N>
31where
32 N: ArrayLength<T>,
33{
34 #[inline]
36 pub fn as_slice(&self) -> &[T] {
37 &self.array.as_slice()[self.index..self.index_back]
38 }
39
40 #[inline]
42 pub fn as_mut_slice(&mut self) -> &mut [T] {
43 &mut self.array.as_mut_slice()[self.index..self.index_back]
44 }
45}
46
47impl<T, N> IntoIterator for GenericArray<T, N>
48where
49 N: ArrayLength<T>,
50{
51 type Item = T;
52 type IntoIter = GenericArrayIter<T, N>;
53
54 fn into_iter(self) -> Self::IntoIter {
55 GenericArrayIter {
56 array: ManuallyDrop::new(self),
57 index: 0,
58 index_back: N::USIZE,
59 }
60 }
61}
62
63impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>
65where
66 N: ArrayLength<T>,
67{
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 f.debug_tuple("GenericArrayIter")
70 .field(&self.as_slice())
71 .finish()
72 }
73}
74
75impl<T, N> Drop for GenericArrayIter<T, N>
76where
77 N: ArrayLength<T>,
78{
79 #[inline]
80 fn drop(&mut self) {
81 if mem::needs_drop::<T>() {
82 for p in self.as_mut_slice() {
84 unsafe {
85 ptr::drop_in_place(p);
86 }
87 }
88 }
89 }
90}
91
92impl<T: Clone, N> Clone for GenericArrayIter<T, N>
94where
95 N: ArrayLength<T>,
96{
97 fn clone(&self) -> Self {
98 unsafe {
101 let mut array: MaybeUninit<GenericArray<T, N>> = MaybeUninit::uninit();
102 let mut index_back = 0;
103
104 for (dst, src) in (&mut *array.as_mut_ptr()).iter_mut().zip(self.as_slice()) {
105 ptr::write(dst, src.clone());
106
107 index_back += 1;
108 }
109
110 GenericArrayIter {
111 array: ManuallyDrop::new(array.assume_init()),
112 index: 0,
113 index_back
114 }
115 }
116 }
117}
118
119impl<T, N> Iterator for GenericArrayIter<T, N>
120where
121 N: ArrayLength<T>,
122{
123 type Item = T;
124
125 #[inline]
126 fn next(&mut self) -> Option<T> {
127 if self.index < self.index_back {
128 let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };
129
130 self.index += 1;
131
132 p
133 } else {
134 None
135 }
136 }
137
138 fn fold<B, F>(mut self, init: B, mut f: F) -> B
139 where
140 F: FnMut(B, Self::Item) -> B,
141 {
142 let ret = unsafe {
143 let GenericArrayIter {
144 ref array,
145 ref mut index,
146 index_back,
147 } = self;
148
149 let remaining = &array[*index..index_back];
150
151 remaining.iter().fold(init, |acc, src| {
152 let value = ptr::read(src);
153
154 *index += 1;
155
156 f(acc, value)
157 })
158 };
159
160 drop(self);
162
163 ret
164 }
165
166 #[inline]
167 fn size_hint(&self) -> (usize, Option<usize>) {
168 let len = self.len();
169 (len, Some(len))
170 }
171
172 #[inline]
173 fn count(self) -> usize {
174 self.len()
175 }
176
177 fn nth(&mut self, n: usize) -> Option<T> {
178 let ndrop = cmp::min(n, self.len());
180
181 for p in &mut self.array[self.index..self.index + ndrop] {
182 self.index += 1;
183
184 unsafe {
185 ptr::drop_in_place(p);
186 }
187 }
188
189 self.next()
190 }
191
192 #[inline]
193 fn last(mut self) -> Option<T> {
194 self.next_back()
196 }
197}
198
199impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
200where
201 N: ArrayLength<T>,
202{
203 fn next_back(&mut self) -> Option<T> {
204 if self.index < self.index_back {
205 self.index_back -= 1;
206
207 unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }
208 } else {
209 None
210 }
211 }
212
213 fn rfold<B, F>(mut self, init: B, mut f: F) -> B
214 where
215 F: FnMut(B, Self::Item) -> B,
216 {
217 let ret = unsafe {
218 let GenericArrayIter {
219 ref array,
220 index,
221 ref mut index_back,
222 } = self;
223
224 let remaining = &array[index..*index_back];
225
226 remaining.iter().rfold(init, |acc, src| {
227 let value = ptr::read(src);
228
229 *index_back -= 1;
230
231 f(acc, value)
232 })
233 };
234
235 drop(self);
237
238 ret
239 }
240}
241
242impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
243where
244 N: ArrayLength<T>,
245{
246 fn len(&self) -> usize {
247 self.index_back - self.index
248 }
249}
250
251impl<T, N> FusedIterator for GenericArrayIter<T, N>
252where
253 N: ArrayLength<T>,
254{
255}
256
257