mod ceremony;
mod ids;
pub use ceremony::*;
pub use ids::*;
use indexmap::IndexMap;
use std::hash::Hash;
#[derive(Debug, Clone)]
pub struct SymbolTable<Id, T> {
items: IndexMap<Id, T>,
}
impl<Id: Eq + Hash + Clone, T> SymbolTable<Id, T> {
pub fn new() -> Self {
Self {
items: IndexMap::new(),
}
}
pub fn insert(&mut self, id: Id, value: T) -> Result<(), Id> {
if self.items.contains_key(&id) {
return Err(id);
}
self.items.insert(id, value);
Ok(())
}
pub fn insert_or_replace(&mut self, id: Id, value: T) {
self.items.insert(id, value);
}
pub fn get(&self, id: &Id) -> Option<&T> {
self.items.get(id)
}
pub fn get_mut(&mut self, id: &Id) -> Option<&mut T> {
self.items.get_mut(id)
}
pub fn contains(&self, id: &Id) -> bool {
self.items.contains_key(id)
}
pub fn iter(&self) -> impl Iterator<Item = (&Id, &T)> {
self.items.iter()
}
pub fn values(&self) -> impl Iterator<Item = &T> {
self.items.values()
}
pub fn keys(&self) -> impl Iterator<Item = &Id> {
self.items.keys()
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
}
impl<Id: Eq + Hash + Clone, T> Default for SymbolTable<Id, T> {
fn default() -> Self {
Self::new()
}
}
impl<Id: Eq + Hash + Clone, T> FromIterator<(Id, T)> for SymbolTable<Id, T> {
fn from_iter<I: IntoIterator<Item = (Id, T)>>(iter: I) -> Self {
Self {
items: iter.into_iter().collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn symbol_table_basic_operations() {
let mut table: SymbolTable<RoleId, String> = SymbolTable::new();
assert!(table.insert(RoleId::new("admin"), "Alice".into()).is_ok());
assert!(table.insert(RoleId::new("admin"), "Bob".into()).is_err());
assert_eq!(table.get(&RoleId::new("admin")), Some(&"Alice".to_string()));
assert_eq!(table.get(&RoleId::new("witness")), None);
assert!(table.contains(&RoleId::new("admin")));
assert!(!table.contains(&RoleId::new("witness")));
}
#[test]
fn symbol_table_from_iterator() {
let table: SymbolTable<StepId, u32> = vec![
(StepId::new("step1"), 1),
(StepId::new("step2"), 2),
(StepId::new("step3"), 3),
]
.into_iter()
.collect();
assert_eq!(table.len(), 3);
assert_eq!(table.get(&StepId::new("step2")), Some(&2));
}
}