]>
Commit | Line | Data |
---|---|---|
1b1a35ee XL |
1 | //! `GenericArray` iterator implementation.\r |
2 | \r | |
3 | use super::{ArrayLength, GenericArray};\r | |
4 | use core::{cmp, ptr, fmt, mem};\r | |
5 | use core::mem::ManuallyDrop;\r | |
6 | \r | |
7 | /// An iterator that moves out of a `GenericArray`\r | |
8 | pub struct GenericArrayIter<T, N: ArrayLength<T>> {\r | |
9 | // Invariants: index <= index_back <= N\r | |
10 | // Only values in array[index..index_back] are alive at any given time.\r | |
11 | // Values from array[..index] and array[index_back..] are already moved/dropped.\r | |
12 | array: ManuallyDrop<GenericArray<T, N>>,\r | |
13 | index: usize,\r | |
14 | index_back: usize,\r | |
15 | }\r | |
16 | \r | |
17 | #[cfg(test)]\r | |
18 | mod test {\r | |
19 | use super::*;\r | |
20 | \r | |
21 | fn send<I: Send>(_iter: I) {}\r | |
22 | \r | |
23 | #[test]\r | |
24 | fn test_send_iter() {\r | |
25 | send(GenericArray::from([1, 2, 3, 4]).into_iter());\r | |
26 | }\r | |
27 | }\r | |
28 | \r | |
29 | impl<T, N> GenericArrayIter<T, N>\r | |
30 | where\r | |
31 | N: ArrayLength<T>,\r | |
32 | {\r | |
33 | /// Returns the remaining items of this iterator as a slice\r | |
34 | #[inline]\r | |
35 | pub fn as_slice(&self) -> &[T] {\r | |
36 | &self.array.as_slice()[self.index..self.index_back]\r | |
37 | }\r | |
38 | \r | |
39 | /// Returns the remaining items of this iterator as a mutable slice\r | |
40 | #[inline]\r | |
41 | pub fn as_mut_slice(&mut self) -> &mut [T] {\r | |
42 | &mut self.array.as_mut_slice()[self.index..self.index_back]\r | |
43 | }\r | |
44 | }\r | |
45 | \r | |
46 | impl<T, N> IntoIterator for GenericArray<T, N>\r | |
47 | where\r | |
48 | N: ArrayLength<T>,\r | |
49 | {\r | |
50 | type Item = T;\r | |
51 | type IntoIter = GenericArrayIter<T, N>;\r | |
52 | \r | |
53 | fn into_iter(self) -> Self::IntoIter {\r | |
54 | GenericArrayIter {\r | |
55 | array: ManuallyDrop::new(self),\r | |
56 | index: 0,\r | |
57 | index_back: N::to_usize(),\r | |
58 | }\r | |
59 | }\r | |
60 | }\r | |
61 | \r | |
62 | // Based on work in rust-lang/rust#49000\r | |
63 | impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>\r | |
64 | where\r | |
65 | N: ArrayLength<T>,\r | |
66 | {\r | |
67 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\r | |
68 | f.debug_tuple("GenericArrayIter")\r | |
69 | .field(&self.as_slice())\r | |
70 | .finish()\r | |
71 | }\r | |
72 | }\r | |
73 | \r | |
74 | impl<T, N> Drop for GenericArrayIter<T, N>\r | |
75 | where\r | |
76 | N: ArrayLength<T>,\r | |
77 | {\r | |
78 | #[inline]\r | |
79 | fn drop(&mut self) {\r | |
80 | // Drop values that are still alive.\r | |
81 | for p in self.as_mut_slice() {\r | |
82 | unsafe {\r | |
83 | ptr::drop_in_place(p);\r | |
84 | }\r | |
85 | }\r | |
86 | }\r | |
87 | }\r | |
88 | \r | |
89 | // Based on work in rust-lang/rust#49000\r | |
90 | impl<T: Clone, N> Clone for GenericArrayIter<T, N>\r | |
91 | where\r | |
92 | N: ArrayLength<T>,\r | |
93 | {\r | |
94 | fn clone(&self) -> Self {\r | |
95 | // This places all cloned elements at the start of the new array iterator,\r | |
96 | // not at their original indices.\r | |
97 | unsafe {\r | |
98 | let mut iter = GenericArrayIter {\r | |
99 | array: ManuallyDrop::new(mem::uninitialized()),\r | |
100 | index: 0,\r | |
101 | index_back: 0,\r | |
102 | };\r | |
103 | \r | |
104 | for (dst, src) in iter.array.iter_mut().zip(self.as_slice()) {\r | |
105 | ptr::write(dst, src.clone());\r | |
106 | \r | |
107 | iter.index_back += 1;\r | |
108 | }\r | |
109 | \r | |
110 | iter\r | |
111 | }\r | |
112 | }\r | |
113 | }\r | |
114 | \r | |
115 | impl<T, N> Iterator for GenericArrayIter<T, N>\r | |
116 | where\r | |
117 | N: ArrayLength<T>,\r | |
118 | {\r | |
119 | type Item = T;\r | |
120 | \r | |
121 | #[inline]\r | |
122 | fn next(&mut self) -> Option<T> {\r | |
123 | if self.index < self.index_back {\r | |
124 | let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };\r | |
125 | \r | |
126 | self.index += 1;\r | |
127 | \r | |
128 | p\r | |
129 | } else {\r | |
130 | None\r | |
131 | }\r | |
132 | }\r | |
133 | \r | |
134 | #[inline]\r | |
135 | fn size_hint(&self) -> (usize, Option<usize>) {\r | |
136 | let len = self.len();\r | |
137 | (len, Some(len))\r | |
138 | }\r | |
139 | \r | |
140 | #[inline]\r | |
141 | fn count(self) -> usize {\r | |
142 | self.len()\r | |
143 | }\r | |
144 | \r | |
145 | fn nth(&mut self, n: usize) -> Option<T> {\r | |
146 | // First consume values prior to the nth.\r | |
147 | let ndrop = cmp::min(n, self.len());\r | |
148 | \r | |
149 | for p in &mut self.array[self.index..self.index + ndrop] {\r | |
150 | self.index += 1;\r | |
151 | \r | |
152 | unsafe {\r | |
153 | ptr::drop_in_place(p);\r | |
154 | }\r | |
155 | }\r | |
156 | \r | |
157 | self.next()\r | |
158 | }\r | |
159 | \r | |
160 | fn last(mut self) -> Option<T> {\r | |
161 | // Note, everything else will correctly drop first as `self` leaves scope.\r | |
162 | self.next_back()\r | |
163 | }\r | |
164 | }\r | |
165 | \r | |
166 | impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>\r | |
167 | where\r | |
168 | N: ArrayLength<T>,\r | |
169 | {\r | |
170 | fn next_back(&mut self) -> Option<T> {\r | |
171 | if self.index < self.index_back {\r | |
172 | self.index_back -= 1;\r | |
173 | \r | |
174 | unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }\r | |
175 | } else {\r | |
176 | None\r | |
177 | }\r | |
178 | }\r | |
179 | }\r | |
180 | \r | |
181 | impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>\r | |
182 | where\r | |
183 | N: ArrayLength<T>,\r | |
184 | {\r | |
185 | fn len(&self) -> usize {\r | |
186 | self.index_back - self.index\r | |
187 | }\r | |
188 | }\r | |
189 | \r | |
190 | // TODO: Implement `FusedIterator` and `TrustedLen` when stabilized |