1use std::collections::HashMap;
20
21struct TrieNode<V> {
31 fragment: String,
33 value: Option<V>,
36 children: HashMap<u8, Box<TrieNode<V>>>,
38}
39
40impl<V> TrieNode<V> {
41 fn new(fragment: String, value: Option<V>) -> Self {
42 TrieNode {
43 fragment,
44 value,
45 children: HashMap::new(),
46 }
47 }
48
49 fn is_leaf(&self) -> bool {
50 self.children.is_empty()
51 }
52}
53
54pub struct CompressedTrie<V> {
81 root: TrieNode<V>,
82 len: usize,
83}
84
85impl<V> CompressedTrie<V> {
86 pub fn new() -> Self {
88 CompressedTrie {
89 root: TrieNode::new(String::new(), None),
90 len: 0,
91 }
92 }
93
94 pub fn len(&self) -> usize {
96 self.len
97 }
98
99 pub fn is_empty(&self) -> bool {
101 self.len == 0
102 }
103
104 pub fn insert(&mut self, key: &str, value: V) -> Option<V> {
109 let old = Self::insert_recursive(&mut self.root, key, value);
110 if old.is_none() {
111 self.len += 1;
112 }
113 old
114 }
115
116 fn insert_recursive(node: &mut TrieNode<V>, key: &str, value: V) -> Option<V> {
117 if key.is_empty() {
118 return node.value.replace(value);
120 }
121
122 let first_byte = key.as_bytes()[0];
123
124 if let Some(child) = node.children.get_mut(&first_byte) {
125 let common = common_prefix_len(&child.fragment, key);
126
127 if common == child.fragment.len() {
128 return Self::insert_recursive(child, &key[common..], value);
130 }
131
132 let child_remaining = child.fragment[common..].to_string();
134 let key_remaining = &key[common..];
135
136 let mut split_node = TrieNode::new(child.fragment[..common].to_string(), None);
138
139 let mut old_child = node.children.remove(&first_byte).expect("child must exist");
141 old_child.fragment = child_remaining.clone();
142 let old_first_byte = if child_remaining.is_empty() {
143 0u8
147 } else {
148 child_remaining.as_bytes()[0]
149 };
150 split_node.children.insert(old_first_byte, old_child);
151
152 if key_remaining.is_empty() {
153 split_node.value = Some(value);
154 } else {
155 let new_child = TrieNode::new(key_remaining.to_string(), Some(value));
156 split_node
157 .children
158 .insert(key_remaining.as_bytes()[0], Box::new(new_child));
159 }
160
161 node.children.insert(first_byte, Box::new(split_node));
162 None
163 } else {
164 let new_node = TrieNode::new(key.to_string(), Some(value));
166 node.children.insert(first_byte, Box::new(new_node));
167 None
168 }
169 }
170
171 pub fn get(&self, key: &str) -> Option<&V> {
173 Self::get_recursive(&self.root, key)
174 }
175
176 fn get_recursive<'a>(node: &'a TrieNode<V>, key: &str) -> Option<&'a V> {
177 if key.is_empty() {
178 return node.value.as_ref();
179 }
180
181 let first_byte = key.as_bytes()[0];
182 let child = node.children.get(&first_byte)?;
183 let common = common_prefix_len(&child.fragment, key);
184
185 if common < child.fragment.len() {
186 return None;
188 }
189
190 Self::get_recursive(child, &key[common..])
191 }
192
193 pub fn remove(&mut self, key: &str) -> Option<V> {
195 let removed = Self::remove_recursive(&mut self.root, key);
196 if removed.is_some() {
197 self.len -= 1;
198 }
199 removed
200 }
201
202 fn remove_recursive(node: &mut TrieNode<V>, key: &str) -> Option<V> {
203 if key.is_empty() {
204 return node.value.take();
205 }
206
207 let first_byte = key.as_bytes()[0];
208
209 let child = node.children.get_mut(&first_byte)?;
212 let common = common_prefix_len(&child.fragment, key);
213 if common < child.fragment.len() {
214 return None;
215 }
216
217 let removed = Self::remove_recursive(child, &key[common..]);
218 removed.as_ref()?;
219
220 let child = match node.children.get(&first_byte) {
222 Some(c) => c,
223 None => return removed,
224 };
225
226 if child.value.is_none() && child.children.is_empty() {
227 node.children.remove(&first_byte);
229 } else if child.value.is_none() && child.children.len() == 1 {
230 let mut child = node.children.remove(&first_byte).expect("child exists");
232 let (_, grandchild) = child.children.drain().next().expect("one grandchild");
233 let merged_fragment = format!("{}{}", child.fragment, grandchild.fragment);
234 let mut merged = grandchild;
235 merged.fragment = merged_fragment;
236 let new_first = if merged.fragment.is_empty() {
237 first_byte
238 } else {
239 merged.fragment.as_bytes()[0]
240 };
241 node.children.insert(new_first, merged);
242 }
243
244 removed
245 }
246
247 pub fn prefix_search(&self, prefix: &str) -> Vec<(String, &V)> {
251 let mut results = Vec::new();
252 self.prefix_search_inner(&self.root, prefix, String::new(), &mut results);
253 results
254 }
255
256 fn prefix_search_inner<'a>(
257 &'a self,
258 node: &'a TrieNode<V>,
259 remaining_prefix: &str,
260 accumulated_key: String,
261 results: &mut Vec<(String, &'a V)>,
262 ) {
263 if remaining_prefix.is_empty() {
264 self.collect_all(node, &accumulated_key, results);
266 return;
267 }
268
269 let first_byte = remaining_prefix.as_bytes()[0];
270 let child = match node.children.get(&first_byte) {
271 Some(c) => c,
272 None => return,
273 };
274
275 let common = common_prefix_len(&child.fragment, remaining_prefix);
276
277 if common < child.fragment.len() && common < remaining_prefix.len() {
278 return;
280 }
281
282 if common >= remaining_prefix.len() {
283 let new_key = format!("{}{}", accumulated_key, child.fragment);
286 self.collect_all(child, &new_key, results);
287 } else {
288 let new_key = format!("{}{}", accumulated_key, child.fragment);
290 self.prefix_search_inner(child, &remaining_prefix[common..], new_key, results);
291 }
292 }
293
294 fn collect_all<'a>(
295 &'a self,
296 node: &'a TrieNode<V>,
297 current_key: &str,
298 results: &mut Vec<(String, &'a V)>,
299 ) {
300 if let Some(ref v) = node.value {
301 results.push((current_key.to_string(), v));
302 }
303 for child in node.children.values() {
304 let child_key = format!("{}{}", current_key, child.fragment);
305 self.collect_all(child, &child_key, results);
306 }
307 }
308
309 pub fn longest_prefix(&self, key: &str) -> Option<(String, &V)> {
313 let mut best: Option<(String, &V)> = None;
314 self.longest_prefix_inner(&self.root, key, String::new(), &mut best);
315 best
316 }
317
318 fn longest_prefix_inner<'a>(
319 &'a self,
320 node: &'a TrieNode<V>,
321 remaining: &str,
322 accumulated: String,
323 best: &mut Option<(String, &'a V)>,
324 ) {
325 if let Some(ref v) = node.value {
327 *best = Some((accumulated.clone(), v));
328 }
329
330 if remaining.is_empty() {
331 return;
332 }
333
334 let first_byte = remaining.as_bytes()[0];
335 let child = match node.children.get(&first_byte) {
336 Some(c) => c,
337 None => return,
338 };
339
340 let common = common_prefix_len(&child.fragment, remaining);
341 if common < child.fragment.len() {
342 return;
345 }
346
347 let new_acc = format!("{}{}", accumulated, child.fragment);
348 self.longest_prefix_inner(child, &remaining[common..], new_acc, best);
349 }
350
351 pub fn keys(&self) -> Vec<String> {
353 let mut result = Vec::with_capacity(self.len);
354 self.collect_keys(&self.root, "", &mut result);
355 result
356 }
357
358 fn collect_keys(&self, node: &TrieNode<V>, prefix: &str, result: &mut Vec<String>) {
359 if node.value.is_some() {
360 result.push(prefix.to_string());
361 }
362 for child in node.children.values() {
363 let child_key = format!("{}{}", prefix, child.fragment);
364 self.collect_keys(child, &child_key, result);
365 }
366 }
367
368 pub fn contains(&self, key: &str) -> bool {
370 self.get(key).is_some()
371 }
372}
373
374impl<V> Default for CompressedTrie<V> {
375 fn default() -> Self {
376 Self::new()
377 }
378}
379
380fn common_prefix_len(a: &str, b: &str) -> usize {
386 a.bytes().zip(b.bytes()).take_while(|(x, y)| x == y).count()
387}
388
389#[cfg(test)]
394mod tests {
395 use super::*;
396
397 #[test]
398 fn test_insert_and_get() {
399 let mut trie = CompressedTrie::new();
400 trie.insert("hello", 1);
401 trie.insert("help", 2);
402 trie.insert("world", 3);
403
404 assert_eq!(trie.get("hello"), Some(&1));
405 assert_eq!(trie.get("help"), Some(&2));
406 assert_eq!(trie.get("world"), Some(&3));
407 assert_eq!(trie.get("hel"), None);
408 assert_eq!(trie.get("xyz"), None);
409 assert_eq!(trie.len(), 3);
410 }
411
412 #[test]
413 fn test_prefix_search() {
414 let mut trie = CompressedTrie::new();
415 trie.insert("apple", 1);
416 trie.insert("application", 2);
417 trie.insert("apply", 3);
418 trie.insert("banana", 4);
419
420 let results = trie.prefix_search("app");
421 assert_eq!(results.len(), 3);
422 let mut keys: Vec<String> = results.iter().map(|(k, _)| k.clone()).collect();
423 keys.sort();
424 assert_eq!(keys, vec!["apple", "application", "apply"]);
425
426 let results2 = trie.prefix_search("ban");
427 assert_eq!(results2.len(), 1);
428 assert_eq!(results2[0].0, "banana");
429
430 let results3 = trie.prefix_search("xyz");
431 assert!(results3.is_empty());
432 }
433
434 #[test]
435 fn test_longest_prefix() {
436 let mut trie = CompressedTrie::new();
437 trie.insert("/", "root");
438 trie.insert("/api", "api");
439 trie.insert("/api/v1", "api_v1");
440 trie.insert("/api/v1/users", "users");
441
442 let result = trie.longest_prefix("/api/v1/users/123");
443 assert!(result.is_some());
444 let (prefix, val) = result.expect("should find a match");
445 assert_eq!(prefix, "/api/v1/users");
446 assert_eq!(*val, "users");
447
448 let result2 = trie.longest_prefix("/api/v2/data");
449 assert!(result2.is_some());
450 let (prefix2, val2) = result2.expect("should find /api");
451 assert_eq!(prefix2, "/api");
452 assert_eq!(*val2, "api");
453
454 let result3 = trie.longest_prefix("/other");
455 assert!(result3.is_some());
456 let (prefix3, _) = result3.expect("should find /");
457 assert_eq!(prefix3, "/");
458
459 let mut trie2: CompressedTrie<i32> = CompressedTrie::new();
461 trie2.insert("abc", 1);
462 assert!(trie2.longest_prefix("xyz").is_none());
463 }
464
465 #[test]
466 fn test_remove() {
467 let mut trie = CompressedTrie::new();
468 trie.insert("hello", 1);
469 trie.insert("help", 2);
470 trie.insert("world", 3);
471
472 assert_eq!(trie.remove("hello"), Some(1));
473 assert_eq!(trie.get("hello"), None);
474 assert_eq!(trie.len(), 2);
475 assert_eq!(trie.get("help"), Some(&2));
477
478 assert_eq!(trie.remove("nonexistent"), None);
479 assert_eq!(trie.len(), 2);
480 }
481
482 #[test]
483 fn test_path_compression() {
484 let mut trie = CompressedTrie::new();
485 trie.insert("abcdefghij", 1);
487 assert_eq!(trie.get("abcdefghij"), Some(&1));
488 assert_eq!(trie.len(), 1);
489
490 trie.insert("abcde12345", 2);
492 assert_eq!(trie.get("abcdefghij"), Some(&1));
493 assert_eq!(trie.get("abcde12345"), Some(&2));
494 assert_eq!(trie.len(), 2);
495 }
496
497 #[test]
498 fn test_empty_trie() {
499 let trie: CompressedTrie<i32> = CompressedTrie::new();
500 assert!(trie.is_empty());
501 assert_eq!(trie.len(), 0);
502 assert_eq!(trie.get("anything"), None);
503 assert!(trie.keys().is_empty());
504 assert!(trie.prefix_search("").is_empty());
505 assert!(trie.longest_prefix("test").is_none());
506 }
507
508 #[test]
509 fn test_keys() {
510 let mut trie = CompressedTrie::new();
511 trie.insert("cat", 1);
512 trie.insert("car", 2);
513 trie.insert("card", 3);
514 trie.insert("dog", 4);
515
516 let mut keys = trie.keys();
517 keys.sort();
518 assert_eq!(keys, vec!["car", "card", "cat", "dog"]);
519 }
520
521 #[test]
522 fn test_overwrite_value() {
523 let mut trie = CompressedTrie::new();
524 let old = trie.insert("key", 1);
525 assert!(old.is_none());
526
527 let old2 = trie.insert("key", 2);
528 assert_eq!(old2, Some(1));
529 assert_eq!(trie.get("key"), Some(&2));
530 assert_eq!(trie.len(), 1); }
532
533 #[test]
534 fn test_single_char_keys() {
535 let mut trie = CompressedTrie::new();
536 trie.insert("a", 1);
537 trie.insert("b", 2);
538 trie.insert("c", 3);
539
540 assert_eq!(trie.get("a"), Some(&1));
541 assert_eq!(trie.get("b"), Some(&2));
542 assert_eq!(trie.get("c"), Some(&3));
543 assert_eq!(trie.len(), 3);
544 }
545
546 #[test]
547 fn test_contains() {
548 let mut trie = CompressedTrie::new();
549 trie.insert("foo", 1);
550 assert!(trie.contains("foo"));
551 assert!(!trie.contains("bar"));
552 }
553
554 #[test]
555 fn test_prefix_search_with_exact_prefix_match() {
556 let mut trie = CompressedTrie::new();
557 trie.insert("test", 1);
558 trie.insert("testing", 2);
559 trie.insert("tester", 3);
560
561 let results = trie.prefix_search("test");
563 assert_eq!(results.len(), 3);
564 }
565
566 #[test]
567 fn test_remove_with_merge() {
568 let mut trie = CompressedTrie::new();
569 trie.insert("abc", 1);
570 trie.insert("abcdef", 2);
571 trie.insert("abcxyz", 3);
572
573 trie.remove("abc");
576 assert_eq!(trie.get("abcdef"), Some(&2));
577 assert_eq!(trie.get("abcxyz"), Some(&3));
578 assert_eq!(trie.len(), 2);
579 }
580
581 #[test]
582 fn test_empty_string_key() {
583 let mut trie = CompressedTrie::new();
584 trie.insert("", 42);
585 assert_eq!(trie.get(""), Some(&42));
586 assert_eq!(trie.len(), 1);
587
588 trie.insert("a", 1);
589 assert_eq!(trie.len(), 2);
590 assert_eq!(trie.get(""), Some(&42));
591
592 let results = trie.prefix_search("");
594 assert_eq!(results.len(), 2);
595 }
596}