|
| 1 | +use nodrop::NoDrop; |
| 2 | +use std::cmp; |
| 3 | +use std::ptr; |
| 4 | +use super::{GenericArray, ArrayLength}; |
| 5 | + |
| 6 | +/// An iterator that moves out of a `GenericArray` |
| 7 | +pub struct GenericArrayIter<T, N: ArrayLength<T>> { |
| 8 | + // Invariants: index <= index_back <= N |
| 9 | + // Only values in array[index..index_back] are alive at any given time. |
| 10 | + // Values from array[..index] and array[index_back..] are already moved/dropped. |
| 11 | + array: NoDrop<GenericArray<T, N>>, |
| 12 | + index: usize, |
| 13 | + index_back: usize, |
| 14 | +} |
| 15 | + |
| 16 | +impl<T, N> IntoIterator for GenericArray<T, N> where N: ArrayLength<T> { |
| 17 | + type Item = T; |
| 18 | + type IntoIter = GenericArrayIter<T, N>; |
| 19 | + |
| 20 | + fn into_iter(self) -> Self::IntoIter { |
| 21 | + GenericArrayIter { |
| 22 | + array: NoDrop::new(self), |
| 23 | + index: 0, |
| 24 | + index_back: N::to_usize(), |
| 25 | + } |
| 26 | + } |
| 27 | +} |
| 28 | + |
| 29 | +impl<T, N> Drop for GenericArrayIter<T, N> where N: ArrayLength<T> { |
| 30 | + fn drop(&mut self) { |
| 31 | + // Drop values that are still alive. |
| 32 | + for p in &mut self.array[self.index..self.index_back] { |
| 33 | + unsafe { ptr::drop_in_place(p); } |
| 34 | + } |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +impl<T, N> Iterator for GenericArrayIter<T, N> where N: ArrayLength<T> { |
| 39 | + type Item = T; |
| 40 | + |
| 41 | + fn next(&mut self) -> Option<T> { |
| 42 | + if self.len() > 0 { |
| 43 | + unsafe { |
| 44 | + let p = self.array.get_unchecked(self.index); |
| 45 | + self.index += 1; |
| 46 | + Some(ptr::read(p)) |
| 47 | + } |
| 48 | + } else { |
| 49 | + None |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + fn size_hint(&self) -> (usize, Option<usize>) { |
| 54 | + let len = self.len(); |
| 55 | + (len, Some(len)) |
| 56 | + } |
| 57 | + |
| 58 | + fn count(self) -> usize { |
| 59 | + self.len() |
| 60 | + } |
| 61 | + |
| 62 | + fn nth(&mut self, n: usize) -> Option<T> { |
| 63 | + // First consume values prior to the nth. |
| 64 | + let ndrop = cmp::min(n, self.len()); |
| 65 | + for p in &mut self.array[self.index..self.index + ndrop] { |
| 66 | + self.index += 1; |
| 67 | + unsafe { ptr::drop_in_place(p); } |
| 68 | + } |
| 69 | + |
| 70 | + self.next() |
| 71 | + } |
| 72 | + |
| 73 | + fn last(mut self) -> Option<T> { |
| 74 | + // Note, everything else will correctly drop first as `self` leaves scope. |
| 75 | + self.next_back() |
| 76 | + } |
| 77 | +} |
| 78 | + |
| 79 | +impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N> where N: ArrayLength<T> { |
| 80 | + fn next_back(&mut self) -> Option<T> { |
| 81 | + if self.len() > 0 { |
| 82 | + self.index_back -= 1; |
| 83 | + unsafe { |
| 84 | + let p = self.array.get_unchecked(self.index_back); |
| 85 | + Some(ptr::read(p)) |
| 86 | + } |
| 87 | + } else { |
| 88 | + None |
| 89 | + } |
| 90 | + } |
| 91 | +} |
| 92 | + |
| 93 | +impl<T, N> ExactSizeIterator for GenericArrayIter<T, N> where N: ArrayLength<T> { |
| 94 | + fn len(&self) -> usize { |
| 95 | + self.index_back - self.index |
| 96 | + } |
| 97 | +} |
0 commit comments