1f1945664SAndrew Brown //! An index-accessed table implementation that avoids duplicate entries.
2393b88afSBenjamin Bouvier use std::collections::HashMap;
3393b88afSBenjamin Bouvier use std::hash::Hash;
4747ad3c4Slazypassion use std::slice;
5747ad3c4Slazypassion
6393b88afSBenjamin Bouvier /// Collect items into the `table` list, removing duplicates.
75889dd2cSBenjamin Bouvier pub(crate) struct UniqueTable<'entries, T: Eq + Hash> {
8393b88afSBenjamin Bouvier table: Vec<&'entries T>,
9393b88afSBenjamin Bouvier map: HashMap<&'entries T, usize>,
10393b88afSBenjamin Bouvier }
11393b88afSBenjamin Bouvier
12393b88afSBenjamin Bouvier impl<'entries, T: Eq + Hash> UniqueTable<'entries, T> {
new() -> Self13393b88afSBenjamin Bouvier pub fn new() -> Self {
14393b88afSBenjamin Bouvier Self {
15393b88afSBenjamin Bouvier table: Vec::new(),
16393b88afSBenjamin Bouvier map: HashMap::new(),
17393b88afSBenjamin Bouvier }
18393b88afSBenjamin Bouvier }
19393b88afSBenjamin Bouvier
add(&mut self, entry: &'entries T) -> usize20393b88afSBenjamin Bouvier pub fn add(&mut self, entry: &'entries T) -> usize {
21393b88afSBenjamin Bouvier match self.map.get(&entry) {
22393b88afSBenjamin Bouvier None => {
23393b88afSBenjamin Bouvier let i = self.table.len();
24393b88afSBenjamin Bouvier self.table.push(entry);
25393b88afSBenjamin Bouvier self.map.insert(entry, i);
26393b88afSBenjamin Bouvier i
27393b88afSBenjamin Bouvier }
28393b88afSBenjamin Bouvier Some(&i) => i,
29393b88afSBenjamin Bouvier }
30393b88afSBenjamin Bouvier }
31393b88afSBenjamin Bouvier
len(&self) -> usize32393b88afSBenjamin Bouvier pub fn len(&self) -> usize {
33393b88afSBenjamin Bouvier self.table.len()
34393b88afSBenjamin Bouvier }
iter(&self) -> slice::Iter<'_, &'entries T>35*8a42768fSAlex Crichton pub fn iter(&self) -> slice::Iter<'_, &'entries T> {
36393b88afSBenjamin Bouvier self.table.iter()
37393b88afSBenjamin Bouvier }
38393b88afSBenjamin Bouvier }
39393b88afSBenjamin Bouvier
40747ad3c4Slazypassion /// A table of sequences which tries to avoid common subsequences.
415889dd2cSBenjamin Bouvier pub(crate) struct UniqueSeqTable<T: PartialEq + Clone> {
42747ad3c4Slazypassion table: Vec<T>,
43747ad3c4Slazypassion }
44747ad3c4Slazypassion
45393b88afSBenjamin Bouvier impl<T: PartialEq + Clone> UniqueSeqTable<T> {
new() -> Self46747ad3c4Slazypassion pub fn new() -> Self {
47747ad3c4Slazypassion Self { table: Vec::new() }
48747ad3c4Slazypassion }
add(&mut self, values: &[T]) -> usize499f506692SPeter Huene pub fn add(&mut self, values: &[T]) -> usize {
509f506692SPeter Huene if values.is_empty() {
51393b88afSBenjamin Bouvier return 0;
52393b88afSBenjamin Bouvier }
53747ad3c4Slazypassion if let Some(offset) = find_subsequence(values, &self.table) {
54747ad3c4Slazypassion offset
55747ad3c4Slazypassion } else {
5684fede89SBenjamin Bouvier let table_len = self.table.len();
5784fede89SBenjamin Bouvier
5884fede89SBenjamin Bouvier // Try to put in common the last elements of the table if they're a prefix of the new
5984fede89SBenjamin Bouvier // sequence.
6084fede89SBenjamin Bouvier //
6184fede89SBenjamin Bouvier // We know there wasn't a full match, so the best prefix we can hope to find contains
6284fede89SBenjamin Bouvier // all the values but the last one.
6384fede89SBenjamin Bouvier let mut start_from = usize::min(table_len, values.len() - 1);
6484fede89SBenjamin Bouvier while start_from != 0 {
6584fede89SBenjamin Bouvier // Loop invariant: start_from <= table_len, so table_len - start_from >= 0.
6684fede89SBenjamin Bouvier if values[0..start_from] == self.table[table_len - start_from..table_len] {
6784fede89SBenjamin Bouvier break;
6884fede89SBenjamin Bouvier }
6984fede89SBenjamin Bouvier start_from -= 1;
7084fede89SBenjamin Bouvier }
7184fede89SBenjamin Bouvier
7284fede89SBenjamin Bouvier self.table
7384fede89SBenjamin Bouvier .extend(values[start_from..values.len()].iter().cloned());
7484fede89SBenjamin Bouvier table_len - start_from
75747ad3c4Slazypassion }
76747ad3c4Slazypassion }
len(&self) -> usize77747ad3c4Slazypassion pub fn len(&self) -> usize {
78747ad3c4Slazypassion self.table.len()
79747ad3c4Slazypassion }
iter(&self) -> slice::Iter<'_, T>80*8a42768fSAlex Crichton pub fn iter(&self) -> slice::Iter<'_, T> {
81747ad3c4Slazypassion self.table.iter()
82747ad3c4Slazypassion }
83747ad3c4Slazypassion }
84747ad3c4Slazypassion
85747ad3c4Slazypassion /// Try to find the subsequence `sub` in the `whole` sequence. Returns None if
86747ad3c4Slazypassion /// it's not been found, or Some(index) if it has been. Naive implementation
87747ad3c4Slazypassion /// until proven we need something better.
find_subsequence<T: PartialEq>(sub: &[T], whole: &[T]) -> Option<usize>889f506692SPeter Huene fn find_subsequence<T: PartialEq>(sub: &[T], whole: &[T]) -> Option<usize> {
899f506692SPeter Huene assert!(!sub.is_empty());
90747ad3c4Slazypassion // We want i + sub.len() <= whole.len(), i.e. i < whole.len() + 1 - sub.len().
91747ad3c4Slazypassion if whole.len() < sub.len() {
92747ad3c4Slazypassion return None;
93747ad3c4Slazypassion }
9484fede89SBenjamin Bouvier let max = whole.len() - sub.len();
959f506692SPeter Huene for i in 0..=max {
9684fede89SBenjamin Bouvier if whole[i..i + sub.len()] == sub[..] {
9784fede89SBenjamin Bouvier return Some(i);
98747ad3c4Slazypassion }
99747ad3c4Slazypassion }
1009f506692SPeter Huene None
101747ad3c4Slazypassion }
102747ad3c4Slazypassion
103747ad3c4Slazypassion #[test]
test_find_subsequence()104747ad3c4Slazypassion fn test_find_subsequence() {
105747ad3c4Slazypassion assert_eq!(find_subsequence(&vec![1], &vec![4]), None);
106747ad3c4Slazypassion assert_eq!(find_subsequence(&vec![1], &vec![1]), Some(0));
107747ad3c4Slazypassion assert_eq!(find_subsequence(&vec![1, 2], &vec![1]), None);
108747ad3c4Slazypassion assert_eq!(find_subsequence(&vec![1, 2], &vec![1, 2]), Some(0));
109747ad3c4Slazypassion assert_eq!(find_subsequence(&vec![1, 2], &vec![1, 3]), None);
110747ad3c4Slazypassion assert_eq!(find_subsequence(&vec![1, 2], &vec![0, 1, 2]), Some(1));
111747ad3c4Slazypassion assert_eq!(find_subsequence(&vec![1, 2], &vec![0, 1, 3, 1]), None);
112747ad3c4Slazypassion assert_eq!(find_subsequence(&vec![1, 2], &vec![0, 1, 3, 1, 2]), Some(3));
113747ad3c4Slazypassion assert_eq!(
114747ad3c4Slazypassion find_subsequence(&vec![1, 1, 3], &vec![1, 1, 1, 3, 3]),
115747ad3c4Slazypassion Some(1)
116747ad3c4Slazypassion );
117747ad3c4Slazypassion }
11884fede89SBenjamin Bouvier
11984fede89SBenjamin Bouvier #[test]
test_optimal_add()12084fede89SBenjamin Bouvier fn test_optimal_add() {
12184fede89SBenjamin Bouvier let mut seq_table = UniqueSeqTable::new();
12284fede89SBenjamin Bouvier // [0, 1, 2, 3]
12384fede89SBenjamin Bouvier assert_eq!(seq_table.add(&vec![0, 1, 2, 3]), 0);
12484fede89SBenjamin Bouvier assert_eq!(seq_table.add(&vec![0, 1, 2, 3]), 0);
12584fede89SBenjamin Bouvier assert_eq!(seq_table.add(&vec![1, 2, 3]), 1);
12684fede89SBenjamin Bouvier assert_eq!(seq_table.add(&vec![2, 3]), 2);
12784fede89SBenjamin Bouvier assert_eq!(seq_table.len(), 4);
12884fede89SBenjamin Bouvier // [0, 1, 2, 3, 4]
12984fede89SBenjamin Bouvier assert_eq!(seq_table.add(&vec![2, 3, 4]), 2);
13084fede89SBenjamin Bouvier assert_eq!(seq_table.len(), 5);
13184fede89SBenjamin Bouvier // [0, 1, 2, 3, 4, 6, 5, 7]
13284fede89SBenjamin Bouvier assert_eq!(seq_table.add(&vec![4, 6, 5, 7]), 4);
13384fede89SBenjamin Bouvier assert_eq!(seq_table.len(), 8);
13484fede89SBenjamin Bouvier // [0, 1, 2, 3, 4, 6, 5, 7, 8, 2, 3, 4]
13584fede89SBenjamin Bouvier assert_eq!(seq_table.add(&vec![8, 2, 3, 4]), 8);
13684fede89SBenjamin Bouvier assert_eq!(seq_table.add(&vec![8]), 8);
13784fede89SBenjamin Bouvier assert_eq!(seq_table.len(), 12);
13884fede89SBenjamin Bouvier }
139