use std::mem;
use std::cell::RefMut;
use std::collections::VecDeque;
use grep_matcher::Match;
use hyperscan::{
ScanFlags, Scannable, MatchEventCallback, MatchEventCallbackMut, Scratch,
RawScratch, BlockDatabase, BlockScanner
};
#[derive(Debug)]
pub struct MatchData {
pub results: VecDeque<Match>,
haystack_len: usize,
started: bool,
}
impl MatchData {
pub fn new_match_data() -> MatchData {
MatchData {
results: VecDeque::with_capacity(100),
started: false,
haystack_len: 0,
}
}
pub fn stop(&mut self) {
self.started = false;
}
pub fn should_restart(&self, len : usize) -> bool {
len != self.haystack_len || !self.started
}
pub fn restart(&mut self, len : usize) {
self.haystack_len = len;
self.started = true;
self.results.clear();
}
}
pub fn hyperscan_callback(
_: u32,
from: u64,
to: u64,
_: u32,
this: &mut RefMut<MatchData>
) -> u32 {
this.results.push_back(Match::new(from as usize, to as usize));
0
}
#[derive(Debug)]
pub struct ThreadScratch {
pub s: RawScratch,
}
unsafe impl Send for ThreadScratch {}
pub trait ScanMutCtxtExt<T: Scannable, S: Scratch> : BlockScanner<T,S> {
fn scan_mut_ctxt<D>(
&self,
data: T,
flags: ScanFlags,
scratch: &S,
callback: Option<MatchEventCallbackMut<D>>,
context: Option<&mut D>,
) -> Result<&Self, hyperscan::Error> {
self.scan(
data,
flags,
scratch,
callback.map(|f| unsafe {
mem::transmute::<MatchEventCallbackMut<D>, MatchEventCallback<D>>(f)
}),
context.map(|v| &*v),
)
}
}
impl<T: Scannable, S: Scratch> ScanMutCtxtExt<T,S> for BlockDatabase {}