1use crate::FxHashMap;
4use std::hash::{BuildHasher, Hash};
5
6#[derive(Clone, Debug)]
13pub struct SetTrie<K, V> {
14 next: FxHashMap<K, SetTrie<K, V>>,
15 value: Option<V>,
16}
17
18impl<K, V> Default for SetTrie<K, V> {
19 fn default() -> Self {
20 Self {
21 next: FxHashMap::default(),
22 value: None,
23 }
24 }
25}
26
27impl<K, V> SetTrie<K, V>
28where
29 K: Clone + Eq + Hash,
30{
31 pub fn new() -> Self {
33 Self::default()
34 }
35
36 pub fn get_or_insert_with(&mut self, key: &[K], make: impl FnOnce() -> V) -> &mut V {
38 let mut node = self;
39 for part in key {
40 node = node.next.entry(part.clone()).or_default();
41 }
42 node.value.get_or_insert_with(make)
43 }
44
45 pub fn get(&self, key: &[K]) -> Option<&V> {
47 let mut node = self;
48 for part in key {
49 node = node.next.get(part)?;
50 }
51 node.value.as_ref()
52 }
53
54 pub fn for_each_value_for_key_sets<S>(&self, key_sets: &[S], mut out: impl FnMut(&V))
59 where
60 S: KeySet<K>,
61 {
62 self.for_each_value_for_key_sets_at(0, key_sets, &mut out);
63 }
64
65 pub fn for_each_value_for_prefix_and_key_sets<S>(
68 &self,
69 prefix: &[K],
70 key_sets: &[S],
71 mut out: impl FnMut(&V),
72 ) where
73 S: KeySet<K>,
74 {
75 let mut node = self;
76 for part in prefix {
77 let Some(next) = node.next.get(part) else {
78 return;
79 };
80 node = next;
81 }
82 node.for_each_value_for_key_sets_at(0, key_sets, &mut out);
83 }
84
85 fn for_each_value_for_key_sets_at<S>(
86 &self,
87 depth: usize,
88 key_sets: &[S],
89 out: &mut dyn FnMut(&V),
90 ) where
91 S: KeySet<K>,
92 {
93 if depth == key_sets.len() {
94 if let Some(value) = &self.value {
95 out(value);
96 }
97 return;
98 }
99
100 let keys = &key_sets[depth];
101 if keys.len() < self.next.len() {
102 keys.for_each(&mut |key| {
103 if let Some(next) = self.next.get(key) {
104 next.for_each_value_for_key_sets_at(depth + 1, key_sets, out);
105 }
106 });
107 } else {
108 for (key, next) in &self.next {
109 if keys.contains(key) {
110 next.for_each_value_for_key_sets_at(depth + 1, key_sets, out);
111 }
112 }
113 }
114 }
115}
116
117pub trait KeySet<K> {
119 fn len(&self) -> usize;
121
122 fn is_empty(&self) -> bool {
124 self.len() == 0
125 }
126
127 fn contains(&self, key: &K) -> bool;
129
130 fn for_each(&self, out: &mut dyn FnMut(&K));
132}
133
134impl<K, S> KeySet<K> for hashbrown::HashSet<K, S>
135where
136 K: Eq + Hash,
137 S: BuildHasher,
138{
139 fn len(&self) -> usize {
140 self.len()
141 }
142
143 fn contains(&self, key: &K) -> bool {
144 self.contains(key)
145 }
146
147 fn for_each(&self, out: &mut dyn FnMut(&K)) {
148 for key in self {
149 out(key);
150 }
151 }
152}
153
154impl<K, T> KeySet<K> for &T
155where
156 T: KeySet<K> + ?Sized,
157{
158 fn len(&self) -> usize {
159 (**self).len()
160 }
161
162 fn contains(&self, key: &K) -> bool {
163 (**self).contains(key)
164 }
165
166 fn for_each(&self, out: &mut dyn FnMut(&K)) {
167 (**self).for_each(out);
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174 use crate::FxHashSet;
175
176 #[test]
177 fn visits_values_matching_key_sets() {
178 let mut trie = SetTrie::new();
179 trie.get_or_insert_with(&[1, 2], Vec::new).push("a");
180 trie.get_or_insert_with(&[1, 3], Vec::new).push("b");
181 trie.get_or_insert_with(&[4, 2], Vec::new).push("c");
182
183 let first = FxHashSet::from_iter([1]);
184 let second = FxHashSet::from_iter([2, 3]);
185 let mut values = Vec::new();
186 trie.for_each_value_for_key_sets(&[&first, &second], |found| {
187 values.extend(found.iter().copied());
188 });
189 values.sort_unstable();
190
191 assert_eq!(values, vec!["a", "b"]);
192 }
193
194 #[test]
195 fn visits_values_matching_prefix_and_key_sets() {
196 let mut trie = SetTrie::new();
197 trie.get_or_insert_with(&[1, 2], Vec::new).push("a");
198 trie.get_or_insert_with(&[1, 3], Vec::new).push("b");
199 trie.get_or_insert_with(&[4, 2], Vec::new).push("c");
200
201 let second = FxHashSet::from_iter([2, 3]);
202 let mut values = Vec::new();
203 trie.for_each_value_for_prefix_and_key_sets(&[1], &[&second], |found| {
204 values.extend(found.iter().copied());
205 });
206 values.sort_unstable();
207
208 assert_eq!(values, vec!["a", "b"]);
209 }
210}