Skip to content

Commit

Permalink
feat: Initialization macros
Browse files Browse the repository at this point in the history
Initialize with all values set explicitly, or with defaults
for missing values. Static initialization via array not done yet,
as there are design tradeoffs. The KV pairs would rely on
downstream crate ensuring correct order, or automated order
correction.
  • Loading branch information
Pscheidl committed May 24, 2024
1 parent 43d17bc commit 6953bdd
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 1 deletion.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ assert_eq!(0, enum_map[Letter::A]);
enum_map[Letter::A] = 42;
assert_eq!(42, enum_map[Letter::A]);

// Construction using macros
// (Key type, Value type, Key=>Value pairs)
let enum_map = em!(Letter, i32, A=>42, B=>24); // All values set explicitly
assert_eq!(42, enum_map[Letter::A]);
assert_eq!(24, enum_map[Letter::B]);

// (Key type, Value type, optional Key=>Value pairs)
let enum_map = em_default!(Letter, i32, A => 42); // Default used for missing values
assert_eq!(42, enum_map[Letter::A]);
assert_eq!(i32::default(), enum_map[Letter::B]);

let enum_map = em_default!(Letter, i32,); // All default
assert_eq!(i32::default(), enum_map[Letter::A]);
assert_eq!(i32::default(), enum_map[Letter::B]);

// Constructor with default values
let enum_map_default = EnumMap::<Letter, i32, { Letter::SIZE }>::new_default();
assert_eq!(0, enum_map_default[Letter::A]);
Expand Down
79 changes: 78 additions & 1 deletion enum-collections/src/enummap.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,88 @@
use crate::Enumerated;
use std::{
array,
fmt::Debug,
marker::PhantomData,
ops::{Index, IndexMut},
};

use crate::Enumerated;
///
/// ```
/// use enum_collections::{em, Enumerated, EnumMap};
/// #[derive(Enumerated)]
/// enum Letter {
/// A,
/// B,
/// }
///
/// let enum_map = em!(Letter, i32, A => 42, B => 24);
/// assert_eq!(42, enum_map[Letter::A]);
/// assert_eq!(24, enum_map[Letter::B]);
/// ```
///
#[macro_export]
macro_rules! em {

($ktp:ty, $vtp:ty, $($x:ident=>$y:expr),* ) => {
enum_collections::EnumMap::<$ktp, $vtp, {<$ktp>::SIZE}>::new_inspect(|letter| {
match letter {
$(<$ktp>::$x => $y,)*
}
})
};

}

///
/// ```
/// use enum_collections::{em_default, Enumerated, EnumMap};
/// #[derive(Enumerated)]
/// enum Letter {
/// A,
/// B,
/// }
///
/// // One non-default value
/// let enum_map = em_default!(Letter, i32, A => 42);
/// assert_eq!(42, enum_map[Letter::A]);
/// assert_eq!(i32::default(), enum_map[Letter::B]);
///
/// // All default
///
/// let enum_map = em_default!(Letter, i32,);
/// assert_eq!(i32::default(), enum_map[Letter::A]);
/// assert_eq!(i32::default(), enum_map[Letter::B]);
/// ```
///
#[macro_export]
macro_rules! em_default {
($ktp:ty, $vtp:ty, $($x:ident=>$y:expr),* ) => {
EnumMap::<$ktp, $vtp, {<$ktp>::SIZE}>::new_inspect(|letter| {
match letter {
$(<$ktp>::$x => $y,)*
_ => Default::default(),
}
})
};
}

#[cfg(test)]
mod macro_test {
use crate::{EnumMap, Enumerated};

#[derive(Enumerated)]
enum Letter {
A,
B,
}

#[test]
fn test_macro() {
let enum_map = em_default!(Letter, i32, A=>42);
assert_eq!(42, enum_map[Letter::A]);
assert_eq!(i32::default(), enum_map[Letter::B]);
}
}

/// A map of enum variants to values. EnumMap is a fixed-size map, where each variant of the enum
/// is mapped to a value. EnumMap is a a zero-cost abstraction over an array, where the index of the array
Expand Down

0 comments on commit 6953bdd

Please sign in to comment.