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