1use crate::character::Character;
13use crate::error::Error;
14use crate::fm_index::FMIndexBackend;
15use crate::multi_pieces::FMIndexMultiPiecesBackend;
16use crate::piece::PieceId;
17use crate::rlfmi::RLFMIndexBackend;
18use crate::suffix_array::discard::DiscardedSuffixArray;
19use crate::suffix_array::sample::SOSampledSuffixArray;
20use crate::text::Text;
21use crate::wrapper::{MatchWrapper, SearchIndexWrapper, SearchWrapper};
22
23pub trait SearchIndex<C> {
27 fn search<K>(&self, pattern: K) -> impl Search<C>
32 where
33 K: AsRef<[C]>;
34
35 fn len(&self) -> usize;
40
41 fn heap_size(&self) -> usize;
45}
46
47pub trait SearchIndexWithMultiPieces<C>: SearchIndex<C> {
49 fn search_prefix<K>(&self, pattern: K) -> impl Search<C>
51 where
52 K: AsRef<[C]>;
53
54 fn search_suffix<K>(&self, pattern: K) -> impl Search<C>
56 where
57 K: AsRef<[C]>;
58
59 fn search_exact<K>(&self, pattern: K) -> impl Search<C>
61 where
62 K: AsRef<[C]>;
63}
64
65pub trait Search<'a, C> {
71 type Match: Match<'a, C>;
73
74 fn search<K: AsRef<[C]>>(&self, pattern: K) -> Self;
79 fn count(&self) -> usize;
81 fn iter_matches(&'a self) -> impl Iterator<Item = Self::Match> + 'a;
83}
84
85pub trait Match<'a, C> {
87 fn iter_chars_forward(&self) -> impl Iterator<Item = C> + 'a;
89
90 fn iter_chars_backward(&self) -> impl Iterator<Item = C> + 'a;
92}
93
94pub trait MatchWithLocate<'a, C>: Match<'a, C> {
96 fn locate(&self) -> usize;
98}
99
100pub trait MatchWithPieceId<'a, C>: Match<'a, C> {
102 fn piece_id(&self) -> PieceId;
104}
105
106pub struct FMIndex<C: Character>(SearchIndexWrapper<FMIndexBackend<C, DiscardedSuffixArray>>);
111pub struct FMIndexSearch<'a, C: Character>(
113 SearchWrapper<'a, FMIndexBackend<C, DiscardedSuffixArray>>,
114);
115pub struct FMIndexMatch<'a, C: Character>(
117 MatchWrapper<'a, FMIndexBackend<C, DiscardedSuffixArray>>,
118);
119
120pub struct FMIndexWithLocate<C: Character>(
124 SearchIndexWrapper<FMIndexBackend<C, SOSampledSuffixArray>>,
125);
126pub struct FMIndexSearchWithLocate<'a, C: Character>(
128 SearchWrapper<'a, FMIndexBackend<C, SOSampledSuffixArray>>,
129);
130pub struct FMIndexMatchWithLocate<'a, C: Character>(
132 MatchWrapper<'a, FMIndexBackend<C, SOSampledSuffixArray>>,
133);
134
135pub struct RLFMIndex<C: Character>(SearchIndexWrapper<RLFMIndexBackend<C, DiscardedSuffixArray>>);
139pub struct RLFMIndexSearch<'a, C: Character>(
141 SearchWrapper<'a, RLFMIndexBackend<C, DiscardedSuffixArray>>,
142);
143pub struct RLFMIndexMatch<'a, C: Character>(
145 MatchWrapper<'a, RLFMIndexBackend<C, DiscardedSuffixArray>>,
146);
147
148pub struct RLFMIndexWithLocate<C: Character>(
153 SearchIndexWrapper<RLFMIndexBackend<C, SOSampledSuffixArray>>,
154);
155pub struct RLFMIndexSearchWithLocate<'a, C: Character>(
157 SearchWrapper<'a, RLFMIndexBackend<C, SOSampledSuffixArray>>,
158);
159pub struct RLFMIndexMatchWithLocate<'a, C: Character>(
161 MatchWrapper<'a, RLFMIndexBackend<C, SOSampledSuffixArray>>,
162);
163
164pub struct FMIndexMultiPieces<C: Character>(
168 SearchIndexWrapper<FMIndexMultiPiecesBackend<C, DiscardedSuffixArray>>,
169);
170pub struct FMIndexMultiPiecesSearch<'a, C: Character>(
172 SearchWrapper<'a, FMIndexMultiPiecesBackend<C, DiscardedSuffixArray>>,
173);
174pub struct FMIndexMultiPiecesMatch<'a, C: Character>(
176 MatchWrapper<'a, FMIndexMultiPiecesBackend<C, DiscardedSuffixArray>>,
177);
178
179pub struct FMIndexMultiPiecesWithLocate<C: Character>(
184 SearchIndexWrapper<FMIndexMultiPiecesBackend<C, SOSampledSuffixArray>>,
185);
186pub struct FMIndexMultiPiecesSearchWithLocate<'a, C: Character>(
188 SearchWrapper<'a, FMIndexMultiPiecesBackend<C, SOSampledSuffixArray>>,
189);
190pub struct FMIndexMultiPiecesMatchWithLocate<'a, C: Character>(
192 MatchWrapper<'a, FMIndexMultiPiecesBackend<C, SOSampledSuffixArray>>,
193);
194
195impl<C: Character> FMIndex<C> {
196 pub fn new<T: AsRef<[C]>>(text: &Text<C, T>) -> Result<Self, Error> {
198 Ok(FMIndex(SearchIndexWrapper::new(FMIndexBackend::new(
199 text,
200 |_| DiscardedSuffixArray {},
201 )?)))
202 }
203}
204
205impl<C: Character> FMIndexWithLocate<C> {
206 pub fn new<T: AsRef<[C]>>(text: &Text<C, T>, level: usize) -> Result<Self, Error> {
214 Ok(FMIndexWithLocate(SearchIndexWrapper::new(
215 FMIndexBackend::new(text, |sa| SOSampledSuffixArray::sample(sa, level))?,
216 )))
217 }
218}
219
220impl<C: Character> RLFMIndex<C> {
221 pub fn new<T: AsRef<[C]>>(text: &Text<C, T>) -> Result<Self, Error> {
223 Ok(RLFMIndex(SearchIndexWrapper::new(RLFMIndexBackend::new(
224 text,
225 |_| DiscardedSuffixArray {},
226 )?)))
227 }
228}
229
230impl<C: Character> RLFMIndexWithLocate<C> {
231 pub fn new<T: AsRef<[C]>>(text: &Text<C, T>, level: usize) -> Result<Self, Error> {
239 Ok(RLFMIndexWithLocate(SearchIndexWrapper::new(
240 RLFMIndexBackend::new(text, |sa| SOSampledSuffixArray::sample(sa, level))?,
241 )))
242 }
243}
244
245impl<C: Character> FMIndexMultiPieces<C> {
246 pub fn new<T: AsRef<[C]>>(text: &Text<C, T>) -> Result<Self, Error> {
248 Ok(FMIndexMultiPieces(SearchIndexWrapper::new(
249 FMIndexMultiPiecesBackend::new(text, |_| DiscardedSuffixArray {})?,
250 )))
251 }
252}
253
254impl<C: Character> FMIndexMultiPiecesWithLocate<C> {
255 pub fn new<T: AsRef<[C]>>(text: &Text<C, T>, level: usize) -> Result<Self, Error> {
263 Ok(FMIndexMultiPiecesWithLocate(SearchIndexWrapper::new(
264 FMIndexMultiPiecesBackend::new(text, |sa| SOSampledSuffixArray::sample(sa, level))?,
265 )))
266 }
267}
268
269macro_rules! impl_search_index {
270 ($t:ty, $s:ident, $st:ty) => {
271 impl<C: Character> SearchIndex<C> for $t {
272 fn search<K>(&self, pattern: K) -> impl Search<C>
273 where
274 K: AsRef<[C]>,
275 {
276 $s(self.0.search(pattern))
277 }
278
279 fn len(&self) -> usize {
280 self.0.len()
281 }
282
283 fn heap_size(&self) -> usize {
284 self.0.heap_size()
285 }
286 }
287
288 impl<C: Character> $t {
290 pub fn search<K>(&self, pattern: K) -> $st
292 where
293 K: AsRef<[C]>,
294 {
295 $s(self.0.search(pattern))
296 }
297 pub fn len(&self) -> usize {
299 SearchIndex::len(self)
300 }
301 }
302 };
303}
304
305macro_rules! impl_search_index_with_locate {
306 ($t:ty, $s:ident, $st:ty) => {
307 impl<C: Character> SearchIndex<C> for $t {
308 fn search<K>(&self, pattern: K) -> impl Search<C>
309 where
310 K: AsRef<[C]>,
311 {
312 $s(self.0.search(pattern))
313 }
314
315 fn len(&self) -> usize {
316 self.0.len()
317 }
318
319 fn heap_size(&self) -> usize {
320 self.0.heap_size()
321 }
322 }
323
324 impl<C: Character> $t {
326 pub fn search<K>(&self, pattern: K) -> $st
328 where
329 K: AsRef<[C]>,
330 {
331 $s(self.0.search(pattern))
332 }
333 pub fn len(&self) -> usize {
335 SearchIndex::len(self)
336 }
337 }
338 };
339}
340
341macro_rules! impl_search_index_with_multi_pieces {
342 ($t:ty, $s:ident, $st:ty) => {
343 impl<C: Character> SearchIndexWithMultiPieces<C> for $t {
344 fn search_prefix<K>(&self, pattern: K) -> impl Search<C>
345 where
346 K: AsRef<[C]>,
347 {
348 $s(self.0.search_prefix(pattern))
349 }
350
351 fn search_suffix<K>(&self, pattern: K) -> impl Search<C>
352 where
353 K: AsRef<[C]>,
354 {
355 $s(self.0.search_suffix(pattern))
356 }
357
358 fn search_exact<K>(&self, pattern: K) -> impl Search<C>
359 where
360 K: AsRef<[C]>,
361 {
362 $s(self.0.search_exact(pattern))
363 }
364 }
365
366 impl<C: Character> $t {
368 pub fn search_prefix<K>(&self, pattern: K) -> $st
370 where
371 K: AsRef<[C]>,
372 {
373 $s(self.0.search_prefix(pattern))
374 }
375
376 pub fn search_suffix<K>(&self, pattern: K) -> $st
378 where
379 K: AsRef<[C]>,
380 {
381 $s(self.0.search_suffix(pattern))
382 }
383
384 pub fn search_exact<K>(&self, pattern: K) -> $st
386 where
387 K: AsRef<[C]>,
388 {
389 $s(self.0.search_exact(pattern))
390 }
391 }
392 };
393}
394
395macro_rules! impl_search {
396 ($t:ty, $m:ident, $mt:ty) => {
397 impl<'a, C: Character> Search<'a, C> for $t {
398 type Match = $mt;
399
400 fn search<K>(&self, pattern: K) -> Self
401 where
402 K: AsRef<[C]>,
403 {
404 Self(self.0.search(pattern))
405 }
406
407 fn count(&self) -> usize {
408 self.0.count()
409 }
410
411 fn iter_matches(&'a self) -> impl Iterator<Item = Self::Match> + 'a {
412 self.0.iter_matches().map(|m| $m(m))
413 }
414 }
415 impl<'a, C: Character> $t {
417 pub fn search<K>(&self, pattern: K) -> Self
422 where
423 K: AsRef<[C]>,
424 {
425 Search::search(self, pattern)
426 }
427
428 pub fn count(&self) -> usize {
430 Search::count(self)
431 }
432 }
433 };
434}
435
436macro_rules! impl_match {
437 ($t:ty) => {
438 impl<'a, C: Character> Match<'a, C> for $t {
439 fn iter_chars_forward(&self) -> impl Iterator<Item = C> + 'a {
440 self.0.iter_chars_forward()
441 }
442
443 fn iter_chars_backward(&self) -> impl Iterator<Item = C> + 'a {
444 self.0.iter_chars_backward()
445 }
446 }
447 };
448}
449
450macro_rules! impl_match_locate {
451 ($t:ty) => {
452 impl<'a, C: Character> MatchWithLocate<'a, C> for $t {
453 fn locate(&self) -> usize {
454 self.0.locate()
455 }
456 }
457 };
458}
459
460macro_rules! impl_match_piece_id {
461 ($t:ty) => {
462 impl<'a, C: Character> MatchWithPieceId<'a, C> for $t {
463 fn piece_id(&self) -> PieceId {
464 self.0.piece_id()
465 }
466 }
467 };
468}
469
470impl_search_index!(FMIndex<C>, FMIndexSearch, FMIndexSearch<C>);
471impl_search!(FMIndexSearch<'a, C>, FMIndexMatch, FMIndexMatch<'a, C>);
472impl_match!(FMIndexMatch<'a, C>);
473
474impl_search_index_with_locate!(
475 FMIndexWithLocate<C>,
476 FMIndexSearchWithLocate,
477 FMIndexSearchWithLocate<C>
478);
479impl_search!(
480 FMIndexSearchWithLocate<'a, C>,
481 FMIndexMatchWithLocate,
482 FMIndexMatchWithLocate<'a, C>
483);
484impl_match!(FMIndexMatchWithLocate<'a, C>);
485impl_match_locate!(FMIndexMatchWithLocate<'a, C>);
486
487impl_search_index!(RLFMIndex<C>, RLFMIndexSearch, RLFMIndexSearch<C>);
488impl_search!(
489 RLFMIndexSearch<'a, C>,
490 RLFMIndexMatch,
491 RLFMIndexMatch<'a, C>
492);
493impl_match!(RLFMIndexMatch<'a, C>);
494
495impl_search_index_with_locate!(
496 RLFMIndexWithLocate<C>,
497 RLFMIndexSearchWithLocate,
498 RLFMIndexSearchWithLocate<C>
499);
500impl_search!(
501 RLFMIndexSearchWithLocate<'a, C>,
502 RLFMIndexMatchWithLocate,
503 RLFMIndexMatchWithLocate<'a, C>
504);
505impl_match!(RLFMIndexMatchWithLocate<'a, C>);
506impl_match_locate!(RLFMIndexMatchWithLocate<'a, C>);
507
508impl_search_index!(
509 FMIndexMultiPieces<C>,
510 FMIndexMultiPiecesSearch,
511 FMIndexMultiPiecesSearch<C>
512);
513impl_search_index_with_multi_pieces!(
514 FMIndexMultiPieces<C>,
515 FMIndexMultiPiecesSearch,
516 FMIndexMultiPiecesSearch<C>
517);
518impl_search!(
519 FMIndexMultiPiecesSearch<'a, C>,
520 FMIndexMultiPiecesMatch,
521 FMIndexMultiPiecesMatch<'a, C>
522);
523impl_match!(FMIndexMultiPiecesMatch<'a, C>);
524
525impl_search_index_with_locate!(
526 FMIndexMultiPiecesWithLocate<C>,
527 FMIndexMultiPiecesSearchWithLocate,
528 FMIndexMultiPiecesSearchWithLocate<C>
529);
530impl_search_index_with_multi_pieces!(
531 FMIndexMultiPiecesWithLocate<C>,
532 FMIndexMultiPiecesSearchWithLocate,
533 FMIndexMultiPiecesSearchWithLocate<C>
534);
535impl_search!(
536 FMIndexMultiPiecesSearchWithLocate<'a, C>,
537 FMIndexMultiPiecesMatchWithLocate,
538 FMIndexMultiPiecesMatchWithLocate<'a, C>
539);
540impl_match!(FMIndexMultiPiecesMatchWithLocate<'a, C>);
541impl_match_locate!(FMIndexMultiPiecesMatchWithLocate<'a, C>);
542impl_match_piece_id!(FMIndexMultiPiecesMatchWithLocate<'a, C>);