Skip to main content

enum_table/impls/
iter.rs

1use crate::{EnumTable, Enumable};
2
3impl<K: Enumable, V, const N: usize> EnumTable<K, V, N> {
4    /// Returns an iterator over references to the keys in the table.
5    pub fn keys(&self) -> core::slice::Iter<'_, K> {
6        K::VARIANTS.iter()
7    }
8
9    /// Returns an iterator over references to the values in the table.
10    pub fn values(&self) -> core::slice::Iter<'_, V> {
11        self.table.iter()
12    }
13
14    /// Returns an iterator over mutable references to the values in the table.
15    pub fn values_mut(&mut self) -> core::slice::IterMut<'_, V> {
16        self.table.iter_mut()
17    }
18
19    /// Returns an iterator over references to the key-value pairs in the table.
20    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
21        self.into_iter()
22    }
23
24    /// Returns an iterator over mutable references to the key-value pairs in the table.
25    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
26        self.into_iter()
27    }
28}
29
30impl<K: Enumable, V, const N: usize> IntoIterator for EnumTable<K, V, N> {
31    type Item = (K, V);
32    type IntoIter = core::iter::Map<
33        core::iter::Enumerate<core::array::IntoIter<V, N>>,
34        fn((usize, V)) -> (K, V),
35    >;
36
37    fn into_iter(self) -> Self::IntoIter {
38        self.table
39            .into_iter()
40            .enumerate()
41            .map(|(i, v)| (K::VARIANTS[i], v))
42    }
43}
44
45impl<'a, K: Enumable, V, const N: usize> IntoIterator for &'a EnumTable<K, V, N> {
46    type Item = (&'a K, &'a V);
47    type IntoIter = core::iter::Map<
48        core::iter::Enumerate<core::slice::Iter<'a, V>>,
49        fn((usize, &'a V)) -> (&'a K, &'a V),
50    >;
51
52    fn into_iter(self) -> Self::IntoIter {
53        self.table
54            .iter()
55            .enumerate()
56            .map(|(i, v)| (&K::VARIANTS[i], v))
57    }
58}
59
60impl<K: Enumable, V, const N: usize> Extend<(K, V)> for EnumTable<K, V, N> {
61    fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
62        for (k, v) in iter {
63            self.set(&k, v);
64        }
65    }
66}
67
68impl<'a, K: Enumable, V: Copy, const N: usize> Extend<(&'a K, &'a V)> for EnumTable<K, V, N> {
69    fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
70        for (k, v) in iter {
71            self.set(k, *v);
72        }
73    }
74}
75
76impl<'a, K: Enumable, V, const N: usize> IntoIterator for &'a mut EnumTable<K, V, N> {
77    type Item = (&'a K, &'a mut V);
78    type IntoIter = core::iter::Map<
79        core::iter::Enumerate<core::slice::IterMut<'a, V>>,
80        fn((usize, &'a mut V)) -> (&'a K, &'a mut V),
81    >;
82
83    fn into_iter(self) -> Self::IntoIter {
84        self.table
85            .iter_mut()
86            .enumerate()
87            .map(|(i, v)| (&K::VARIANTS[i], v))
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Enumable)]
96    enum Color {
97        Red,
98        Green,
99        Blue,
100    }
101
102    const TABLES: EnumTable<Color, &'static str, { Color::COUNT }> =
103        crate::et!(Color, &'static str, |color| match color {
104            Color::Red => "Red",
105            Color::Green => "Green",
106            Color::Blue => "Blue",
107        });
108
109    #[test]
110    fn into_iter_impl() {
111        let mut iter = TABLES.into_iter();
112        assert_eq!(iter.next(), Some((Color::Red, "Red")));
113        assert_eq!(iter.next(), Some((Color::Green, "Green")));
114        assert_eq!(iter.next(), Some((Color::Blue, "Blue")));
115        assert_eq!(iter.next(), None);
116    }
117
118    #[test]
119    fn into_iter_ref_impl() {
120        let mut iter = (&TABLES).into_iter();
121        assert_eq!(iter.next(), Some((&Color::Red, &"Red")));
122        assert_eq!(iter.next(), Some((&Color::Green, &"Green")));
123        assert_eq!(iter.next(), Some((&Color::Blue, &"Blue")));
124        assert_eq!(iter.next(), None);
125    }
126
127    #[test]
128    fn into_iter_mut_impl() {
129        let mut mutable_table = TABLES;
130        let mut iter = (&mut mutable_table).into_iter();
131        assert_eq!(iter.next(), Some((&Color::Red, &mut "Red")));
132        assert_eq!(iter.next(), Some((&Color::Green, &mut "Green")));
133        let blue = iter.next().unwrap();
134        assert_eq!(blue, (&Color::Blue, &mut "Blue"));
135        assert_eq!(iter.next(), None);
136
137        // Modify the value through the mutable reference
138        *blue.1 = "Modified Blue";
139        assert_eq!(mutable_table[Color::Blue], "Modified Blue");
140    }
141
142    #[test]
143    fn extend_owned() {
144        let mut table = TABLES;
145        table.extend([(Color::Red, "New Red"), (Color::Blue, "New Blue")]);
146        assert_eq!(table.get(&Color::Red), &"New Red");
147        assert_eq!(table.get(&Color::Green), &"Green");
148        assert_eq!(table.get(&Color::Blue), &"New Blue");
149    }
150
151    #[test]
152    fn extend_ref() {
153        let mut table = TABLES;
154        table.extend([(&Color::Red, &"New Red")]);
155        assert_eq!(table.get(&Color::Red), &"New Red");
156        assert_eq!(table.get(&Color::Green), &"Green");
157    }
158}