jubako 0.3.0

The reference implementation of the Jubako container format
Documentation
use std::fs::File;
use std::io;
use std::io::Seek;
use std::ops::{Deref, DerefMut};

#[derive(Debug)]
pub(crate) struct Skip<R> {
    inner: R,
    skip: u64,
}

impl<R> Skip<R>
where
    R: Seek,
{
    pub fn new(mut inner: R) -> io::Result<Self> {
        let skip = inner.stream_position()?;
        Ok(Self { inner, skip })
    }
}

impl<R> Skip<R> {
    #[inline]
    pub fn into_inner(self) -> R {
        self.inner
    }

    pub fn inner_mut(&mut self) -> &mut R {
        &mut self.inner
    }
}

impl<R> io::Read for Skip<R>
where
    R: io::Read,
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.read(buf)
    }
}

impl<R> io::Write for Skip<R>
where
    R: io::Write,
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.inner.flush()
    }
}

impl<R> io::Seek for Skip<R>
where
    R: io::Seek,
{
    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
        let new_pos = match pos {
            io::SeekFrom::Start(s) => self.inner.seek(io::SeekFrom::Start(self.skip + s))?,
            _ => self.inner.seek(pos)?,
        };
        if new_pos < self.skip {
            Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "You cannot seek before skip",
            ))
        } else {
            Ok(new_pos - self.skip)
        }
    }
}

impl TryFrom<File> for Skip<File> {
    type Error = io::Error;
    fn try_from(f: File) -> io::Result<Self> {
        Self::new(f)
    }
}

impl<R> Deref for Skip<R> {
    type Target = R;
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<R> DerefMut for Skip<R> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner_mut()
    }
}

impl AsMut<File> for Skip<File> {
    fn as_mut(&mut self) -> &mut File {
        self.inner_mut()
    }
}