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}