enum-table 3.0.0

A library for creating tables with enums as key.
Documentation
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");
    }
}