use std::io::{BufReader, Read, Seek, SeekFrom};
use crate::{Iso8211Error, Result, FIELD_TERMINATOR, UNIT_TERMINATOR};
pub struct Reader<T> {
buffer: BufReader<T>,
}
impl<T: Read + Seek> Reader<T> {
pub fn new(buffer: BufReader<T>) -> Reader<T> {
Reader { buffer }
}
pub fn is_eof(&mut self) -> Result<bool> {
let mut buf: [u8; 1] = [0; 1];
let bytes = self.buffer.read(&mut buf)?;
if bytes == 0 {
Ok(true)
} else {
self.buffer.seek(SeekFrom::Current(-1))?;
Ok(false)
}
}
pub fn peek_byte(&mut self) -> Result<u8> {
let result = self.read_u8();
if result.is_ok() {
self.buffer.seek(SeekFrom::Current(-1))?;
}
result
}
pub fn read_char(&mut self) -> Result<char> {
let mut buf: [u8; 1] = [0; 1];
self.buffer.read_exact(&mut buf)?;
Ok(buf[0] as char)
}
pub fn read_bytes(&mut self, length: usize) -> Result<Vec<u8>> {
let mut buf: Vec<u8> = vec![0u8; length];
self.buffer.read_exact(&mut buf)?;
Ok(buf)
}
pub fn read_str(&mut self, length: usize) -> Result<String> {
let mut buf = vec![0u8; length];
self.buffer.read_exact(&mut buf)?;
let s = String::from_utf8(buf)?;
Ok(s)
}
pub fn read_str_ft(&mut self) -> Result<String> {
let mut buf: [u8; 1] = [0; 1];
let mut bytes: Vec<u8> = Vec::new();
while {
self.buffer.read_exact(&mut buf)?;
buf[0] != FIELD_TERMINATOR
} {
bytes.push(buf[0]);
}
let s = String::from_utf8(bytes)?;
Ok(s)
}
pub fn read_str_ut(&mut self) -> Result<String> {
let mut buf: [u8; 1] = [0; 1];
let mut bytes: Vec<u8> = Vec::new();
while {
self.buffer.read_exact(&mut buf)?;
buf[0] != UNIT_TERMINATOR
} {
bytes.push(buf[0]);
}
let s = String::from_utf8(bytes)?;
Ok(s)
}
pub fn read_u8(&mut self) -> Result<u8> {
let mut buf = [0u8; 1];
self.buffer.read_exact(&mut buf)?;
let r = u8::from_le_bytes(buf);
Ok(r)
}
pub fn read_u8_str(&mut self, length: usize) -> Result<u8> {
let mut buf = vec![0u8; length];
self.buffer.read_exact(&mut buf)?;
let s = String::from_utf8(buf)?;
let r = s.parse::<u8>()?;
Ok(r)
}
pub fn read_u64(&mut self, length: usize) -> Result<u64> {
let mut buf = vec![0u8; length];
self.buffer.read_exact(&mut buf)?;
let mut val = [0u8; 8];
val[8 - length..].clone_from_slice(&buf);
let r = u64::from_le_bytes(val);
Ok(r)
}
pub fn read_u64_str(&mut self, length: usize) -> Result<u64> {
let mut buf = vec![0u8; length];
self.buffer.read_exact(&mut buf)?;
let s = String::from_utf8(buf)?;
match s.parse::<u64>() {
Ok(r) => Ok(r),
Err(_) => Err(Iso8211Error::Parse(format!(
"error reading u64 {} byte string at position {}: '{}'",
length,
self.position()? - length as u64,
s
))),
}
}
pub fn position(&mut self) -> Result<u64> {
Ok(self.buffer.stream_position()?)
}
}