use super::byte_source::ByteSource;
use std::io::{self, Read, Seek, SeekFrom};
use std::sync::Arc;
pub struct ByteSourceCursor {
inner: Arc<dyn ByteSource>,
position: u64,
}
impl ByteSourceCursor {
pub fn new(inner: Arc<dyn ByteSource>) -> Self {
Self { inner, position: 0 }
}
}
impl Read for ByteSourceCursor {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let total_len = self.inner.len();
if self.position >= total_len {
return Ok(0);
}
let max_read = (total_len - self.position).min(buf.len() as u64) as usize;
let data = self.inner.read_at(self.position, max_read)?;
buf[..data.len()].copy_from_slice(&data);
self.position += data.len() as u64;
Ok(data.len())
}
}
impl Seek for ByteSourceCursor {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
let total_len = self.inner.len() as i64;
let current_pos = self.position as i64;
let new_pos = match pos {
SeekFrom::Start(p) => p as i64,
SeekFrom::End(p) => total_len + p,
SeekFrom::Current(p) => current_pos + p,
};
if new_pos < 0 {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "Seek before 0"));
}
self.position = new_pos as u64;
Ok(self.position)
}
}