eu4save/
deflate.rs

1#[derive(thiserror::Error, Debug)]
2pub(crate) enum ZipInflationError {
3    #[error("unable to inflate: {msg}")]
4    BadData { msg: String },
5
6    #[error("early eof, only able to write {written} bytes")]
7    EarlyEof { written: usize },
8}
9
10#[cfg(all(feature = "miniz", not(feature = "libdeflate")))]
11pub(crate) fn inflate_exact(raw: &[u8], out: &mut [u8]) -> Result<(), ZipInflationError> {
12    let inflation = miniz_oxide::inflate::decompress_slice_iter_to_slice(
13        out,
14        std::iter::once(raw),
15        false,
16        false,
17    );
18
19    match inflation {
20        Ok(written) if written == out.len() => Ok(()),
21        Ok(written) => Err(ZipInflationError::EarlyEof { written }),
22        Err(miniz_oxide::inflate::TINFLStatus::HasMoreOutput) => Ok(()),
23        Err(e) => Err(ZipInflationError::BadData {
24            msg: format!("{:?}", e),
25        }),
26    }
27}
28
29#[cfg(feature = "libdeflate")]
30pub(crate) fn inflate_exact(raw: &[u8], out: &mut [u8]) -> Result<(), ZipInflationError> {
31    let inflation = libdeflater::Decompressor::new().deflate_decompress(raw, out);
32
33    match inflation {
34        Ok(written) if written == out.len() => Ok(()),
35        Ok(written) => Err(ZipInflationError::EarlyEof { written }),
36        Err(libdeflater::DecompressionError::InsufficientSpace) => Ok(()),
37        Err(e) => Err(ZipInflationError::BadData { msg: e.to_string() }),
38    }
39}