use std::fs;
use std::path::PathBuf;
use anyhow::{Context, Result};
use structopt::StructOpt;
use hyperscan::prelude::*;
#[derive(Debug, StructOpt)]
#[structopt(name = "simplegrep", about = "An example search a given input file for a pattern.")]
struct Opt {
pattern: String,
#[structopt(parse(from_os_str))]
input: PathBuf,
}
fn main() -> Result<()> {
let opt = Opt::from_args();
let pattern = Pattern::with_flags(
opt.pattern,
CompileFlags::DOTALL | CompileFlags::MULTILINE | CompileFlags::SOM_LEFTMOST,
)
.with_context(|| "parse pattern")?;
let database: BlockDatabase = pattern.build().with_context(|| "compile pattern")?;
let input_data = fs::read_to_string(opt.input).with_context(|| "read input file")?;
let scratch = database.alloc_scratch().with_context(|| "allocate scratch space")?;
println!("Scanning {} bytes with Hyperscan", input_data.len());
database
.scan(&input_data, &scratch, |_, from, to, _| {
println!(
"Match for pattern \"{}\" at offset {}..{}: {}",
pattern.expression,
from,
to,
&input_data[from as usize..to as usize]
);
Matching::Continue
})
.with_context(|| "scan input buffer")
}