use std::io;
pub struct NoneReader<R> {
inner: R,
start: u64,
end: u64,
position: u64,
}
impl<R> NoneReader<R> {
pub fn with_length(inner: R, start: u64, length: u64) -> Self {
Self {
inner,
start,
end: start + length,
position: 0,
}
}
}
impl<R: io::Read> io::Read for NoneReader<R> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if self.start + self.position >= self.end {
return Ok(0);
}
if self.start + self.position + buf.len() as u64 >= self.end {
let available_bytes = self.end - self.start - self.position;
let result = self.inner.read(&mut buf[0..(available_bytes as usize)])?;
self.position += result as u64;
return Ok(result);
}
let consumed = self.inner.read(buf)?;
self.position += consumed as u64;
Ok(consumed)
}
}
impl<R: io::Seek> io::Seek for NoneReader<R> {
#[inline]
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
match pos {
io::SeekFrom::Start(pos) => {
let new_offset = self.inner.seek(io::SeekFrom::Start(pos + self.start))?;
self.position = new_offset - self.start;
Ok(self.position)
}
io::SeekFrom::End(pos) => {
let new_offset = self
.inner
.seek(io::SeekFrom::Start((self.end as i64 + pos) as u64))?;
self.position = new_offset - self.start;
Ok(self.position)
}
io::SeekFrom::Current(pos) => {
if pos == 0 {
return Ok(self.position);
}
let new_offset = self.inner.seek(io::SeekFrom::Current(pos))?;
self.position = new_offset - self.start;
Ok(self.position)
}
}
}
#[inline]
fn stream_position(&mut self) -> io::Result<u64> {
Ok(self.position)
}
#[inline]
fn stream_len(&mut self) -> io::Result<u64> {
Ok(self.end - self.start)
}
}