1use super::ConnectionId;
2use std::collections::HashMap;
3
4pub struct PatternTrie {
5 root: TrieNode,
6}
7
8impl Default for PatternTrie {
9 fn default() -> Self {
10 Self::new()
11 }
12}
13
14struct TrieNode {
15 children: HashMap<u8, Box<TrieNode>>,
16 wildcard_child: Option<Box<TrieNode>>,
17 single_char_child: Option<Box<TrieNode>>,
18 char_class_child: Option<Box<CharClassNode>>,
19 subscribers: Vec<(Vec<u8>, ConnectionId)>,
20}
21
22struct CharClassNode {
23 chars: Vec<u8>,
24 negated: bool,
25 next: Box<TrieNode>,
26}
27
28impl PatternTrie {
29 pub fn new() -> Self {
30 Self {
31 root: TrieNode::new(),
32 }
33 }
34
35 pub fn insert(&mut self, pattern: &[u8], conn_id: ConnectionId) {
36 let mut node = &mut self.root;
37 let mut i = 0;
38
39 while i < pattern.len() {
40 match pattern[i] {
41 b'*' => {
42 if node.wildcard_child.is_none() {
43 node.wildcard_child = Some(Box::new(TrieNode::new()));
44 }
45 node = node.wildcard_child.as_mut().unwrap();
46 i += 1;
47 }
48 b'?' => {
49 if node.single_char_child.is_none() {
50 node.single_char_child = Some(Box::new(TrieNode::new()));
51 }
52 node = node.single_char_child.as_mut().unwrap();
53 i += 1;
54 }
55 b'[' => {
56 let (char_class, next_i) = parse_char_class(&pattern[i..]);
57 if let Some((chars, negated)) = char_class {
58 if node.char_class_child.is_none() {
59 node.char_class_child = Some(Box::new(CharClassNode {
60 chars,
61 negated,
62 next: Box::new(TrieNode::new()),
63 }));
64 }
65 node = &mut node.char_class_child.as_mut().unwrap().next;
66 i += next_i;
67 } else {
68 node = node
69 .children
70 .entry(pattern[i])
71 .or_insert_with(|| Box::new(TrieNode::new()));
72 i += 1;
73 }
74 }
75 b'\\' if i + 1 < pattern.len() => {
76 i += 1;
77 node = node
78 .children
79 .entry(pattern[i])
80 .or_insert_with(|| Box::new(TrieNode::new()));
81 i += 1;
82 }
83 c => {
84 node = node
85 .children
86 .entry(c)
87 .or_insert_with(|| Box::new(TrieNode::new()));
88 i += 1;
89 }
90 }
91 }
92
93 node.subscribers.push((pattern.to_vec(), conn_id));
94 }
95
96 pub fn remove(&mut self, pattern: &[u8], conn_id: ConnectionId) -> bool {
97 Self::remove_from_node(&mut self.root, pattern, 0, pattern, conn_id)
98 }
99
100 fn remove_from_node(
101 node: &mut TrieNode,
102 pattern: &[u8],
103 pos: usize,
104 full_pattern: &[u8],
105 conn_id: ConnectionId,
106 ) -> bool {
107 if pos == pattern.len() {
108 let before_len = node.subscribers.len();
109 node.subscribers
110 .retain(|(p, id)| !(p == full_pattern && *id == conn_id));
111 return node.subscribers.len() < before_len;
112 }
113
114 match pattern[pos] {
115 b'*' => {
116 if let Some(ref mut child) = node.wildcard_child {
117 return Self::remove_from_node(child, pattern, pos + 1, full_pattern, conn_id);
118 }
119 }
120 b'?' => {
121 if let Some(ref mut child) = node.single_char_child {
122 return Self::remove_from_node(child, pattern, pos + 1, full_pattern, conn_id);
123 }
124 }
125 b'[' => {
126 let (char_class, next_i) = parse_char_class(&pattern[pos..]);
127 if char_class.is_some() {
128 if let Some(ref mut child) = node.char_class_child {
129 return Self::remove_from_node(
130 &mut child.next,
131 pattern,
132 pos + next_i,
133 full_pattern,
134 conn_id,
135 );
136 }
137 } else if let Some(ref mut child) = node.children.get_mut(&pattern[pos]) {
138 return Self::remove_from_node(child, pattern, pos + 1, full_pattern, conn_id);
139 }
140 }
141 b'\\' if pos + 1 < pattern.len() => {
142 if let Some(ref mut child) = node.children.get_mut(&pattern[pos + 1]) {
143 return Self::remove_from_node(child, pattern, pos + 2, full_pattern, conn_id);
144 }
145 }
146 c => {
147 if let Some(ref mut child) = node.children.get_mut(&c) {
148 return Self::remove_from_node(child, pattern, pos + 1, full_pattern, conn_id);
149 }
150 }
151 }
152
153 false
154 }
155
156 pub fn find_matches(&self, channel: &[u8]) -> Vec<(Vec<u8>, ConnectionId)> {
157 let mut matches = Vec::new();
158 self.find_in_node(&self.root, channel, 0, &mut matches);
159 matches
160 }
161
162 fn find_in_node(
163 &self,
164 node: &TrieNode,
165 channel: &[u8],
166 pos: usize,
167 matches: &mut Vec<(Vec<u8>, ConnectionId)>,
168 ) {
169 if pos == channel.len() {
170 matches.extend(node.subscribers.clone());
171
172 if let Some(ref wildcard) = node.wildcard_child {
173 matches.extend(wildcard.subscribers.clone());
174 }
175 return;
176 }
177
178 let current_char = channel[pos];
179
180 if let Some(child) = node.children.get(¤t_char) {
181 self.find_in_node(child, channel, pos + 1, matches);
182 }
183
184 if let Some(ref single) = node.single_char_child {
185 self.find_in_node(single, channel, pos + 1, matches);
186 }
187
188 if let Some(ref char_class) = node.char_class_child {
189 if self.matches_char_class(current_char, &char_class.chars, char_class.negated) {
190 self.find_in_node(&char_class.next, channel, pos + 1, matches);
191 }
192 }
193
194 if let Some(ref wildcard) = node.wildcard_child {
195 matches.extend(wildcard.subscribers.clone());
196
197 for i in pos..=channel.len() {
198 self.find_in_node(wildcard, channel, i, matches);
199 }
200 }
201 }
202
203 fn matches_char_class(&self, c: u8, chars: &[u8], negated: bool) -> bool {
204 let matches = chars.contains(&c);
205 if negated {
206 !matches
207 } else {
208 matches
209 }
210 }
211
212 pub fn clear(&mut self) {
213 self.root = TrieNode::new();
214 }
215
216 pub fn get_all_patterns(&self) -> Vec<Vec<u8>> {
217 let mut patterns = Vec::new();
218 Self::collect_patterns(&self.root, &mut patterns);
219 patterns
220 .into_iter()
221 .collect::<std::collections::HashSet<_>>()
222 .into_iter()
223 .collect()
224 }
225
226 fn collect_patterns(node: &TrieNode, patterns: &mut Vec<Vec<u8>>) {
227 for (pattern, _) in &node.subscribers {
228 patterns.push(pattern.clone());
229 }
230
231 for child in node.children.values() {
232 Self::collect_patterns(child, patterns);
233 }
234
235 if let Some(ref wildcard) = node.wildcard_child {
236 Self::collect_patterns(wildcard, patterns);
237 }
238
239 if let Some(ref single) = node.single_char_child {
240 Self::collect_patterns(single, patterns);
241 }
242
243 if let Some(ref char_class) = node.char_class_child {
244 Self::collect_patterns(&char_class.next, patterns);
245 }
246 }
247}
248
249fn parse_char_class(pattern: &[u8]) -> (Option<(Vec<u8>, bool)>, usize) {
250 if pattern.is_empty() || pattern[0] != b'[' {
251 return (None, 0);
252 }
253
254 let mut i = 1;
255 let negated = pattern.get(1) == Some(&b'^');
256 if negated {
257 i = 2;
258 }
259
260 let mut chars = Vec::new();
261 let mut escaped = false;
262
263 while i < pattern.len() {
264 if escaped {
265 chars.push(pattern[i]);
266 escaped = false;
267 } else if pattern[i] == b'\\' {
268 escaped = true;
269 } else if pattern[i] == b']' {
270 return (Some((chars, negated)), i + 1);
271 } else if pattern[i] == b'-'
272 && !chars.is_empty()
273 && i + 1 < pattern.len()
274 && pattern[i + 1] != b']'
275 {
276 let start = *chars.last().unwrap();
277 let end = pattern[i + 1];
278 for c in (start + 1)..=end {
279 chars.push(c);
280 }
281 i += 1;
282 } else {
283 chars.push(pattern[i]);
284 }
285 i += 1;
286 }
287
288 (None, 0)
289}
290
291impl TrieNode {
292 fn new() -> Self {
293 Self {
294 children: HashMap::new(),
295 wildcard_child: None,
296 single_char_child: None,
297 char_class_child: None,
298 subscribers: Vec::new(),
299 }
300 }
301}