use pattern_matching::shift_and::masks;
use std::slice::SliceExt;
#[derive(Copy)]
pub struct BNDM {
m: usize,
masks: [u64; 256],
accept: u64
}
impl BNDM {
pub fn new(pattern: &[u8]) -> Self {
let m = pattern.len();
assert!(m <= 64, "Expecting a pattern of at most 64 symbols.");
let mut rev = pattern.to_vec();
rev.reverse();
let (masks, accept) = masks(rev.as_slice());
BNDM { m: m, masks: masks, accept: accept }
}
pub fn find_all<'a>(&'a self, text: &'a [u8]) -> BNDMMatches {
BNDMMatches { bndm: self, window: self.m, text: text }
}
}
pub struct BNDMMatches<'a> {
bndm: &'a BNDM,
window: usize,
text: &'a [u8]
}
impl<'a> Iterator for BNDMMatches<'a> {
type Item = usize;
fn next(&mut self) -> Option<usize> {
while self.window <= self.text.len() {
let mut occ = None;
let mut active = (1u64 << self.bndm.m) - 1;
let (mut j, mut lastsuffix) = (1, 0);
while active != 0 {
active &= self.bndm.masks[self.text[self.window - j] as usize];
if active & self.bndm.accept != 0 {
if j == self.bndm.m {
occ = Some(self.window - self.bndm.m);
break;
}
else {
lastsuffix = j;
}
}
j += 1;
active <<= 1;
}
self.window += self.bndm.m - lastsuffix;
if occ.is_some() {
return occ;
}
}
None
}
}