]> git.proxmox.com Git - rustc.git/blame - vendor/generic-array-0.12.3/src/iter.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / vendor / generic-array-0.12.3 / src / iter.rs
CommitLineData
1b1a35ee
XL
1//! `GenericArray` iterator implementation.\r
2\r
3use super::{ArrayLength, GenericArray};\r
4use core::{cmp, ptr, fmt, mem};\r
5use core::mem::ManuallyDrop;\r
6\r
7/// An iterator that moves out of a `GenericArray`\r
8pub 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
18mod 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
29impl<T, N> GenericArrayIter<T, N>\r
30where\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
46impl<T, N> IntoIterator for GenericArray<T, N>\r
47where\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
63impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>\r
64where\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
74impl<T, N> Drop for GenericArrayIter<T, N>\r
75where\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
90impl<T: Clone, N> Clone for GenericArrayIter<T, N>\r
91where\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
115impl<T, N> Iterator for GenericArrayIter<T, N>\r
116where\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
166impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>\r
167where\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
181impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>\r
182where\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