EnumTable

Struct EnumTable 

Source
pub struct EnumTable<K: Enumable, V, const N: usize> { /* private fields */ }
Expand description

A table that associates each variant of an enumeration with a value.

EnumTable is a generic struct that uses an enumeration as keys and stores associated values. It provides efficient logarithmic-time access (O(log N)) to the values based on the enumeration variant. This is particularly useful when you want to map enum variants to specific values without the overhead of a HashMap.

§Guarantees and Design

The core design principle of EnumTable is that an instance is guaranteed to hold a value for every variant of the enum K. This guarantee allows for a cleaner API than general-purpose map structures.

For example, the Self::get method returns &V directly. This is in contrast to std::collections::HashMap::get, which returns an Option<&V> because a key may or may not be present. With EnumTable, the presence of all keys (variants) is a type-level invariant, eliminating the need for unwrap() or other Option handling.

If you need to handle cases where a value might not be present or will be set later, you can use Option<V> as the value type: EnumTable<K, Option<V>, N>. The struct provides convenient methods like Self::new_fill_with_none for this pattern.

§Type Parameters

  • K: The enumeration type that implements the Enumable trait. This trait ensures that the enum provides a static array of its variants and a count of these variants.
  • V: The type of values to be associated with each enum variant.
  • N: The number of variants in the enum, which should match the length of the static array of variants provided by the Enumable trait.

§Examples

use enum_table::{EnumTable, Enumable};

#[derive(Enumable, Copy, Clone)]
enum Color {
    Red,
    Green,
    Blue,
}

// Create an EnumTable using the new_with_fn method
let table = EnumTable::<Color, &'static str, { Color::COUNT }>::new_with_fn(|color| match color {
    Color::Red => "Red",
    Color::Green => "Green",
    Color::Blue => "Blue",
});

// Access values associated with enum variants
assert_eq!(table.get(&Color::Red), &"Red");
assert_eq!(table.get(&Color::Green), &"Green");
assert_eq!(table.get(&Color::Blue), &"Blue");

Implementations§

Source§

impl<K: Enumable + Eq + Hash + Debug, V, const N: usize> EnumTable<K, V, N>

Source

pub fn into_hash_map(self) -> HashMap<K, V>

Converts the EnumTable into a HashMap.

This method consumes the EnumTable and creates a new HashMap with the same key-value pairs. Each enum variant is mapped to its associated value.

§Examples
use enum_table::{EnumTable, Enumable};
use std::collections::HashMap;

#[derive(Enumable, Debug, PartialEq, Eq, Hash, Copy, Clone)]
enum Status {
    Active,
    Inactive,
    Pending,
}

let table = EnumTable::<Status, &str, { Status::COUNT }>::new_with_fn(|status| match status {
    Status::Active => "running",
    Status::Inactive => "stopped",
    Status::Pending => "waiting",
});

let hash_map = table.into_hash_map();
assert_eq!(hash_map.get(&Status::Active), Some(&"running"));
assert_eq!(hash_map.get(&Status::Inactive), Some(&"stopped"));
assert_eq!(hash_map.get(&Status::Pending), Some(&"waiting"));
assert_eq!(hash_map.len(), 3);
Source

pub fn try_from_hash_map(map: HashMap<K, V>) -> Option<EnumTable<K, V, N>>

Creates an EnumTable from a HashMap.

Returns None if the HashMap doesn’t contain exactly one entry for each enum variant. The HashMap must have exactly N entries where N is the number of enum variants.

§Arguments
  • map - A HashMap containing key-value pairs for each enum variant.
§Examples
use enum_table::{EnumTable, Enumable};
use std::collections::HashMap;

#[derive(Enumable, Debug, PartialEq, Eq, Hash, Copy, Clone)]
enum Priority {
    Low,
    Medium,
    High,
}

let mut hash_map = HashMap::new();
hash_map.insert(Priority::Low, 1);
hash_map.insert(Priority::Medium, 5);
hash_map.insert(Priority::High, 10);

let table = EnumTable::<Priority, i32, { Priority::COUNT }>::try_from_hash_map(hash_map)
    .expect("HashMap should contain all variants");

assert_eq!(table.get(&Priority::Low), &1);
assert_eq!(table.get(&Priority::Medium), &5);
assert_eq!(table.get(&Priority::High), &10);
// Example with missing variant
let mut incomplete_map = HashMap::new();
incomplete_map.insert(Priority::Low, 1);
incomplete_map.insert(Priority::Medium, 5);
// Missing Priority::High

let result = EnumTable::<Priority, i32, { Priority::COUNT }>::try_from_hash_map(incomplete_map);
assert!(result.is_none());
Source§

impl<K: Enumable + Ord, V, const N: usize> EnumTable<K, V, N>

Source

pub fn into_btree_map(self) -> BTreeMap<K, V>

Converts the EnumTable into a BTreeMap.

This method consumes the EnumTable and creates a new BTreeMap with the same key-value pairs. The resulting map will have keys sorted according to their Ord implementation.

§Examples
use enum_table::{EnumTable, Enumable};
use std::collections::BTreeMap;

#[derive(Enumable, Debug, PartialEq, Eq, Ord, PartialOrd, Copy, Clone)]
enum Level {
    Beginner,
    Intermediate,
    Advanced,
}

let table = EnumTable::<Level, u32, { Level::COUNT }>::new_with_fn(|level| match level {
    Level::Beginner => 100,
    Level::Intermediate => 500,
    Level::Advanced => 1000,
});

let btree_map = table.into_btree_map();
assert_eq!(btree_map.get(&Level::Beginner), Some(&100));
assert_eq!(btree_map.get(&Level::Intermediate), Some(&500));
assert_eq!(btree_map.get(&Level::Advanced), Some(&1000));
assert_eq!(btree_map.len(), 3);
Source

pub fn try_from_btree_map(map: BTreeMap<K, V>) -> Option<EnumTable<K, V, N>>

Creates an EnumTable from a BTreeMap.

Returns None if the BTreeMap doesn’t contain exactly one entry for each enum variant. The BTreeMap must have exactly N entries where N is the number of enum variants.

§Arguments
  • map - A BTreeMap containing key-value pairs for each enum variant.
§Examples
use enum_table::{EnumTable, Enumable};
use std::collections::BTreeMap;

#[derive(Enumable, Debug, PartialEq, Eq, Ord, PartialOrd, Copy, Clone)]
enum Grade {
    A,
    B,
    C,
}

let mut btree_map = BTreeMap::new();
btree_map.insert(Grade::A, 90.0);
btree_map.insert(Grade::B, 80.0);
btree_map.insert(Grade::C, 70.0);

let table = EnumTable::<Grade, f64, { Grade::COUNT }>::try_from_btree_map(btree_map)
    .expect("BTreeMap should contain all variants");

assert_eq!(table.get(&Grade::A), &90.0);
assert_eq!(table.get(&Grade::B), &80.0);
assert_eq!(table.get(&Grade::C), &70.0);
// Example with missing variant
let mut incomplete_map = BTreeMap::new();
incomplete_map.insert(Grade::A, 90.0);
incomplete_map.insert(Grade::B, 80.0);
// Missing Grade::C

let result = EnumTable::<Grade, f64, { Grade::COUNT }>::try_from_btree_map(incomplete_map);
assert!(result.is_none());
Source§

impl<K: Enumable, V, const N: usize> EnumTable<K, V, N>

Source

pub fn into_vec(self) -> Vec<(K, V)>

Converts the EnumTable into a Vec of key-value pairs.

§Examples
use enum_table::{EnumTable, Enumable};

#[derive(Enumable, Debug, PartialEq, Copy, Clone)]
enum Color {
    Red,
    Green,
    Blue,
}

let table = EnumTable::<Color, &str, { Color::COUNT }>::new_with_fn(|color| match color {
    Color::Red => "red",
    Color::Green => "green",
    Color::Blue => "blue",
});

let vec = table.into_vec();
assert!(vec.contains(&(Color::Red, "red")));
assert!(vec.contains(&(Color::Green, "green")));
assert!(vec.contains(&(Color::Blue, "blue")));
assert_eq!(vec.len(), 3);
Source

pub fn try_from_vec(vec: Vec<(K, V)>) -> Result<Self, EnumTableFromVecError<K>>

Creates an EnumTable from a Vec of key-value pairs.

Returns an error if the vector doesn’t contain exactly one entry for each enum variant.

§Arguments
  • vec - A vector containing key-value pairs for each enum variant.
§Examples
use enum_table::{EnumTable, Enumable};

#[derive(Enumable, Debug, PartialEq, Copy, Clone)]
enum Color {
    Red,
    Green,
    Blue,
}

let vec = vec![
    (Color::Red, "red"),
    (Color::Green, "green"),
    (Color::Blue, "blue"),
];

let table = EnumTable::<Color, &str, { Color::COUNT }>::try_from_vec(vec).unwrap();
assert_eq!(table.get(&Color::Red), &"red");
assert_eq!(table.get(&Color::Green), &"green");
assert_eq!(table.get(&Color::Blue), &"blue");
Source§

impl<K: Enumable, V, const N: usize> EnumTable<K, V, N>

Source

pub fn new_with_fn(f: impl FnMut(&K) -> V) -> Self

Create a new EnumTable with a function that takes a variant and returns a value. If you want to define it in const, use crate::et macro Creates a new EnumTable using a function to generate values for each variant.

§Arguments
  • f - A function that takes a reference to an enumeration variant and returns a value to be associated with that variant.
Source

pub fn try_new_with_fn<E>( f: impl FnMut(&K) -> Result<V, E>, ) -> Result<Self, (K, E)>

Creates a new EnumTable using a function that returns a Result for each variant.

This method applies the provided closure to each variant of the enum. If the closure returns Ok(value) for all variants, an EnumTable is constructed and returned as Ok(Self). If the closure returns Err(e) for any variant, the construction is aborted and Err((variant, e)) is returned, where variant is the enum variant that caused the error.

§Arguments
  • f - A closure that takes a reference to an enum variant and returns a Result<V, E>.
§Returns
  • Ok(Self) if all variants succeed.
  • Err((variant, e)) if any variant fails, containing the failing variant and the error.
Source

pub fn checked_new_with_fn(f: impl FnMut(&K) -> Option<V>) -> Result<Self, K>

Creates a new EnumTable using a function that returns an Option for each variant.

This method applies the provided closure to each variant of the enum. If the closure returns Some(value) for all variants, an EnumTable is constructed and returned as Ok(Self). If the closure returns None for any variant, the construction is aborted and Err(variant) is returned, where variant is the enum variant that caused the failure.

§Arguments
  • f - A closure that takes a reference to an enum variant and returns an Option<V>.
§Returns
  • Ok(Self) if all variants succeed.
  • Err(variant) if any variant fails, containing the failing variant.
Source

pub const fn get(&self, variant: &K) -> &V

Returns a reference to the value associated with the given enumeration variant.

§Arguments
  • variant - A reference to an enumeration variant.
Source

pub const fn get_mut(&mut self, variant: &K) -> &mut V

Returns a mutable reference to the value associated with the given enumeration variant.

§Arguments
  • variant - A reference to an enumeration variant.
Source

pub const fn set(&mut self, variant: &K, value: V) -> V

Sets the value associated with the given enumeration variant.

§Arguments
  • variant - A reference to an enumeration variant.
  • value - The new value to associate with the variant.
§Returns

The old value associated with the variant.

Source

pub const fn len(&self) -> usize

Returns the number of generic N

Source

pub const fn is_empty(&self) -> bool

Returns false since the table is never empty.

Source

pub fn keys(&self) -> impl Iterator<Item = &K>

Returns an iterator over references to the keys in the table.

Source

pub fn values(&self) -> impl Iterator<Item = &V>

Returns an iterator over references to the values in the table.

Source

pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V>

Returns an iterator over mutable references to the values in the table.

Source

pub fn iter(&self) -> impl Iterator<Item = (&K, &V)>

Returns an iterator over mutable references to the values in the table.

Source

pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)>

Returns an iterator over mutable references to the values in the table.

Source

pub fn map<U>(self, f: impl FnMut(V) -> U) -> EnumTable<K, U, N>

Transforms all values in the table using the provided function.

This method consumes the table and creates a new one with values transformed by the given closure.

§Arguments
  • f - A closure that takes an owned value and returns a new value.
§Examples
use enum_table::{EnumTable, Enumable};

#[derive(Enumable, Copy, Clone)]
enum Size {
    Small,
    Medium,
    Large,
}

let table = EnumTable::<Size, i32, { Size::COUNT }>::new_with_fn(|size| match size {
    Size::Small => 1,
    Size::Medium => 2,
    Size::Large => 3,
});

let doubled = table.map(|value| value * 2);

assert_eq!(doubled.get(&Size::Small), &2);
assert_eq!(doubled.get(&Size::Medium), &4);
assert_eq!(doubled.get(&Size::Large), &6);
Source

pub fn map_with_key<U>(self, f: impl FnMut(&K, V) -> U) -> EnumTable<K, U, N>

Transforms all values in the table using the provided function, with access to the key.

This method consumes the table and creates a new one with values transformed by the given closure, which receives both the key and the value.

§Arguments
  • f - A closure that takes a key reference and an owned value, and returns a new value.
Source

pub fn map_mut(&mut self, f: impl FnMut(&mut V))

Transforms all values in the table in-place using the provided function.

§Arguments
  • f - A closure that takes a mutable reference to a value and modifies it.
§Examples
use enum_table::{EnumTable, Enumable};

#[derive(Enumable, Copy, Clone)]
enum Level {
    Low,
    Medium,
    High,
}

let mut table = EnumTable::<Level, i32, { Level::COUNT }>::new_with_fn(|level| match level {
    Level::Low => 10,
    Level::Medium => 20,
    Level::High => 30,
});

table.map_mut(|value| *value += 5);

assert_eq!(table.get(&Level::Low), &15);
assert_eq!(table.get(&Level::Medium), &25);
assert_eq!(table.get(&Level::High), &35);
Source

pub fn map_mut_with_key(&mut self, f: impl FnMut(&K, &mut V))

Transforms all values in the table in-place using the provided function, with access to the key.

§Arguments
  • f - A closure that takes a key reference and a mutable reference to a value, and modifies it.
Source§

impl<K: Enumable, V, const N: usize> EnumTable<K, Option<V>, N>

Source

pub const fn new_fill_with_none() -> Self

Creates a new EnumTable with None values for each variant.

Source

pub fn clear_to_none(&mut self)

Clears the table, setting each value to None.

Source§

impl<K: Enumable, V: Copy, const N: usize> EnumTable<K, V, N>

Source

pub const fn new_fill_with_copy(value: V) -> Self

Creates a new EnumTable with the same copied value for each variant.

This method initializes the table with the same value for each variant of the enumeration. The value must implement Copy.

§Arguments
  • value - The value to copy for each enum variant.
§Examples
use enum_table::{EnumTable, Enumable};

#[derive(Enumable, Copy, Clone)]
enum Status {
    Active,
    Inactive,
    Pending,
}

let table = EnumTable::<Status, i32, { Status::COUNT }>::new_fill_with_copy(42);

assert_eq!(table.get(&Status::Active), &42);
assert_eq!(table.get(&Status::Inactive), &42);
assert_eq!(table.get(&Status::Pending), &42);
Source§

impl<K: Enumable, V: Default, const N: usize> EnumTable<K, V, N>

Source

pub fn new_fill_with_default() -> Self

Creates a new EnumTable with default values for each variant.

This method initializes the table with the default value of type V for each variant of the enumeration.

Source

pub fn clear_to_default(&mut self)

Clears the table, setting each value to its default.

Trait Implementations§

Source§

impl<K: Enumable, V: Clone, const N: usize> Clone for EnumTable<K, V, N>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<K: Enumable + Debug, V: Debug, const N: usize> Debug for EnumTable<K, V, N>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<K: Enumable, V: Default, const N: usize> Default for EnumTable<K, V, N>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<K: Enumable, V: Hash, const N: usize> Hash for EnumTable<K, V, N>

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<K: Enumable, V, const N: usize> Index<K> for EnumTable<K, V, N>

Source§

type Output = V

The returned type after indexing.
Source§

fn index(&self, index: K) -> &Self::Output

Performs the indexing (container[index]) operation. Read more
Source§

impl<K: Enumable, V, const N: usize> IndexMut<K> for EnumTable<K, V, N>

Source§

fn index_mut(&mut self, index: K) -> &mut Self::Output

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl<'a, K: Enumable, V, const N: usize> IntoIterator for &'a EnumTable<K, V, N>

Source§

type Item = (&'a K, &'a V)

The type of the elements being iterated over.
Source§

type IntoIter = Map<Iter<'a, (usize, V)>, fn(&'a (usize, V)) -> (&'a K, &'a V)>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<'a, K: Enumable, V, const N: usize> IntoIterator for &'a mut EnumTable<K, V, N>

Source§

type Item = (&'a K, &'a mut V)

The type of the elements being iterated over.
Source§

type IntoIter = Map<IterMut<'a, (usize, V)>, fn(&'a mut (usize, V)) -> (&'a K, &'a mut V)>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<K: Enumable, V, const N: usize> IntoIterator for EnumTable<K, V, N>

Source§

type Item = (K, V)

The type of the elements being iterated over.
Source§

type IntoIter = Map<IntoIter<(usize, V), N>, fn((usize, V)) -> (K, V)>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<K: Enumable, V: PartialEq, const N: usize> PartialEq for EnumTable<K, V, N>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<K: Enumable, V: Copy, const N: usize> Copy for EnumTable<K, V, N>

Source§

impl<K: Enumable, V: Eq, const N: usize> Eq for EnumTable<K, V, N>

Auto Trait Implementations§

§

impl<K, V, const N: usize> Freeze for EnumTable<K, V, N>
where V: Freeze,

§

impl<K, V, const N: usize> RefUnwindSafe for EnumTable<K, V, N>

§

impl<K, V, const N: usize> Send for EnumTable<K, V, N>
where K: Send, V: Send,

§

impl<K, V, const N: usize> Sync for EnumTable<K, V, N>
where K: Sync, V: Sync,

§

impl<K, V, const N: usize> Unpin for EnumTable<K, V, N>
where K: Unpin, V: Unpin,

§

impl<K, V, const N: usize> UnwindSafe for EnumTable<K, V, N>
where K: UnwindSafe, V: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.