use super::record::{ParseRecordError, Record};
use std::fs::File;
use std::io::{self, BufRead, BufReader, Lines};
use std::path::Path;
#[derive(Debug)]
pub struct Reader<B> {
lines: Lines<B>,
line: u32,
}
impl<B> Reader<B> {
pub fn new(buf: B) -> Self
where
B: BufRead,
{
Reader {
lines: buf.lines(),
line: 0,
}
}
}
impl Reader<BufReader<File>> {
pub fn open_file<P>(path: P) -> Result<Self, io::Error>
where
P: AsRef<Path>,
{
Ok(Reader::new(BufReader::new(File::open(path)?)))
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("{}", _0)]
Io(#[from] io::Error),
#[error("invalid record syntax at line {}: {}", _0, _1)]
ParseRecord(u32, #[source] ParseRecordError),
}
impl<B> Iterator for Reader<B>
where
B: BufRead,
{
type Item = Result<Record, Error>;
fn next(&mut self) -> Option<Self::Item> {
self.lines.next().map(|line| {
line.map_err(Error::Io).and_then(|line| {
self.line += 1;
line.parse().map_err(|e| Error::ParseRecord(self.line, e))
})
})
}
}