stack_vm/
write_once_table.rs

1//! A key/value table using strings as keys.
2
3use crate::table::Table;
4use std::collections::HashMap;
5
6/// A table which does not allow values to be overwritten.
7/// Useful for your languages constants, etc.
8///
9/// ```
10/// use stack_vm::{WriteOnceTable, Table};
11/// let mut table: WriteOnceTable<usize> = WriteOnceTable::new();
12/// assert!(table.is_empty());
13///
14/// table.insert("example", 13);
15/// assert!(!table.is_empty());
16///
17/// assert!(table.contains_key("example"));
18///
19/// let value = *table.get("example").unwrap();
20/// assert_eq!(value, 13);
21/// ```
22///
23/// ```should_panic
24/// use stack_vm::{WriteOnceTable, Table};
25/// let mut table: WriteOnceTable<usize> = WriteOnceTable::new();
26/// table.insert("example", 13);
27/// table.insert("example", 14);
28/// ```
29#[derive(Debug, Default)]
30pub struct WriteOnceTable<T>(HashMap<String, T>);
31
32impl<T> WriteOnceTable<T> {
33    /// Return a new, empty `WriteOnceTable`.
34    pub fn new() -> WriteOnceTable<T> {
35        WriteOnceTable(HashMap::new())
36    }
37
38    fn already_exists_guard(&self, name: &str) {
39        if self.0.contains_key(name) {
40            panic!("Error: redefining constant {} not allowed.", name);
41        }
42    }
43
44    pub fn keys(&self) -> Vec<String> {
45        let mut result = vec![];
46        self.0.keys().for_each(|ref k| result.push(k.to_string()));
47        result
48    }
49}
50
51impl<T> Table for WriteOnceTable<T> {
52    type Item = T;
53
54    fn insert(&mut self, name: &str, value: T) {
55        self.already_exists_guard(name);
56        let name = String::from(name);
57        self.0.insert(name, value);
58    }
59
60    fn is_empty(&self) -> bool {
61        self.0.is_empty()
62    }
63
64    fn contains_key(&self, name: &str) -> bool {
65        self.0.contains_key(name)
66    }
67
68    fn get(&self, name: &str) -> Option<&T> {
69        self.0.get(name)
70    }
71}
72
73#[cfg(test)]
74mod test {
75    use super::*;
76    use crate::table::Table;
77
78    #[test]
79    fn new() {
80        let write_once_table: WriteOnceTable<usize> = WriteOnceTable::new();
81        assert!(write_once_table.is_empty())
82    }
83
84    #[test]
85    fn insert() {
86        let mut write_once_table: WriteOnceTable<usize> = WriteOnceTable::new();
87        write_once_table.insert("example", 13);
88        assert!(!write_once_table.is_empty());
89        assert_eq!(*write_once_table.get("example").unwrap(), 13);
90    }
91
92    #[test]
93    #[should_panic(expected = "redefining constant")]
94    fn insert_uniq() {
95        let mut write_once_table: WriteOnceTable<usize> = WriteOnceTable::new();
96        write_once_table.insert("example", 13);
97        assert_eq!(*write_once_table.get("example").unwrap(), 13);
98        write_once_table.insert("example", 13);
99    }
100}