Make PackBitsReader incrementally decompress output

This commit is contained in:
Jonathan Behrens committed 2022-04-15 12:25:24 -04:00
1 parent 167088b33d
commit 7881291032
2 files changed
+57 -42

No files matched your search

+4 -3
View File
@@ -1141,9 +1141,10 @@ impl<R: Read + Seek> Decoder<R> {
CompressionMethod::LZW => { CompressionMethod::LZW => {
Box::new(LZWReader::new(reader, usize::try_from(compressed_length)?)) Box::new(LZWReader::new(reader, usize::try_from(compressed_length)?))
} }
CompressionMethod::PackBits => { CompressionMethod::PackBits => Box::new(PackBitsReader::new(
Box::new(PackBitsReader::new(reader, usize::try_from(compressed_length)?)?.1) reader,
} usize::try_from(compressed_length)?,
)),
CompressionMethod::Deflate | CompressionMethod::OldDeflate => { CompressionMethod::Deflate | CompressionMethod::OldDeflate => {
Box::new(DeflateReader::new(reader)) Box::new(DeflateReader::new(reader))
} }
+53 -39
View File
@@ -255,56 +255,70 @@ impl Read for JpegReader {
/// ## PackBits Reader /// ## PackBits Reader
/// ///
/// Reader that unpacks Apple's `PackBits` format enum PackBitsReaderState {
pub struct PackBitsReader { Header,
buffer: io::Cursor<Vec<u8>>, Literal,
Repeat { value: u8 },
} }
impl PackBitsReader { /// Reader that unpacks Apple's `PackBits` format
pub struct PackBitsReader<R: Read> {
reader: Take<R>,
state: PackBitsReaderState,
count: usize,
}
impl<R: Read> PackBitsReader<R> {
/// Wraps a reader /// Wraps a reader
pub fn new<R: Read + Seek>( pub fn new(reader: R, length: usize) -> Self {
mut reader: R, Self {
length: usize, reader: reader.take(length as u64),
) -> io::Result<(usize, PackBitsReader)> { state: PackBitsReaderState::Header,
let mut buffer = Vec::new(); count: 0,
let mut header: [u8; 1] = [0]; }
let mut data: [u8; 1] = [0]; }
}
let mut bytes_read = 0; impl<R: Read> Read for PackBitsReader<R> {
while bytes_read < length { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
reader.read_exact(&mut header)?; while let PackBitsReaderState::Header = self.state {
bytes_read += 1; if self.reader.limit() == 0 {
return Ok(0);
let h = header[0] as i8; }
let mut header: [u8; 1] = [0];
self.reader.read_exact(&mut header)?;
let h = dbg!(header[0] as i8);
if h >= -127 && h <= -1 { if h >= -127 && h <= -1 {
let new_len = buffer.len() + (1 - h as isize) as usize; let mut data: [u8; 1] = [0];
reader.read_exact(&mut data)?; self.reader.read_exact(&mut data)?;
buffer.resize(new_len, data[0]); self.state = PackBitsReaderState::Repeat { value: data[0] };
bytes_read += 1; self.count = (1 - h as isize) as usize;
} else if h >= 0 { } else if h >= 0 {
let num_vals = h as usize + 1; self.state = PackBitsReaderState::Literal;
let start = buffer.len(); self.count = h as usize + 1;
buffer.resize(start + num_vals, 0);
reader.read_exact(&mut buffer[start..])?;
bytes_read += num_vals
} else { } else {
// h = -128 is a no-op. // h = -128 is a no-op.
} }
} }
Ok(( let length = buf.len().min(self.count);
buffer.len(), match self.state {
PackBitsReader { PackBitsReaderState::Literal => {
buffer: io::Cursor::new(buffer), self.reader.read(&mut buf[..length])?;
}, }
)) PackBitsReaderState::Repeat { value } => {
} for b in &mut buf[..length] {
} *b = value;
}
}
PackBitsReaderState::Header => unreachable!(),
}
impl Read for PackBitsReader { self.count -= length;
#[inline] if self.count <= buf.len() {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.state = PackBitsReaderState::Header;
self.buffer.read(buf) }
return Ok(length);
} }
} }
@@ -377,7 +391,7 @@ mod test {
let encoded_len = encoded.len(); let encoded_len = encoded.len();
let buff = io::Cursor::new(encoded); let buff = io::Cursor::new(encoded);
let (_, mut decoder) = PackBitsReader::new(buff, encoded_len).unwrap(); let mut decoder = PackBitsReader::new(buff, encoded_len);
let mut decoded = Vec::new(); let mut decoded = Vec::new();
decoder.read_to_end(&mut decoded).unwrap(); decoder.read_to_end(&mut decoded).unwrap();