1use std::collections::HashMap;
3use std::hash::Hash;
4use std::slice;
5
6pub(crate) struct UniqueTable<'entries, T: Eq + Hash> {
8 table: Vec<&'entries T>,
9 map: HashMap<&'entries T, usize>,
10}
11
12impl<'entries, T: Eq + Hash> UniqueTable<'entries, T> {
13 pub fn new() -> Self {
14 Self {
15 table: Vec::new(),
16 map: HashMap::new(),
17 }
18 }
19
20 pub fn add(&mut self, entry: &'entries T) -> usize {
21 match self.map.get(&entry) {
22 None => {
23 let i = self.table.len();
24 self.table.push(entry);
25 self.map.insert(entry, i);
26 i
27 }
28 Some(&i) => i,
29 }
30 }
31
32 pub fn len(&self) -> usize {
33 self.table.len()
34 }
35 pub fn iter(&self) -> slice::Iter<&'entries T> {
36 self.table.iter()
37 }
38}
39
40pub(crate) struct UniqueSeqTable<T: PartialEq + Clone> {
42 table: Vec<T>,
43}
44
45impl<T: PartialEq + Clone> UniqueSeqTable<T> {
46 pub fn new() -> Self {
47 Self { table: Vec::new() }
48 }
49 pub fn add(&mut self, values: &[T]) -> usize {
50 if values.is_empty() {
51 return 0;
52 }
53 if let Some(offset) = find_subsequence(values, &self.table) {
54 offset
55 } else {
56 let table_len = self.table.len();
57
58 let mut start_from = usize::min(table_len, values.len() - 1);
64 while start_from != 0 {
65 if values[0..start_from] == self.table[table_len - start_from..table_len] {
67 break;
68 }
69 start_from -= 1;
70 }
71
72 self.table
73 .extend(values[start_from..values.len()].iter().cloned());
74 table_len - start_from
75 }
76 }
77 pub fn len(&self) -> usize {
78 self.table.len()
79 }
80 pub fn iter(&self) -> slice::Iter<T> {
81 self.table.iter()
82 }
83}
84
85fn find_subsequence<T: PartialEq>(sub: &[T], whole: &[T]) -> Option<usize> {
89 assert!(!sub.is_empty());
90 if whole.len() < sub.len() {
92 return None;
93 }
94 let max = whole.len() - sub.len();
95 for i in 0..=max {
96 if whole[i..i + sub.len()] == sub[..] {
97 return Some(i);
98 }
99 }
100 None
101}
102
103#[test]
104fn test_find_subsequence() {
105 assert_eq!(find_subsequence(&vec![1], &vec![4]), None);
106 assert_eq!(find_subsequence(&vec![1], &vec![1]), Some(0));
107 assert_eq!(find_subsequence(&vec![1, 2], &vec![1]), None);
108 assert_eq!(find_subsequence(&vec![1, 2], &vec![1, 2]), Some(0));
109 assert_eq!(find_subsequence(&vec![1, 2], &vec![1, 3]), None);
110 assert_eq!(find_subsequence(&vec![1, 2], &vec![0, 1, 2]), Some(1));
111 assert_eq!(find_subsequence(&vec![1, 2], &vec![0, 1, 3, 1]), None);
112 assert_eq!(find_subsequence(&vec![1, 2], &vec![0, 1, 3, 1, 2]), Some(3));
113 assert_eq!(
114 find_subsequence(&vec![1, 1, 3], &vec![1, 1, 1, 3, 3]),
115 Some(1)
116 );
117}
118
119#[test]
120fn test_optimal_add() {
121 let mut seq_table = UniqueSeqTable::new();
122 assert_eq!(seq_table.add(&vec![0, 1, 2, 3]), 0);
124 assert_eq!(seq_table.add(&vec![0, 1, 2, 3]), 0);
125 assert_eq!(seq_table.add(&vec![1, 2, 3]), 1);
126 assert_eq!(seq_table.add(&vec![2, 3]), 2);
127 assert_eq!(seq_table.len(), 4);
128 assert_eq!(seq_table.add(&vec![2, 3, 4]), 2);
130 assert_eq!(seq_table.len(), 5);
131 assert_eq!(seq_table.add(&vec![4, 6, 5, 7]), 4);
133 assert_eq!(seq_table.len(), 8);
134 assert_eq!(seq_table.add(&vec![8, 2, 3, 4]), 8);
136 assert_eq!(seq_table.add(&vec![8]), 8);
137 assert_eq!(seq_table.len(), 12);
138}