index_table_builder/
lib.rs
1use std::cmp::Eq;
6use std::collections::HashMap;
7use std::hash::Hash;
8
9pub struct IndexTableBuilder<T>
11where
12 T: Eq + Hash + Default + 'static,
13{
14 index: HashMap<T, usize>,
15}
16
17impl<T> Default for IndexTableBuilder<T>
18where
19 T: Eq + Hash + Default + 'static,
20{
21 fn default() -> IndexTableBuilder<T> {
22 IndexTableBuilder { index: HashMap::new() }
23 }
24}
25
26impl<T> IndexTableBuilder<T>
27where
28 T: Eq + Hash + Default + 'static,
29{
30 pub fn intern(&mut self, value: impl Into<T>) -> usize {
32 let next_index = self.index.len();
33 *self.index.entry(value.into()).or_insert(next_index)
34 }
35
36 pub fn build(mut self) -> Vec<T> {
38 let mut table = Vec::default();
39 table.resize_with(self.index.len(), Default::default);
40 self.index.drain().for_each(|(element, index)| {
41 table[index] = element;
42 });
43 table
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use std::iter::zip;
51
52 #[test]
53 fn test_starts_with_empty_string() {
54 let result = IndexTableBuilder::default().build();
55 assert_eq!(vec![], result);
56 }
57
58 #[test]
59 fn test_mostly_empty() {
60 let b = IndexTableBuilder::default();
61 assert_eq!(0, b.intern("singleton"));
62 assert_eq!(vec!["singleton"], b.build());
63 }
64
65 #[test]
67 fn test_interns_unique_words() {
68 let mut b = IndexTableBuilder::default();
69 let words = vec!["Those", "are", "unique", "words"];
70 let indices: Vec<i64> = words.iter().map(|w| b.intern(w)).collect();
71 let result = b.build();
72
73 for (index, word) in zip(indices, words.iter()) {
74 assert_eq!(*word, result[index as usize]);
75 }
76 }
77
78 #[test]
81 fn test_interns_repeated_words() {
82 let mut b = IndexTableBuilder::default();
83 let words = vec!["word", "word", "word", "word"];
84 let indices: Vec<i64> = words.iter().map(|w| b.intern(w)).collect();
85 let result = b.build();
86
87 let repeated = indices[0];
88 for (index, word) in zip(indices, words.iter()) {
89 assert_eq!(*word, result[index as usize]);
90 assert_eq!(repeated, index);
91 }
92 }
93}