use std::{
fs::File,
io::{self, BufReader, Read, Seek, SeekFrom},
};
#[derive(Debug)]
pub struct BufReaderWithPos<R>
where
R: Read + Seek,
{
pos: u64,
reader: BufReader<R>,
}
impl<R> BufReaderWithPos<R>
where
R: Read + Seek,
{
pub fn new(mut inner_reader: R) -> io::Result<Self> {
let pos = inner_reader.stream_position()?;
let reader = BufReader::new(inner_reader);
Ok(BufReaderWithPos { pos, reader })
}
pub fn pos(&self) -> u64 {
self.pos
}
}
impl<R> Read for BufReaderWithPos<R>
where
R: Read + Seek,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
self.reader.read(buf).map(|bytes_read| {
self.pos += bytes_read as u64;
bytes_read
})
}
}
impl<R> Seek for BufReaderWithPos<R>
where
R: Read + Seek,
{
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
let offset = self.reader.seek(pos)?;
self.pos = offset;
Ok(offset)
}
}
impl Clone for BufReaderWithPos<File> {
fn clone(&self) -> Self {
let internal_reader = self.reader.get_ref().try_clone().unwrap();
Self {
pos: 0,
reader: BufReader::new(internal_reader),
}
}
}