1use std::borrow::Borrow;
2use std::collections::HashMap;
3use std::hash::Hash;
4use std::iter::FusedIterator;
5use std::marker::PhantomData;
6use std::ops::Index;
7use std::ops::IndexMut;
8
9pub struct TrieMap<K, V, A = u8> {
10 _key: PhantomData<K>,
11 val: Option<V>,
12 subtrie: HashMap<A, TrieMap<K, V, A>>,
13 len: usize,
14}
15
16impl<K, V, A: Clone + Eq + Hash> TrieMap<K, V, A> {
17 pub fn new() -> Self {
18 Self::default()
19 }
20
21 pub fn clear(&mut self) {
22 self.val.take();
23 self.subtrie.clear();
24 self.len = 0;
25 }
26
27 pub fn contains<T: AsRef<[A]> + ?Sized>(&self, key: &T) -> bool
28 where K: Borrow<T> {
29 self.get(key).is_some()
30 }
31
32 pub fn get<T: AsRef<[A]> + ?Sized>(&self, key: &T) -> Option<&V>
33 where K: Borrow<T> {
34 self.get_helper(key.as_ref())
35 }
36
37 pub fn get_mut<T: AsRef<[A]> + ?Sized>(&mut self, key: &T) -> Option<&mut V>
38 where K: Borrow<T> {
39 self.get_mut_helper(key.as_ref())
40 }
41
42 pub fn insert<T: AsRef<[A]> + ?Sized>(&mut self, key: &T, val: V) -> Option<V>
43 where K: Borrow<T> {
44 self.insert_helper(key.as_ref(), val)
45 }
46
47 pub fn is_empty(&self) -> bool {
48 self.len == 0
49 }
50
51 pub fn iter(&self) -> Iter<&V> {
52 self.iter_helper(&[])
53 }
54
55 pub fn iter_mut(&mut self) -> Iter<&mut V> {
56 self.iter_mut_helper(&[])
57 }
58
59 pub fn iter_prefix<T: AsRef<[A]> + ?Sized>(&self, prefix: &T) -> Iter<&V>
60 where K: Borrow<T> {
61 self.iter_helper(prefix.as_ref())
62 }
63
64 pub fn iter_prefix_mut<T: AsRef<[A]> + ?Sized>(&mut self, prefix: &T) -> Iter<&mut V>
65 where K: Borrow<T> {
66 self.iter_mut_helper(prefix.as_ref())
67 }
68
69 pub fn len(&self) -> usize {
70 self.len
71 }
72
73 fn get_helper(&self, key: &[A]) -> Option<&V> {
74 if let Some(atom) = key.first() {
75 self.subtrie.get(atom)?.get_helper(&key[1..])
76 } else {
77 self.val.as_ref()
78 }
79 }
80
81 fn get_mut_helper(&mut self, key: &[A]) -> Option<&mut V> {
82 if let Some(atom) = key.first() {
83 self.subtrie.get_mut(atom)?.get_mut_helper(&key[1..])
84 } else {
85 self.val.as_mut()
86 }
87 }
88
89 fn insert_helper(&mut self, key: &[A], val: V) -> Option<V> {
90 let existing = if let Some(atom) = key.first().cloned() {
91 self.subtrie.entry(atom).or_default().insert_helper(&key[1..], val)
92 } else {
93 self.val.replace(val)
94 };
95
96 if existing.is_none() {
97 self.len += 1;
98 }
99
100 existing
101 }
102
103 fn iter_helper(&self, key: &[A]) -> Iter<&V> {
104 use std::iter;
105
106 if let Some(atom) = key.first() {
107 if let Some(subtrie) = self.subtrie.get(atom) {
108 subtrie.iter_helper(&key[1..])
109 } else {
110 Box::new(iter::empty())
111 }
112 } else {
113 Box::new(self.val.iter().chain(self.subtrie.iter().flat_map(|(_, subtrie)|
114 subtrie.iter_helper(&[]))
115 ))
116 }
117 }
118
119 fn iter_mut_helper(&mut self, key: &[A]) -> Iter<&mut V> {
120 use std::iter;
121
122 if let Some(atom) = key.first() {
123 if let Some(subtrie) = self.subtrie.get_mut(atom) {
124 subtrie.iter_mut_helper(&key[1..])
125 } else {
126 Box::new(iter::empty())
127 }
128 } else {
129 Box::new(self.val.iter_mut().chain(self.subtrie.iter_mut().flat_map(|(_, subtrie)|
130 subtrie.iter_mut_helper(&[]))
131 ))
132 }
133 }
134}
135
136impl<K, V, A: Clone + Eq + Hash> Default for TrieMap<K, V, A> {
137 fn default() -> Self {
138 Self {
139 _key: PhantomData::default(),
140 val: None,
141 subtrie: HashMap::default(),
142 len: 0,
143 }
144 }
145}
146
147impl<A: Clone + Eq + Hash, T: AsRef<[A]> + ?Sized, K: Borrow<T>, V> Index<&T> for TrieMap<K, V, A> {
148 type Output = V;
149
150 fn index(&self, key: &T) -> &Self::Output {
151 self.get(key).unwrap()
152 }
153}
154
155impl<A: Clone + Eq + Hash, T: AsRef<[A]> + ?Sized, K: Borrow<T>, V> IndexMut<&T> for TrieMap<K, V, A> {
156 fn index_mut(&mut self, key: &T) -> &mut Self::Output {
157 self.get_mut(key).unwrap()
158 }
159}
160
161pub type Iter<'a, T> = Box<dyn FusedIterator<Item = T> + 'a>;