1use core::marker::PhantomData;
2use core::ops::{Index, IndexMut};
3
4use crate::{EnumTable, Enumerable};
5
6impl<K: Enumerable + core::fmt::Debug, V: core::fmt::Debug, const N: usize> core::fmt::Debug
7 for EnumTable<K, V, N>
8{
9 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
10 f.debug_map().entries(self.iter()).finish()
11 }
12}
13
14impl<K: Enumerable, V: Clone, const N: usize> Clone for EnumTable<K, V, N> {
15 fn clone(&self) -> Self {
16 Self {
17 table: self.table.clone(),
18 _phantom: PhantomData,
19 }
20 }
21}
22
23impl<K: Enumerable, V: Copy, const N: usize> Copy for EnumTable<K, V, N> {}
24
25impl<K: Enumerable, V: PartialEq, const N: usize> PartialEq for EnumTable<K, V, N> {
26 fn eq(&self, other: &Self) -> bool {
27 self.table.eq(&other.table)
28 }
29}
30
31impl<K: Enumerable, V: Eq, const N: usize> Eq for EnumTable<K, V, N> {}
32
33impl<K: Enumerable, V: core::hash::Hash, const N: usize> core::hash::Hash for EnumTable<K, V, N> {
34 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
35 self.table.hash(state);
36 }
37}
38
39impl<K: Enumerable, V: Default, const N: usize> Default for EnumTable<K, V, N> {
40 fn default() -> Self {
41 Self::new(core::array::from_fn(|_| V::default()))
42 }
43}
44
45impl<K: Enumerable, V, const N: usize> Index<K> for EnumTable<K, V, N> {
46 type Output = V;
47
48 fn index(&self, index: K) -> &Self::Output {
49 self.get(index)
50 }
51}
52
53impl<K: Enumerable, V, const N: usize> IndexMut<K> for EnumTable<K, V, N> {
54 fn index_mut(&mut self, index: K) -> &mut Self::Output {
55 self.get_mut(index)
56 }
57}
58
59impl<K: Enumerable, 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: Enumerable, 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
73#[cfg(test)]
74mod tests {
75 use core::hash::{Hash, Hasher};
76
77 use super::*;
78
79 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Enumerable)]
80 enum Color {
81 Red,
82 Green,
83 Blue,
84 }
85
86 const TABLES: EnumTable<Color, &'static str, { Color::COUNT }> =
87 crate::et!(Color, &'static str, |color| match color {
88 Color::Red => "Red",
89 Color::Green => "Green",
90 Color::Blue => "Blue",
91 });
92
93 const ANOTHER_TABLES: EnumTable<Color, &'static str, { Color::COUNT }> =
94 crate::et!(Color, &'static str, |color| match color {
95 Color::Red => "Red",
96 Color::Green => "Green",
97 Color::Blue => "Blue",
98 });
99
100 #[test]
101 fn debug_impl() {
102 assert_eq!(
103 format!("{TABLES:?}"),
104 r#"{Red: "Red", Green: "Green", Blue: "Blue"}"#
105 );
106 }
107
108 #[test]
109 fn eq_impl() {
110 assert!(TABLES == ANOTHER_TABLES);
111 assert!(TABLES != EnumTable::from_fn(|_| "Unknown"));
112 }
113
114 #[test]
115 fn hash_impl() {
116 let mut hasher = std::collections::hash_map::DefaultHasher::new();
117 TABLES.hash(&mut hasher);
118 let hash1 = hasher.finish();
119
120 let mut hasher2 = std::collections::hash_map::DefaultHasher::new();
121 ANOTHER_TABLES.hash(&mut hasher2);
122 let hash2 = hasher2.finish();
123
124 assert_eq!(hash1, hash2);
125 }
126
127 #[test]
128 fn default_impl() {
129 let default_table: EnumTable<Color, &'static str, { Color::COUNT }> = EnumTable::default();
130 assert_eq!(default_table.get(Color::Red), &"");
131 assert_eq!(default_table.get(Color::Green), &"");
132 assert_eq!(default_table.get(Color::Blue), &"");
133 }
134
135 #[test]
136 fn index_impl() {
137 assert_eq!(TABLES[Color::Red], "Red");
138 assert_eq!(TABLES[Color::Green], "Green");
139 assert_eq!(TABLES[Color::Blue], "Blue");
140
141 let mut mutable_table = TABLES;
142 mutable_table[Color::Red] = "Changed Red";
143 assert_eq!(mutable_table[Color::Red], "Changed Red");
144 }
145}