use super::*;
use ::grep::regex::{RegexMatcher, RegexMatcherBuilder};
fn build_matcher_for_literals<B: AsRef<str>>(literals: &[B]) -> Result<RegexMatcher> {
let matcher = RegexMatcherBuilder::new()
.line_terminator(Some(b'\n'))
.multi_line(true)
.build_literals(literals)?;
Ok(matcher)
}
use ::grep::searcher::{Sink, SinkError, SinkMatch};
#[derive(Clone, Debug)]
struct PartSink<F>(pub F)
where
F: FnMut(u64, &str) -> std::io::Result<bool>;
impl<F> Sink for PartSink<F>
where
F: FnMut(u64, &str) -> std::io::Result<bool>,
{
type Error = std::io::Error;
fn matched(&mut self, _searcher: &Searcher, mat: &SinkMatch<'_>) -> std::io::Result<bool> {
let matched_line = std::str::from_utf8(mat.bytes()).map_err(|e| Self::Error::error_message(e))?;
let matched_line_position = mat.absolute_byte_offset();
(self.0)(matched_line_position, &matched_line)
}
}
use ::grep::searcher::{BinaryDetection, Searcher, SearcherBuilder};
fn make_searcher() -> Searcher {
SearcherBuilder::new()
.line_number(false)
.binary_detection(BinaryDetection::quit(b'\x00'))
.build()
}
pub fn mark_matched_positions_with_ripgrep(pattern: &str, path: &Path, max_count: Option<usize>) -> Result<Vec<u64>> {
let max_count = max_count.unwrap_or(usize::MAX);
let mut reader = BufReader::new(File::open(path)?);
let patterns: Vec<_> = pattern.split("|").collect();
let matcher = build_matcher_for_literals(&patterns)?;
let mut n = 0;
let mut marked = vec![];
make_searcher().search_reader(
matcher,
&mut reader,
PartSink(|pos, _line| {
marked.push(pos);
n += 1;
Ok(n < max_count)
}),
)?;
Ok(marked)
}