use super::*;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
mod grep_lib;
use std::io::SeekFrom;
use std::path::{Path, PathBuf};
#[derive(Debug)]
pub struct GrepReader {
src: PathBuf,
reader: BufReader<File>,
position_markers: Vec<u64>,
marker_index: usize,
}
impl GrepReader {
pub fn try_from_path(p: &Path) -> Result<Self> {
let f = File::open(p)?;
let reader = BufReader::new(f);
let grep = Self {
reader,
src: p.to_owned(),
position_markers: vec![],
marker_index: 0,
};
Ok(grep)
}
pub fn mark(&mut self, pattern: &str, max_count: impl Into<Option<usize>>) -> Result<usize> {
use self::grep_lib::mark_matched_positions_with_ripgrep;
let max_count = max_count.into();
self.position_markers = mark_matched_positions_with_ripgrep(pattern, &self.src, max_count)?;
self.marker_index = 0;
Ok(self.position_markers.len())
}
pub fn goto_start(&mut self) {
let _ = self.reader.rewind();
}
pub fn goto_end(&mut self) {
let _ = self.reader.seek(SeekFrom::End(0));
}
pub fn num_markers(&self) -> usize {
self.position_markers.len()
}
pub fn goto_next_marker(&mut self) -> Result<u64> {
let n = self.position_markers.len();
if self.marker_index < n {
let pos = self.position_markers[self.marker_index];
self.marker_index += 1;
let _ = self.reader.seek(SeekFrom::Start(pos))?;
Ok(pos)
} else {
bail!("Already reached the last marker or no marker at all!");
}
}
pub fn goto_marker(&mut self, marker_index: usize) -> Result<u64> {
let pos = self.position_markers[marker_index];
let _ = self.reader.seek(SeekFrom::Start(pos))?;
self.marker_index = marker_index + 1;
Ok(pos)
}
pub fn current_marker(&mut self) -> usize {
self.marker_index
}
pub fn read_lines(&mut self, n: usize, buffer: &mut String) -> Result<()> {
for i in 0..n {
let nbytes = self.reader.read_line(buffer)?;
if nbytes == 0 {
bail!("The stream has reached EOF. Required {} lines, but filled {} lines", n, i);
}
}
Ok(())
}
pub fn get_mut(&mut self) -> &mut BufReader<File> {
&mut self.reader
}
pub fn read_until_next_marker(&mut self, s: &mut String) -> Result<()> {
ensure!(!self.position_markers.is_empty(), "No markers present!");
let i = self.marker_index;
let pos_cur = self.reader.stream_position()?;
if i < self.position_markers.len() {
let pos_mark = self.position_markers[i];
ensure!(pos_cur <= pos_mark, "cannot continue: cursor is behind current marker");
let delta = pos_mark - pos_cur;
let mut nsum = 0;
for _ in 0.. {
let n = self.reader.read_line(s)?;
assert_ne!(n, 0);
nsum += n as u64;
if nsum >= delta {
break;
}
}
self.marker_index += 1;
} else {
let pos_mark = self.position_markers.last().expect("no marker");
ensure!(pos_cur <= *pos_mark, "cannot continue: cursor is behind current marker");
while self.reader.read_line(s)? != 0 {
}
}
Ok(())
}
}