#![deny(clippy::all)]
#![deny(missing_docs)]
use std::path::Path;
use anyhow::*;
use grep_reader::GrepReader;
mod reader {
use anyhow::*;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;
use std::path::Path;
use std::result::Result::Ok;
type FileReader = BufReader<File>;
fn text_file_reader<P: AsRef<Path>>(p: P) -> Result<FileReader> {
let p = p.as_ref();
let f = File::open(p).with_context(|| format!("Failed to open file {:?}", p))?;
let reader = BufReader::new(f);
Ok(reader)
}
#[derive(Debug)]
pub struct TextReader<R> {
inner: R,
}
impl TextReader<FileReader> {
pub fn try_from_path(p: &Path) -> Result<Self> {
let reader = text_file_reader(p)?;
let parser = Self { inner: reader };
Ok(parser)
}
}
impl<R: Read> TextReader<BufReader<R>> {
pub fn new(r: R) -> Self {
Self { inner: BufReader::new(r) }
}
}
impl<R: BufRead> TextReader<R> {
pub fn read_line(&mut self, buf: &mut String) -> Option<usize> {
match self.inner.read_line(buf) {
Ok(0) => None,
Ok(n) => Some(n),
Err(_) => {
return None;
}
}
}
pub fn lines(self) -> impl Iterator<Item = String> {
self.inner.lines().filter_map(|s| if let Ok(line) = s { Some(line) } else { None })
}
pub fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
let n = self.inner.read_to_string(buf)?;
Ok(n)
}
}
}
pub fn read_xyz_frames_two_pass(path: impl AsRef<Path>, mut selection: impl Iterator<Item = usize>) -> Result<impl Iterator<Item = String>> {
let mut reader = GrepReader::try_from_path(path.as_ref())?;
let n = reader.mark(r"^\s*\d+\s*$", None)?;
let frames = std::iter::from_fn(move || {
if reader.current_marker() <= n {
let j = selection.next()?;
if j < n {
reader.goto_marker(j).ok()?;
let mut buf = String::new();
reader.read_until_next_marker(&mut buf).ok()?;
Some(buf)
} else {
None
}
} else {
None
}
});
Ok(frames)
}
pub use read_xyz_frames_two_pass as read_xyz_frames;
pub fn read_xyz_frames_direct(path: impl AsRef<Path>) -> Result<impl Iterator<Item = String>> {
let mut reader = self::reader::TextReader::try_from_path(path.as_ref())?;
let frames = std::iter::from_fn(move || {
let mut buf = String::new();
let _ = reader.read_line(&mut buf)?;
let n: usize = buf.trim().parse().ok()?;
let _ = reader.read_line(&mut buf)?;
for _ in 0..n {
reader.read_line(&mut buf)?;
}
Some(buf)
});
Ok(frames)
}