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