sit-algos 0.3.0

Implementation of decompression algorithms used by StuffIt Expander and related applications
Documentation
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)
    }
}