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