1use crate::{
42 map::Trie,
43 try_collect::{TryCollect, TryFromIterator},
44};
45use louds_rs::LoudsNodeNum;
46
47#[derive(Debug, Clone)]
48pub struct IncSearch<'a, Label, Value> {
50 trie: &'a Trie<Label, Value>,
51 node: LoudsNodeNum,
52}
53
54pub type Position = LoudsNodeNum;
61
62impl<'a, L, V> From<IncSearch<'a, L, V>> for Position {
65 fn from(inc_search: IncSearch<'a, L, V>) -> Self {
66 inc_search.node
67 }
68}
69
70#[derive(Debug, PartialEq, Eq, Clone, Copy)]
72pub enum Answer {
73 Prefix,
75 Match,
77 PrefixAndMatch,
79}
80
81impl Answer {
82 pub fn is_prefix(&self) -> bool {
84 matches!(self, Answer::Prefix | Answer::PrefixAndMatch)
85 }
86
87 pub fn is_match(&self) -> bool {
89 matches!(self, Answer::Match | Answer::PrefixAndMatch)
90 }
91
92 fn new(is_prefix: bool, is_match: bool) -> Option<Self> {
93 match (is_prefix, is_match) {
94 (true, false) => Some(Answer::Prefix),
95 (false, true) => Some(Answer::Match),
96 (true, true) => Some(Answer::PrefixAndMatch),
97 (false, false) => None,
98 }
99 }
100}
101
102impl<'a, Label: Ord, Value> IncSearch<'a, Label, Value> {
103 pub fn new(trie: &'a Trie<Label, Value>) -> Self {
105 Self {
106 trie,
107 node: LoudsNodeNum(1),
108 }
109 }
110
111 pub fn resume(trie: &'a Trie<Label, Value>, position: Position) -> Self {
129 Self {
130 trie,
131 node: position,
132 }
133 }
134
135 pub fn peek(&self, chr: &Label) -> Option<Answer> {
137 let children_node_nums: Vec<_> = self.trie.children_node_nums(self.node).collect();
138 let res = self
139 .trie
140 .bin_search_by_children_labels(chr, &children_node_nums[..]);
141 match res {
142 Ok(j) => {
143 let node = children_node_nums[j];
144 let is_prefix = self.trie.has_children_node_nums(node);
145 let is_match = self.trie.value(node).is_some();
146 Answer::new(is_prefix, is_match)
147 }
148 Err(_) => None,
149 }
150 }
151
152 pub fn query(&mut self, chr: &Label) -> Option<Answer> {
154 let children_node_nums: Vec<_> = self.trie.children_node_nums(self.node).collect();
155 let res = self
156 .trie
157 .bin_search_by_children_labels(chr, &children_node_nums[..]);
158 match res {
159 Ok(j) => {
160 self.node = children_node_nums[j];
161 let is_prefix = self.trie.has_children_node_nums(self.node);
162 let is_match = self.trie.value(self.node).is_some();
163 Answer::new(is_prefix, is_match)
164 }
165 Err(_) => None,
166 }
167 }
168
169 pub fn query_until(&mut self, query: impl AsRef<[Label]>) -> Result<Answer, usize> {
172 let mut result = None;
173 let mut i = 0;
174 for chr in query.as_ref().iter() {
175 result = self.query(chr);
176 if result.is_none() {
177 return Err(i);
178 }
179 i += 1;
180 }
181 result.ok_or(i)
182 }
183
184 pub fn value(&self) -> Option<&'a Value> {
187 self.trie.value(self.node)
188 }
189
190 pub fn goto_longest_prefix(&mut self) -> Result<usize, usize> {
192 let mut count = 0;
193
194 while count == 0 || !self.trie.is_terminal(self.node) {
195 let mut iter = self.trie.children_node_nums(self.node);
196 let first = iter.next();
197 let second = iter.next();
198 match (first, second) {
199 (Some(child_node_num), None) => {
200 self.node = child_node_num;
201 count += 1;
202 }
203 (None, _) => {
204 assert_eq!(count, 0);
205 return Ok(count);
206 }
207 _ => {
208 return Err(count);
209 }
210 }
211 }
212 Ok(count)
213 }
214
215 pub fn prefix<C, M>(&self) -> C
217 where
218 C: TryFromIterator<Label, M>,
219 Label: Clone,
220 {
221 let mut v: Vec<Label> = self
222 .trie
223 .child_to_ancestors(self.node)
224 .map(|node| self.trie.label(node).clone())
225 .collect();
226 v.reverse();
227 v.into_iter().try_collect().expect("Could not collect")
228 }
229
230 pub fn prefix_len(&self) -> usize {
232 self.trie.child_to_ancestors(self.node).count()
237
238 }
247
248 pub fn reset(&mut self) {
260 self.node = LoudsNodeNum(1);
261 }
262}
263
264#[cfg(test)]
265mod search_tests {
266 use super::*;
267 use crate::map::{Trie, TrieBuilder};
268
269 fn build_trie() -> Trie<u8, u8> {
270 let mut builder = TrieBuilder::new();
271 builder.push("a", 0);
272 builder.push("app", 1);
273 builder.push("apple", 2);
274 builder.push("better", 3);
275 builder.push("application", 4);
276 builder.push("アップル🍎", 5);
277 builder.build()
278 }
279
280 #[test]
281 fn inc_search() {
282 let trie = build_trie();
283 let mut search = trie.inc_search();
284 assert_eq!("", search.prefix::<String, _>());
285 assert_eq!(0, search.prefix_len());
286 assert_eq!(None, search.query(&b'z'));
287 assert_eq!("", search.prefix::<String, _>());
288 assert_eq!(0, search.prefix_len());
289 assert_eq!(Answer::PrefixAndMatch, search.query(&b'a').unwrap());
290 assert_eq!("a", search.prefix::<String, _>());
291 assert_eq!(1, search.prefix_len());
292 assert_eq!(Answer::Prefix, search.query(&b'p').unwrap());
293 assert_eq!("ap", search.prefix::<String, _>());
294 assert_eq!(2, search.prefix_len());
295 assert_eq!(Answer::PrefixAndMatch, search.query(&b'p').unwrap());
296 assert_eq!("app", search.prefix::<String, _>());
297 assert_eq!(3, search.prefix_len());
298 assert_eq!(Answer::Prefix, search.query(&b'l').unwrap());
299 assert_eq!("appl", search.prefix::<String, _>());
300 assert_eq!(4, search.prefix_len());
301 assert_eq!(Answer::Match, search.query(&b'e').unwrap());
302 assert_eq!("apple", search.prefix::<String, _>());
303 assert_eq!(5, search.prefix_len());
304 }
305
306 #[test]
307 fn inc_search_value() {
308 let trie = build_trie();
309 let mut search = trie.inc_search();
310 assert_eq!("", search.prefix::<String, _>());
311 assert_eq!(None, search.query(&b'z'));
312 assert_eq!("", search.prefix::<String, _>());
313 assert_eq!(Answer::PrefixAndMatch, search.query(&b'a').unwrap());
314 assert_eq!("a", search.prefix::<String, _>());
315 assert_eq!(Answer::Prefix, search.query(&b'p').unwrap());
316 assert_eq!("ap", search.prefix::<String, _>());
317 assert_eq!(Answer::PrefixAndMatch, search.query(&b'p').unwrap());
318 assert_eq!("app", search.prefix::<String, _>());
319 assert_eq!(Answer::Prefix, search.query(&b'l').unwrap());
320 assert_eq!("appl", search.prefix::<String, _>());
321 assert_eq!(Answer::Match, search.query(&b'e').unwrap());
322 assert_eq!("apple", search.prefix::<String, _>());
323 assert_eq!(Some(&2), search.value());
324 }
325
326 #[test]
327 fn inc_search_query_until() {
328 let trie = build_trie();
329 let mut search = trie.inc_search();
330 assert_eq!(Err(0), search.query_until("zoo"));
331 assert_eq!("", search.prefix::<String, _>());
332 search.reset();
333 assert_eq!(Err(1), search.query_until("blue"));
334 assert_eq!("b", search.prefix::<String, _>());
335 search.reset();
336 assert_eq!(Answer::Match, search.query_until("apple").unwrap());
337 assert_eq!("apple", search.prefix::<String, _>());
338 assert_eq!(Some(&2), search.value());
339 }
340
341 #[test]
342 fn inc_search_goto_longest_prefix() {
343 let trie = build_trie();
344 let mut search = trie.inc_search();
345 assert_eq!(Err(0), search.goto_longest_prefix());
346 assert_eq!("", search.prefix::<String, _>());
347 search.reset();
348 assert_eq!(Ok(Answer::PrefixAndMatch), search.query_until("a"));
349 assert_eq!("a", search.prefix::<String, _>());
350 assert_eq!(Ok(2), search.goto_longest_prefix());
351 assert_eq!("app", search.prefix::<String, _>());
352 assert_eq!(Err(1), search.goto_longest_prefix());
353 assert_eq!("appl", search.prefix::<String, _>());
354 assert_eq!(Err(0), search.goto_longest_prefix());
355 assert_eq!(Ok(Answer::Prefix), search.query_until("i"));
356 assert_eq!(Ok(6), search.goto_longest_prefix());
357 assert_eq!(Ok(0), search.goto_longest_prefix());
358 assert_eq!("application", search.prefix::<String, _>());
359 search.reset();
360 assert_eq!(Answer::Match, search.query_until("apple").unwrap());
361 assert_eq!("apple", search.prefix::<String, _>());
362 assert_eq!(Some(&2), search.value());
363 }
364
365 }