use crate::{
BytesRead, ReadError, BytesWrite, WriteError, BytesSeek, SeekError, Bytes
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Offset<T> {
offset: usize,
inner: T
}
impl<T> Offset<T> {
pub fn new(mut inner: T, offset: usize) -> Self
where T: BytesRead + BytesSeek {
inner.seek(inner.position() + offset);
Self { inner, offset }
}
pub fn set_offset(&mut self, offset: usize)
where T: BytesSeek {
let prev_pos = self.inner.position() - self.offset;
self.inner.seek(prev_pos + offset);
self.offset = offset;
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn inner(&self) -> &T {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn into_inner(self) -> T {
self.inner
}
}
impl<T> BytesRead for Offset<T>
where T: BytesRead {
#[inline]
fn as_slice(&self) -> &[u8] {
&self.inner.as_slice()[self.offset..]
}
#[inline]
fn remaining(&self) -> &[u8] {
self.inner.remaining()
}
fn try_read(&mut self, len: usize) -> Result<&[u8], ReadError> {
self.inner.try_read(len)
}
fn peek(&self, len: usize) -> Option<&[u8]> {
self.inner.peek(len)
}
}
impl<T> BytesSeek for Offset<T>
where T: BytesSeek {
fn position(&self) -> usize {
self.inner.position() - self.offset
}
fn try_seek(&mut self, pos: usize) -> Result<(), SeekError> {
self.inner.try_seek(self.offset + pos)
}
}
impl<T> BytesWrite for Offset<T>
where T: BytesWrite {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.inner.as_mut()[self.offset..]
}
fn as_bytes(&self) -> Bytes<'_> {
self.inner.as_bytes().inner()[self.offset..].into()
}
fn remaining_mut(&mut self) -> &mut [u8] {
self.inner.remaining_mut()
}
fn try_write(&mut self, slice: impl AsRef<[u8]>) -> Result<(), WriteError> {
self.inner.try_write(slice)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Cursor;
#[test]
fn write() {
let cursor = Cursor::new(vec![1, 2, 3, 4]);
let mut offset_cursor = Offset::new(cursor, 2);
assert_eq!(offset_cursor.remaining_mut().len(), 2);
offset_cursor.write(&[1]);
assert_eq!(offset_cursor.remaining_mut().len(), 1);
offset_cursor.write(&[2]);
assert_eq!(offset_cursor.remaining_mut().len(), 0);
offset_cursor.write(&[1, 2]);
assert_eq!(offset_cursor.as_mut(), &[1, 2, 1, 2]);
}
#[test]
fn read() {
let cursor = Cursor::new(vec![1, 2, 3, 4]);
let mut offset_cursor = Offset::new(cursor, 2);
assert_eq!(offset_cursor.position(), 0);
offset_cursor.seek(1);
assert_eq!(offset_cursor.position(), 1);
assert_eq!(offset_cursor.as_slice(), &[3, 4]);
assert_eq!(offset_cursor.remaining(), &[4]);
offset_cursor.set_offset(1);
assert_eq!(offset_cursor.position(), 1);
assert_eq!(offset_cursor.as_slice(), &[2, 3, 4]);
assert_eq!(offset_cursor.remaining(), &[3, 4]);
}
}