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 *blue.1 = "Modified Blue";
198 assert_eq!(mutable_table[Color::Blue], "Modified Blue");
199 }
200}