use core::marker::PhantomData;
use core::ops::{Index, IndexMut};
use crate::{EnumTable, Enumable};
impl<K: Enumable + core::fmt::Debug, V: core::fmt::Debug, const N: usize> core::fmt::Debug
for EnumTable<K, V, N>
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
impl<K: Enumable, V: Clone, const N: usize> Clone for EnumTable<K, V, N> {
fn clone(&self) -> Self {
Self {
table: self.table.clone(),
_phantom: PhantomData,
}
}
}
impl<K: Enumable, V: Copy, const N: usize> Copy for EnumTable<K, V, N> {}
impl<K: Enumable, V: PartialEq, const N: usize> PartialEq for EnumTable<K, V, N> {
fn eq(&self, other: &Self) -> bool {
self.table.eq(&other.table)
}
}
impl<K: Enumable, V: Eq, const N: usize> Eq for EnumTable<K, V, N> {}
impl<K: Enumable, V: core::hash::Hash, const N: usize> core::hash::Hash
for EnumTable<K, V, N>
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.table.hash(state);
}
}
impl<K: Enumable, V: Default, const N: usize> Default for EnumTable<K, V, N> {
fn default() -> Self {
Self::new_fill_with_default()
}
}
impl<K: Enumable, V, const N: usize> Index<K> for EnumTable<K, V, N> {
type Output = V;
fn index(&self, index: K) -> &Self::Output {
self.get(&index)
}
}
impl<K: Enumable, V, const N: usize> IndexMut<K> for EnumTable<K, V, N> {
fn index_mut(&mut self, index: K) -> &mut Self::Output {
self.get_mut(&index)
}
}
impl<K: Enumable, V, const N: usize> Index<&K> for EnumTable<K, V, N> {
type Output = V;
fn index(&self, index: &K) -> &Self::Output {
self.get(index)
}
}
impl<K: Enumable, V, const N: usize> IndexMut<&K> for EnumTable<K, V, N> {
fn index_mut(&mut self, index: &K) -> &mut Self::Output {
self.get_mut(index)
}
}
impl<K: Enumable, V, const N: usize> AsRef<[V]> for EnumTable<K, V, N> {
fn as_ref(&self) -> &[V] {
self.as_slice()
}
}
impl<K: Enumable, V, const N: usize> AsMut<[V]> for EnumTable<K, V, N> {
fn as_mut(&mut self) -> &mut [V] {
self.as_mut_slice()
}
}
#[cfg(test)]
mod tests {
use core::hash::{Hash, Hasher};
use super::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Enumable)]
enum Color {
Red,
Green,
Blue,
}
const TABLES: EnumTable<Color, &'static str, { Color::COUNT }> =
crate::et!(Color, &'static str, |color| match color {
Color::Red => "Red",
Color::Green => "Green",
Color::Blue => "Blue",
});
const ANOTHER_TABLES: EnumTable<Color, &'static str, { Color::COUNT }> =
crate::et!(Color, &'static str, |color| match color {
Color::Red => "Red",
Color::Green => "Green",
Color::Blue => "Blue",
});
#[test]
fn debug_impl() {
assert_eq!(
format!("{TABLES:?}"),
r#"{Red: "Red", Green: "Green", Blue: "Blue"}"#
);
}
#[test]
fn eq_impl() {
assert!(TABLES == ANOTHER_TABLES);
assert!(TABLES != EnumTable::new_with_fn(|_| "Unknown"));
}
#[test]
fn hash_impl() {
let mut hasher = std::collections::hash_map::DefaultHasher::new();
TABLES.hash(&mut hasher);
let hash1 = hasher.finish();
let mut hasher2 = std::collections::hash_map::DefaultHasher::new();
ANOTHER_TABLES.hash(&mut hasher2);
let hash2 = hasher2.finish();
assert_eq!(hash1, hash2);
}
#[test]
fn default_impl() {
let default_table: EnumTable<Color, &'static str, { Color::COUNT }> = EnumTable::default();
assert_eq!(default_table.get(&Color::Red), &"");
assert_eq!(default_table.get(&Color::Green), &"");
assert_eq!(default_table.get(&Color::Blue), &"");
}
#[test]
fn index_impl() {
assert_eq!(TABLES[Color::Red], "Red");
assert_eq!(TABLES[Color::Green], "Green");
assert_eq!(TABLES[Color::Blue], "Blue");
let mut mutable_table = TABLES;
mutable_table[Color::Red] = "Changed Red";
assert_eq!(mutable_table[Color::Red], "Changed Red");
}
#[test]
fn as_ref_impl() {
let slice: &[&str] = TABLES.as_ref();
assert_eq!(slice.len(), 3);
}
#[test]
fn as_mut_impl() {
let mut table = TABLES;
let slice: &mut [&str] = table.as_mut();
slice[0] = "Changed";
assert_eq!(table.as_slice()[0], "Changed");
}
}