use std::io::{Read, Seek, Write};
use flate2::read::ZlibDecoder;
use crate::{
error::{Error, Result},
file::BasicFileEntry,
read::{BlockSize, read_u16},
};
pub(crate) fn decompress<R, W, F>(
reader: &mut R,
writer: &mut W,
entry: &F,
block_size: BlockSize,
block_sizes: &[u32],
) -> Result<()>
where
R: Read + Seek,
W: Write,
F: BasicFileEntry,
{
let block_size = usize::try_from(block_size.as_u32()).map_err(|_| Error::AddressTooSmall)?;
let total_blocks = entry.output_size().div_ceil(block_size);
let block_start = entry.index_list_size() as usize;
for block_length in &block_sizes[block_start..block_start + total_blocks] {
let zlib_magic = read_u16(reader)
.unwrap_or_default();
reader.seek_relative(-2)?;
let mut slice = reader.by_ref().take(u64::from(*block_length));
if zlib_magic == 0x78DA || zlib_magic == 0x7801 {
let mut decoder = ZlibDecoder::new(slice);
std::io::copy(&mut decoder, writer)
.map_err(|_| Error::Corrupt("could not copy decoded bytes to output"))?;
} else {
std::io::copy(&mut slice, writer)
.map_err(|_| Error::Corrupt("could not copy bytes to output"))?;
}
}
Ok(())
}