1mod ceremony;
13mod ids;
14
15pub use ceremony::*;
16pub use ids::*;
17
18use indexmap::IndexMap;
19use std::hash::Hash;
20
21#[derive(Debug, Clone)]
26pub struct SymbolTable<Id, T> {
27 items: IndexMap<Id, T>,
28}
29
30impl<Id: Eq + Hash + Clone, T> SymbolTable<Id, T> {
31 pub fn new() -> Self {
33 Self {
34 items: IndexMap::new(),
35 }
36 }
37
38 pub fn insert(&mut self, id: Id, value: T) -> Result<(), Id> {
40 if self.items.contains_key(&id) {
41 return Err(id);
42 }
43 self.items.insert(id, value);
44 Ok(())
45 }
46
47 pub fn insert_or_replace(&mut self, id: Id, value: T) {
49 self.items.insert(id, value);
50 }
51
52 pub fn get(&self, id: &Id) -> Option<&T> {
54 self.items.get(id)
55 }
56
57 pub fn get_mut(&mut self, id: &Id) -> Option<&mut T> {
59 self.items.get_mut(id)
60 }
61
62 pub fn contains(&self, id: &Id) -> bool {
64 self.items.contains_key(id)
65 }
66
67 pub fn iter(&self) -> impl Iterator<Item = (&Id, &T)> {
69 self.items.iter()
70 }
71
72 pub fn values(&self) -> impl Iterator<Item = &T> {
74 self.items.values()
75 }
76
77 pub fn keys(&self) -> impl Iterator<Item = &Id> {
79 self.items.keys()
80 }
81
82 pub fn len(&self) -> usize {
84 self.items.len()
85 }
86
87 pub fn is_empty(&self) -> bool {
89 self.items.is_empty()
90 }
91}
92
93impl<Id: Eq + Hash + Clone, T> Default for SymbolTable<Id, T> {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99impl<Id: Eq + Hash + Clone, T> FromIterator<(Id, T)> for SymbolTable<Id, T> {
100 fn from_iter<I: IntoIterator<Item = (Id, T)>>(iter: I) -> Self {
101 Self {
102 items: iter.into_iter().collect(),
103 }
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn symbol_table_basic_operations() {
113 let mut table: SymbolTable<RoleId, String> = SymbolTable::new();
114
115 assert!(table.insert(RoleId::new("admin"), "Alice".into()).is_ok());
117
118 assert!(table.insert(RoleId::new("admin"), "Bob".into()).is_err());
120
121 assert_eq!(table.get(&RoleId::new("admin")), Some(&"Alice".to_string()));
123 assert_eq!(table.get(&RoleId::new("witness")), None);
124
125 assert!(table.contains(&RoleId::new("admin")));
127 assert!(!table.contains(&RoleId::new("witness")));
128 }
129
130 #[test]
131 fn symbol_table_from_iterator() {
132 let table: SymbolTable<StepId, u32> = vec![
133 (StepId::new("step1"), 1),
134 (StepId::new("step2"), 2),
135 (StepId::new("step3"), 3),
136 ]
137 .into_iter()
138 .collect();
139
140 assert_eq!(table.len(), 3);
141 assert_eq!(table.get(&StepId::new("step2")), Some(&2));
142 }
143}