preflate-rs 0.7.0

Decompresses existing DEFLATE streams to allow for better compression (eg with ZStandard) while allowing the exact original binary DEFLATE stream to be recreated by detecting the parameters used during compression.
Documentation
use std::{
    collections::VecDeque,
    io::{Cursor, Error, ErrorKind, Read, Result, SeekFrom},
};

use crate::PreflateError;

pub trait ScopedRead: Read
where
    Self: Sized,
{
    fn peek(&self, position: usize) -> Result<u8>;
    fn advance(&mut self, amount: usize);

    fn scoped_read<
        T,
        F: FnOnce(&mut ScopedReaderWrapper<Self>) -> core::result::Result<T, PreflateError>,
    >(
        &mut self,
        f: F,
    ) -> core::result::Result<T, PreflateError> {
        let mut w = ScopedReaderWrapper {
            inner: self,
            position: 0,
        };
        let r = f(&mut w);
        let inner_pos = w.position;
        match r {
            Ok(t) => {
                self.advance(inner_pos);
                Ok(t)
            }
            Err(e) => Err(e),
        }
    }
}

impl ScopedRead for VecDeque<u8> {
    fn peek(&self, position: usize) -> Result<u8> {
        if position >= self.len() {
            return Err(Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF"));
        }
        Ok(self[position])
    }

    fn advance(&mut self, position: usize) {
        self.drain(0..position);
    }
}

impl<T: AsRef<[u8]>> ScopedRead for Cursor<T> {
    fn peek(&self, position: usize) -> Result<u8> {
        let read_pos = self.position() as usize + position;
        if read_pos >= self.get_ref().as_ref().len() {
            return Err(Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF"));
        }

        Ok(self.get_ref().as_ref()[read_pos])
    }

    fn advance(&mut self, position: usize) {
        std::io::Seek::seek(self, SeekFrom::Current(position as i64)).unwrap();
    }
}

pub struct ScopedReaderWrapper<'a, R: ScopedRead> {
    inner: &'a mut R,
    position: usize,
}

impl<T: ScopedRead> Read for ScopedReaderWrapper<'_, T> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let mut i = 0;
        while i < buf.len() {
            buf[i] = self.inner.peek(self.position)?;
            self.position += 1;
            i += 1;
        }

        Ok(i)
    }
}