use crate::line::NeodesLine;
use crate::line::NeodesLineParseError;
use encoding_rs::mem::decode_latin1;
use std::fs::File;
use std::io::{BufRead, BufReader, Write};
use std::path::Path;
use std::str::FromStr;
pub struct NeodesLineIterator<B: BufRead> {
reader: B,
buffer: Vec<u8>,
}
#[derive(Debug)]
pub enum NeodesLineReadError {
IOError(std::io::Error),
ParseError(NeodesLineParseError),
}
impl<B: BufRead> Iterator for NeodesLineIterator<B> {
type Item = Result<NeodesLine, NeodesLineReadError>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.buffer.clear();
match self.reader.read_until(b'\n', &mut self.buffer) {
Ok(0) => None, Ok(_n) => {
let line = if self.buffer.ends_with(b"\n") {
&self.buffer[..self.buffer.len() - 1]
} else {
&self.buffer[..]
};
let decoded = decode_latin1(line);
Some(NeodesLine::from_str(&decoded).map_err(NeodesLineReadError::ParseError))
}
Err(e) => Some(Err(NeodesLineReadError::IOError(e))),
}
}
}
#[inline]
pub fn read_dsn_file<P: AsRef<Path>>(
path: P,
) -> Result<impl Iterator<Item = Result<NeodesLine, NeodesLineReadError>>, std::io::Error> {
let file = File::open(path)?;
let reader = BufReader::new(file);
Ok(read_dsn(reader))
}
#[inline]
pub fn read_dsn<B: BufRead>(reader: B) -> NeodesLineIterator<B> {
let buffer = Vec::with_capacity(256);
NeodesLineIterator { reader, buffer }
}
#[inline]
pub fn write_dsn_file<'a, P: AsRef<Path>, I>(path: P, lines: I) -> Result<(), std::io::Error>
where
I: IntoIterator<Item = &'a NeodesLine>,
{
let mut file = File::create(path)?;
for line in lines {
file.write_all(&encoding_rs::mem::encode_latin1_lossy(&line.to_string()))?;
file.write_all(b"\n")?;
}
Ok(())
}