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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! iterating over vectors

use crate::vector::Vector;
use std::iter::FusedIterator;
use std::ops::Range;

/// an iterator for consuming the elements of a `Vector`
#[derive(Debug)]
pub struct VectorIterator<T, const ROWS: usize, I>
where
    T: Copy,
    I: Iterator<Item = usize>,
{
    pub(crate) vector: Vector<T, ROWS>,
    pub(crate) row_iterator: I,
}

impl<T, const ROWS: usize, I> Iterator for VectorIterator<T, ROWS, I>
where
    T: Copy,
    I: Iterator<Item = usize>,
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        let index = match self.row_iterator.next() {
            Some(i) => i,
            None => return None,
        };
        // we assume the index given is in bounds (if not, this panics)
        Some(self.vector[index])
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.row_iterator.size_hint()
    }
}

impl<T, const ROWS: usize, I> DoubleEndedIterator for VectorIterator<T, ROWS, I>
where
    T: Copy,
    I: Iterator<Item = usize> + DoubleEndedIterator,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        let index = match self.row_iterator.next_back() {
            Some(i) => i,
            None => return None,
        };
        // we assume the index given is in bounds (if not, this panics)
        Some(self.vector[index])
    }
}

impl<T, const ROWS: usize, I> FusedIterator for VectorIterator<T, ROWS, I>
where
    T: Copy,
    I: Iterator<Item = usize> + FusedIterator,
{
}

impl<T, const ROWS: usize, I> ExactSizeIterator for VectorIterator<T, ROWS, I>
where
    T: Copy,
    I: Iterator<Item = usize> + ExactSizeIterator,
{
}

impl<T, const ROWS: usize> IntoIterator for Vector<T, ROWS>
where
    T: Copy,
{
    type Item = T;
    type IntoIter = VectorIterator<T, ROWS, Range<usize>>;

    fn into_iter(self) -> Self::IntoIter {
        Self::IntoIter {
            vector: self,
            row_iterator: 0..ROWS,
        }
    }
}

/// an iterator for reading (by reference) the elements of a `Vector`
#[derive(Debug)]
pub struct VectorReferenceIterator<'a, T, const ROWS: usize, I>
where
    T: Copy,
    I: Iterator<Item = usize>,
{
    pub(crate) vector: &'a Vector<T, ROWS>,
    pub(crate) row_iterator: I,
}

impl<'a, T, const ROWS: usize, I> Iterator for VectorReferenceIterator<'a, T, ROWS, I>
where
    T: Copy,
    I: Iterator<Item = usize>,
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        let index = match self.row_iterator.next() {
            Some(i) => i,
            _ => return None,
        };
        // we assume the index given is in bounds (if not, this panics)
        Some(&self.vector[index])
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.row_iterator.size_hint()
    }
}

impl<T, const ROWS: usize, I> DoubleEndedIterator for VectorReferenceIterator<'_, T, ROWS, I>
where
    T: Copy,
    I: Iterator<Item = usize> + DoubleEndedIterator,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        let index = match self.row_iterator.next_back() {
            Some(i) => i,
            None => return None,
        };
        // we assume the index given is in bounds (if not, this panics)
        Some(&self.vector[index])
    }
}

impl<T, I, const ROWS: usize> FusedIterator for VectorReferenceIterator<'_, T, ROWS, I>
where
    T: Copy,
    I: Iterator<Item = usize> + FusedIterator,
{
}

impl<T, I, const ROWS: usize> ExactSizeIterator for VectorReferenceIterator<'_, T, ROWS, I>
where
    T: Copy,
    I: Iterator<Item = usize> + ExactSizeIterator,
{
}

impl<'a, T, const ROWS: usize> IntoIterator for &'a Vector<T, ROWS>
where
    T: Copy,
{
    type Item = &'a T;
    type IntoIter = VectorReferenceIterator<'a, T, ROWS, Range<usize>>;

    fn into_iter(self) -> Self::IntoIter {
        Self::IntoIter {
            vector: self,
            row_iterator: 0..ROWS,
        }
    }
}