1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use nodrop::NoDrop;
use std::cmp;
use std::ptr;
use super::{GenericArray, ArrayLength};

/// An iterator that moves out of a `GenericArray`
pub struct GenericArrayIter<T, N: ArrayLength<T>> {
    // Invariants: index <= index_back <= N
    // Only values in array[index..index_back] are alive at any given time.
    // Values from array[..index] and array[index_back..] are already moved/dropped.
    array: NoDrop<GenericArray<T, N>>,
    index: usize,
    index_back: usize,
}

impl<T, N> IntoIterator for GenericArray<T, N> where N: ArrayLength<T> {
    type Item = T;
    type IntoIter = GenericArrayIter<T, N>;

    fn into_iter(self) -> Self::IntoIter {
        GenericArrayIter {
            array: NoDrop::new(self),
            index: 0,
            index_back: N::to_usize(),
        }
    }
}

impl<T, N> Drop for GenericArrayIter<T, N> where N: ArrayLength<T> {
    fn drop(&mut self) {
        // Drop values that are still alive.
        for p in &mut self.array[self.index..self.index_back] {
            unsafe { ptr::drop_in_place(p); }
        }
    }
}

impl<T, N> Iterator for GenericArrayIter<T, N> where N: ArrayLength<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.len() > 0 {
            unsafe {
                let p = self.array.get_unchecked(self.index);
                self.index += 1;
                Some(ptr::read(p))
            }
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }

    fn count(self) -> usize {
        self.len()
    }

    fn nth(&mut self, n: usize) -> Option<T> {
        // First consume values prior to the nth.
        let ndrop = cmp::min(n, self.len());
        for p in &mut self.array[self.index..self.index + ndrop] {
            self.index += 1;
            unsafe { ptr::drop_in_place(p); }
        }

        self.next()
    }

    fn last(mut self) -> Option<T> {
        // Note, everything else will correctly drop first as `self` leaves scope.
        self.next_back()
    }
}

impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N> where N: ArrayLength<T> {
    fn next_back(&mut self) -> Option<T> {
        if self.len() > 0 {
            self.index_back -= 1;
            unsafe {
                let p = self.array.get_unchecked(self.index_back);
                Some(ptr::read(p))
            }
        } else {
            None
        }
    }
}

impl<T, N> ExactSizeIterator for GenericArrayIter<T, N> where N: ArrayLength<T> {
    fn len(&self) -> usize {
        self.index_back - self.index
    }
}