enum_table/impls/
std.rs

1use core::ops::{Index, IndexMut};
2
3use crate::{EnumTable, Enumable};
4
5impl<K: Enumable + core::fmt::Debug, V: core::fmt::Debug, const N: usize> core::fmt::Debug
6    for EnumTable<K, V, N>
7{
8    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
9        f.debug_map().entries(self.iter()).finish()
10    }
11}
12
13impl<K: Enumable, V: Clone, const N: usize> Clone for EnumTable<K, V, N> {
14    fn clone(&self) -> Self {
15        Self {
16            table: self.table.clone(),
17            _phantom: core::marker::PhantomData,
18        }
19    }
20}
21
22impl<K: Enumable, V: Copy, const N: usize> Copy for EnumTable<K, V, N> {}
23
24impl<K: Enumable, V: PartialEq, const N: usize> PartialEq for EnumTable<K, V, N> {
25    fn eq(&self, other: &Self) -> bool {
26        self.table.eq(&other.table)
27    }
28}
29
30impl<K: Enumable, V: Eq, const N: usize> Eq for EnumTable<K, V, N> {}
31
32impl<K: Enumable, V: core::hash::Hash, const N: usize> core::hash::Hash for EnumTable<K, V, N> {
33    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
34        self.table.hash(state);
35    }
36}
37
38impl<K: Enumable, V: Default, const N: usize> Default for EnumTable<K, V, N> {
39    fn default() -> Self {
40        EnumTable::new_with_fn(|_| Default::default())
41    }
42}
43
44impl<K: Enumable, V, const N: usize> Index<K> for EnumTable<K, V, N> {
45    type Output = V;
46
47    fn index(&self, index: K) -> &Self::Output {
48        self.get(&index)
49    }
50}
51
52impl<K: Enumable, V, const N: usize> IndexMut<K> for EnumTable<K, V, N> {
53    fn index_mut(&mut self, index: K) -> &mut Self::Output {
54        self.get_mut(&index)
55    }
56}
57
58impl<K: Enumable, V, const N: usize> IntoIterator for EnumTable<K, V, N> {
59    type Item = (K, V);
60    type IntoIter = core::iter::Map<core::array::IntoIter<(usize, V), N>, fn((usize, V)) -> (K, V)>;
61
62    fn into_iter(self) -> Self::IntoIter {
63        self.table
64            .into_iter()
65            .map(|(discriminant, value)| (crate::intrinsics::into_variant(discriminant), value))
66    }
67}
68
69impl<'a, K: Enumable, V, const N: usize> IntoIterator for &'a EnumTable<K, V, N> {
70    type Item = (&'a K, &'a V);
71    type IntoIter =
72        core::iter::Map<core::slice::Iter<'a, (usize, V)>, fn(&'a (usize, V)) -> (&'a K, &'a V)>;
73
74    fn into_iter(self) -> Self::IntoIter {
75        self.table
76            .iter()
77            .map(|(discriminant, value)| (crate::intrinsics::cast_variant(discriminant), value))
78    }
79}
80
81impl<'a, K: Enumable, V, const N: usize> IntoIterator for &'a mut EnumTable<K, V, N> {
82    type Item = (&'a K, &'a mut V);
83    type IntoIter = core::iter::Map<
84        core::slice::IterMut<'a, (usize, V)>,
85        fn(&'a mut (usize, V)) -> (&'a K, &'a mut V),
86    >;
87
88    fn into_iter(self) -> Self::IntoIter {
89        self.table
90            .iter_mut()
91            .map(|(discriminant, value)| (crate::intrinsics::cast_variant(discriminant), value))
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use core::hash::{Hash, Hasher};
98
99    use super::*;
100
101    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Enumable)]
102    enum Color {
103        Red,
104        Green,
105        Blue,
106    }
107
108    const TABLES: EnumTable<Color, &'static str, { Color::COUNT }> =
109        crate::et!(Color, &'static str, |color| match color {
110            Color::Red => "Red",
111            Color::Green => "Green",
112            Color::Blue => "Blue",
113        });
114
115    const ANOTHER_TABLES: EnumTable<Color, &'static str, { Color::COUNT }> =
116        crate::et!(Color, &'static str, |color| match color {
117            Color::Red => "Red",
118            Color::Green => "Green",
119            Color::Blue => "Blue",
120        });
121
122    #[test]
123    fn debug_impl() {
124        assert_eq!(
125            format!("{TABLES:?}"),
126            r#"{Red: "Red", Green: "Green", Blue: "Blue"}"#
127        );
128    }
129
130    #[test]
131    fn eq_impl() {
132        assert!(TABLES == ANOTHER_TABLES);
133        assert!(TABLES != EnumTable::new_with_fn(|_| "Unknown"));
134    }
135
136    #[test]
137    fn hash_impl() {
138        let mut hasher = std::collections::hash_map::DefaultHasher::new();
139        TABLES.hash(&mut hasher);
140        let hash1 = hasher.finish();
141
142        let mut hasher2 = std::collections::hash_map::DefaultHasher::new();
143        ANOTHER_TABLES.hash(&mut hasher2);
144        let hash2 = hasher2.finish();
145
146        assert_eq!(hash1, hash2);
147    }
148
149    #[test]
150    fn default_impl() {
151        let default_table: EnumTable<Color, &'static str, { Color::COUNT }> = EnumTable::default();
152        assert_eq!(default_table.get(&Color::Red), &"");
153        assert_eq!(default_table.get(&Color::Green), &"");
154        assert_eq!(default_table.get(&Color::Blue), &"");
155    }
156
157    #[test]
158    fn index_impl() {
159        assert_eq!(TABLES[Color::Red], "Red");
160        assert_eq!(TABLES[Color::Green], "Green");
161        assert_eq!(TABLES[Color::Blue], "Blue");
162
163        let mut mutable_table = TABLES;
164        mutable_table[Color::Red] = "Changed Red";
165        assert_eq!(mutable_table[Color::Red], "Changed Red");
166    }
167
168    #[test]
169    fn into_iter_impl() {
170        let mut iter = TABLES.into_iter();
171        assert_eq!(iter.next(), Some((Color::Red, "Red")));
172        assert_eq!(iter.next(), Some((Color::Green, "Green")));
173        assert_eq!(iter.next(), Some((Color::Blue, "Blue")));
174        assert_eq!(iter.next(), None);
175    }
176
177    #[test]
178    fn into_iter_ref_impl() {
179        let mut iter = (&TABLES).into_iter();
180        assert_eq!(iter.next(), Some((&Color::Red, &"Red")));
181        assert_eq!(iter.next(), Some((&Color::Green, &"Green")));
182        assert_eq!(iter.next(), Some((&Color::Blue, &"Blue")));
183        assert_eq!(iter.next(), None);
184    }
185
186    #[test]
187    fn into_iter_mut_impl() {
188        let mut mutable_table = TABLES;
189        let mut iter = (&mut mutable_table).into_iter();
190        assert_eq!(iter.next(), Some((&Color::Red, &mut "Red")));
191        assert_eq!(iter.next(), Some((&Color::Green, &mut "Green")));
192        let blue = iter.next().unwrap();
193        assert_eq!(blue, (&Color::Blue, &mut "Blue"));
194        assert_eq!(iter.next(), None);
195
196        // Modify the value through the mutable reference
197        *blue.1 = "Modified Blue";
198        assert_eq!(mutable_table[Color::Blue], "Modified Blue");
199    }
200}