prust_lib/
trie.rs

1use crate::RefCounter;
2pub struct Trie<T = u8, U = bool> {
3    pub(crate) stored_value: Vec<RefCounter<U>>,
4    pub(crate) adjecent_nodes: Vec<(T, RefCounter<Trie<T, U>>)>,
5}
6
7impl<T: Clone, U> Clone for Trie<T, U> {
8    fn clone(&self) -> Self {
9        Self {
10            stored_value: self.stored_value.clone(),
11            adjecent_nodes: self.adjecent_nodes.clone(),
12        }
13    }
14}
15
16impl<T: PartialEq + Clone, U> Trie<T, U> {
17    pub(crate) fn empty_store() -> Trie<T, U> {
18        Trie {
19            stored_value: Vec::new(),
20            adjecent_nodes: Vec::new(),
21        }
22    }
23    pub fn empty() -> Trie<T, U> {
24        Trie {
25            stored_value: Vec::new(),
26            adjecent_nodes: Vec::new(),
27        }
28    }
29    pub fn insert_store<Slc: AsRef<[T]>>(&self, value: Slc, store: U) -> Self {
30        let value_ref = value.as_ref();
31        let mut new_trie = self.clone();
32        if value_ref.is_empty() {
33            new_trie.stored_value.push(RefCounter::new(store));
34            return new_trie;
35        }
36        let head = &value_ref[0];
37        let tail = &value_ref[1..];
38        for (k, v) in new_trie.adjecent_nodes.iter_mut() {
39            if k == head {
40                *v = RefCounter::new(v.insert_store(tail, store));
41                return new_trie;
42            }
43        }
44        new_trie.adjecent_nodes.push((
45            head.clone(),
46            RefCounter::new(Trie::empty_store().insert_store(tail, store)),
47        ));
48        new_trie
49    }
50    pub fn get_store<Slc: AsRef<[T]>>(&self, value: Slc) -> Option<Box<[&U]>> {
51        let value_ref = value.as_ref();
52        if value_ref.is_empty() {
53            let mut vr = Vec::new();
54            for v in self.stored_value.iter() {
55                vr.push(v.as_ref());
56            }
57            if vr.is_empty() {
58                return Option::None;
59            }
60            return Option::Some(vr.into_boxed_slice());
61        }
62        let head = &value_ref[0];
63        let tail = &value_ref[1..];
64        for (k, v) in &self.adjecent_nodes {
65            if k == head {
66                return v.get_store(tail);
67            }
68        }
69        return Option::None;
70    }
71}
72
73impl<T: PartialEq + Clone, U: PartialEq> Trie<T, U> {
74    pub fn delete_store<Slc: AsRef<[T]>>(&self, value: Slc, store: &U) -> Option<Self> {
75        let value_ref = value.as_ref();
76        let mut new_trie = self.clone();
77        if value_ref.is_empty() {
78            new_trie.stored_value.retain(|v| {
79                let retain = v.as_ref() != store;
80                retain
81            });
82            if self.stored_value.len() == new_trie.stored_value.len() {
83                return Option::None;
84            } else {
85                return Option::Some(new_trie);
86            }
87        }
88        let head = &value_ref[0];
89        let tail = &value_ref[1..];
90        for (k, v) in new_trie.adjecent_nodes.iter_mut() {
91            if k == head {
92                let subt = v.delete_store(tail, store)?;
93                *v = RefCounter::new(subt);
94                return Option::Some(new_trie);
95            }
96        }
97        return Option::None;
98    }
99}
100
101impl<T: PartialEq + Copy> Trie<T> {
102    pub fn insert<Slc: AsRef<[T]>>(&self, value: Slc) -> Self {
103        self.insert_store(value, true)
104    }
105    pub fn search<Slc: AsRef<[T]>>(&self, value: Slc) -> bool {
106        self.get_store(value).is_some()
107    }
108    pub fn delete<Slc: AsRef<[T]>>(&self, value: Slc) -> Option<Self> {
109        self.delete_store(value, &true)
110    }
111}
112
113#[cfg(test)]
114mod tests {
115
116    use std::vec;
117
118    use super::*;
119
120    #[test]
121    fn test_trie_store() {
122        let t = Trie::empty_store().insert_store("aab", 123);
123        let t2 = t.insert_store("adc", 459);
124        let boxed_array: Box<[&i32]> = Box::new([&123]);
125        let boxed_array_2: Box<[&i32]> = Box::new([&459]);
126        assert_eq!(t.get_store("aab"), Option::Some(boxed_array.clone()));
127        assert!(t.get_store("adc").is_none());
128        assert_eq!(t2.get_store("aab"), Option::Some(boxed_array));
129        assert_eq!(t2.get_store("adc"), Option::Some(boxed_array_2));
130    }
131
132    #[test]
133    fn test_trie_persistance_simple() {
134        let t = Trie::empty().insert("aab").insert("adc");
135        assert!(t.search("aab"));
136        assert!(t.search("adc"));
137    }
138
139    #[test]
140    fn test_trie_persistance() {
141        let vs = vec!["aab", "adc", "acd", "dca"];
142        let snapshots: Vec<_> = vs
143            .iter()
144            .scan(Trie::empty(), |tree, value| {
145                *tree = tree.insert(value);
146                Option::Some(tree.clone())
147            })
148            .collect();
149        for (index, tree) in snapshots.iter().enumerate() {
150            let found = vs
151                .iter()
152                .map(|s| tree.search(s))
153                .filter(|found| *found == true)
154                .count();
155            assert_eq!(found, index + 1);
156        }
157    }
158
159    #[test]
160    fn test_search_present() {
161        let v = vec![1, 5, 9];
162        let not_v = vec![1, 15, 9];
163        let t = Trie::empty().insert(&v);
164        assert!(t.search(v));
165        assert!(!t.search(not_v));
166    }
167
168    #[test]
169    fn test_search_absent() {
170        let s = "test";
171        let not_s = "tett";
172        let t = Trie::empty().insert(s);
173        assert!(t.search(s));
174        assert!(!t.search(not_s));
175    }
176
177    #[test]
178    fn test_trie_deletion() {
179        let t = Trie::empty().insert("aab").delete("aab");
180        assert!(t.is_some());
181        assert_eq!(t.unwrap().search("aab"), false);
182        let t2 = Trie::empty();
183        assert!(t2.delete("a").is_none());
184    }
185
186    #[test]
187    fn test_insert_empty_string() {
188        let t = Trie::empty().insert("");
189        assert!(t.search(""));
190    }
191
192    #[test]
193    fn test_multiple_values_for_same_key() {
194        let t = Trie::empty_store()
195            .insert_store("key", 1)
196            .insert_store("key", 2);
197        let values = t.get_store("key").unwrap();
198        assert!(values.contains(&&1) && values.contains(&&2));
199    }
200
201    #[test]
202    fn test_delete_internal_node() {
203        let t = Trie::empty()
204            .insert("abc")
205            .insert("ab")
206            .delete("ab")
207            .unwrap();
208        assert!(!t.search("ab"));
209        assert!(t.search("abc"));
210    }
211
212    #[test]
213    fn test_persistence_after_delete() {
214        let t1 = Trie::empty().insert("key");
215        let t2 = t1.delete("key").unwrap_or_else(|| t1.clone());
216        assert!(t1.search("key"));
217        assert!(!t2.search("key"));
218    }
219
220    #[test]
221    fn test_search_nonexistent_key() {
222        let t = Trie::empty().insert("key");
223        assert!(!t.search("not_key"));
224    }
225
226    #[test]
227    fn test_delete_nonexistent_key() {
228        let t = Trie::empty().insert("key");
229        assert!(t.delete("not_key").is_none());
230    }
231
232    #[test]
233    fn test_readme() {
234        // Insert words
235        let mut trie = Trie::empty().insert("apple").insert("app").insert("banana");
236
237        // Snapshot the current trie. This operation is lightweight, allocating only a couple of bytes long.
238        let snapshot = trie.clone();
239
240        // Insert more words
241        trie = trie.insert("grape").insert("banana-split");
242
243        // Check for words in current trie
244        assert_eq!(trie.search("grape"), true);
245
246        // Restore trie to a previous of moment in time
247        trie = snapshot;
248
249        // Word was not present at snapshop moment
250        assert_eq!(trie.search("grape"), false);
251    }
252}