pub mod executor;
pub mod persistence;
use imbl::{HashMap, Vector};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumVariant {
pub id: String,
pub label: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumSet {
pub id: String,
pub name: String,
pub variants: Vector<EnumVariant>,
}
impl EnumSet {
pub fn variant_ids(&self) -> Vec<&str> {
self.variants.iter().map(|v| v.id.as_str()).collect()
}
}
#[derive(Debug, Clone, Default)]
pub struct EnumSetManager {
pub sets: HashMap<String, EnumSet>,
}
impl EnumSetManager {
pub fn new() -> Self {
Self::default()
}
pub fn get(&self, id: &str) -> Option<&EnumSet> {
self.sets.get(id)
}
pub fn upsert(&mut self, set: EnumSet) {
self.sets.insert(set.id.clone(), set);
}
pub fn remove(&mut self, id: &str) -> Option<EnumSet> {
self.sets.remove(id)
}
pub fn all(&self) -> Vec<&EnumSet> {
let mut out: Vec<&EnumSet> = self.sets.values().collect();
out.sort_by(|a, b| a.id.cmp(&b.id));
out
}
}
#[cfg(test)]
mod tests {
use super::*;
fn set(id: &str, variants: &[(&str, &str)]) -> EnumSet {
EnumSet {
id: id.to_string(),
name: String::new(),
variants: variants
.iter()
.map(|(i, l)| EnumVariant {
id: i.to_string(),
label: l.to_string(),
})
.collect(),
}
}
#[test]
fn an_upsert_replaces_the_option_list_rather_than_merging_into_it() {
let mut m = EnumSetManager::new();
m.upsert(set("status", &[("open", "Open"), ("done", "Done")]));
assert_eq!(m.get("status").unwrap().variant_ids(), vec!["open", "done"]);
m.upsert(set("status", &[("open", "Open")]));
assert_eq!(m.get("status").unwrap().variant_ids(), vec!["open"]);
}
#[test]
fn sets_are_listed_in_a_stable_order() {
let mut m = EnumSetManager::new();
m.upsert(set("zeta", &[("a", "A")]));
m.upsert(set("alpha", &[("b", "B")]));
m.upsert(set("mid", &[("c", "C")]));
assert_eq!(
m.all().iter().map(|s| s.id.as_str()).collect::<Vec<_>>(),
vec!["alpha", "mid", "zeta"]
);
}
}