Type-safe data stores addressed and accessed using enums (in any order).
store_by_enum lets you define multi-dimensional data stores where each dimension is indexed by a Rust enum. Instead of juggling nested maps, arrays, or manual indexing schemes, you describe your axes as enums and get a strongly typed, ergonomic API for reading and writing values.
- Type-safe indexing - only valid enum variants can be used
- Order-independent access - index axes in any order
- Multi-dimensional by construction - no hard-coded limits
- Maximum performance - no strings, no hashing, no lookups, stack-allocated data storage
- Ergonomic API - reads like structured navigation, not bookkeeping
If you find yourself modeling configuration matrices, state tables, schedules, or combinatorial settings, this crate is designed for you.
use store_by_enum::*;
#[derive(Axis, Copy, Clone, Debug)]
enum Room {
Kitchen,
Bedroom,
LivingRoom,
Office,
}
#[derive(Axis, Copy, Clone, Debug)]
enum Period {
Morning,
Day,
Night,
}
#[derive(Axis, Copy, Clone, Debug)]
enum Mode {
Heating,
Cooling,
}
create_store!(HomeClimate, Room, Period, Mode);
fn main() {
// Initialize the store using a function over all enum combinations
let mut schedule = HomeClimate::<f32>::new_from_fn(|room, period, mode| {
match (room, period, mode) {
(_, Period::Night, Mode::Heating) => 18.0,
(_, _, Mode::Heating) => 21.0,
(_, _, Mode::Cooling) => 24.0,
}
});
// Stores can also be initialized using a Vec<T> or filled with T::Default
// Mutate values by progressively refining the address
*schedule
.room_mut(&Room::Office)
.period_mut(&Period::Day)
.mode_mut(&Mode::Heating) = 22.5;
// Axis order does not matter
*schedule
.mode_mut(&Mode::Cooling)
.room_mut(&Room::Bedroom)
.period_mut(&Period::Morning) = 20.0;
// Read values
let heat = schedule
.room(&Room::Kitchen)
.period(&Period::Morning)
.mode(&Mode::Heating);
println!("Kitchen morning heat: {heat}°C");
}Think of a store_by_enum store as:
- a Cartesian product of enum variants
- where each enum defines one axis
- and each combination maps to exactly one value
Instead of indexing with tuples like (room, period, mode), you navigate the address one axis at a time:
store.room(&room).period(&period).mode(&mode)This keeps access explicit, readable, and statically checked.
Good fits:
- Problems with a fixed, finite set of dimensions known at compile time
- Data that can be naturally addressed by enums rather than dynamic keys
- Dense Cartesian products where every combination of axes has a value
- Use cases that benefit from type-safe, order-independent indexing
- Performance-sensitive paths where predictable layout and zero runtime key logic matter
Probably not a good fit:
- Large sparse datasets
- Dynamically changing key sets
- Cases where you need runtime-defined dimensions/keys (this crate is enum-driven)
store_by_enum— main user-facing cratestore_by_enum_macros— proc-macros (re-exported automatically)
Users only need to depend on store_by_enum.
[dependencies]
store_by_enum = "0.1"Licensed under either of:
- Apache License, Version 2.0
- MIT License
at your option.
This crate is early but functional. The API may evolve before 1.0 as real-world use informs design decisions. Feedback and issues are very welcome.