1 //! `GenericArray` iterator implementation. 2 3 use super::{ArrayLength, GenericArray}; 4 use core::iter::FusedIterator; 5 use core::mem::{MaybeUninit, ManuallyDrop}; 6 use core::{cmp, fmt, ptr, mem}; 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 send<I: Send>(_iter: I)22 fn send<I: Send>(_iter: I) {} 23 24 #[test] test_send_iter()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] as_slice(&self) -> &[T]36 pub fn as_slice(&self) -> &[T] { 37 &self.array.as_slice()[self.index..self.index_back] 38 } 39 40 /// Returns the remaining items of this iterator as a mutable slice 41 #[inline] as_mut_slice(&mut self) -> &mut [T]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 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 into_iter(self) -> Self::IntoIter54 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 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 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 69 f.debug_tuple("GenericArrayIter") 70 .field(&self.as_slice()) 71 .finish() 72 } 73 } 74 75 impl<T, N> Drop for GenericArrayIter<T, N> 76 where 77 N: ArrayLength<T>, 78 { 79 #[inline] drop(&mut self)80 fn drop(&mut self) { 81 if mem::needs_drop::<T>() { 82 // Drop values that are still alive. 83 for p in self.as_mut_slice() { 84 unsafe { 85 ptr::drop_in_place(p); 86 } 87 } 88 } 89 } 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 { clone(&self) -> Self97 fn clone(&self) -> Self { 98 // This places all cloned elements at the start of the new array iterator, 99 // not at their original indices. 100 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 119 impl<T, N> Iterator for GenericArrayIter<T, N> 120 where 121 N: ArrayLength<T>, 122 { 123 type Item = T; 124 125 #[inline] next(&mut self) -> Option<T>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 fold<B, F>(mut self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B,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 // ensure the drop happens here after iteration 161 drop(self); 162 163 ret 164 } 165 166 #[inline] size_hint(&self) -> (usize, Option<usize>)167 fn size_hint(&self) -> (usize, Option<usize>) { 168 let len = self.len(); 169 (len, Some(len)) 170 } 171 172 #[inline] count(self) -> usize173 fn count(self) -> usize { 174 self.len() 175 } 176 nth(&mut self, n: usize) -> Option<T>177 fn nth(&mut self, n: usize) -> Option<T> { 178 // First consume values prior to the nth. 179 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] last(mut self) -> Option<T>193 fn last(mut self) -> Option<T> { 194 // Note, everything else will correctly drop first as `self` leaves scope. 195 self.next_back() 196 } 197 } 198 199 impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N> 200 where 201 N: ArrayLength<T>, 202 { next_back(&mut self) -> Option<T>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 rfold<B, F>(mut self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B,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 // ensure the drop happens here after iteration 236 drop(self); 237 238 ret 239 } 240 } 241 242 impl<T, N> ExactSizeIterator for GenericArrayIter<T, N> 243 where 244 N: ArrayLength<T>, 245 { len(&self) -> usize246 fn len(&self) -> usize { 247 self.index_back - self.index 248 } 249 } 250 251 impl<T, N> FusedIterator for GenericArrayIter<T, N> 252 where 253 N: ArrayLength<T>, 254 { 255 } 256 257 // TODO: Implement `TrustedLen` when stabilized 258