ck3save 0.4.3

Ergonomically work with all CK3 saves (regular and ironman)
Documentation
#[derive(thiserror::Error, Debug)]
pub(crate) enum ZipInflationError {
    #[error("unable to inflate: {msg}")]
    BadData { msg: String },

    #[error("early eof, only able to write {written} bytes")]
    EarlyEof { written: usize },
}

#[cfg(all(feature = "miniz", not(feature = "libdeflate")))]
pub(crate) fn inflate_exact(raw: &[u8], out: &mut [u8]) -> Result<(), ZipInflationError> {
    let inflation = miniz_oxide::inflate::decompress_slice_iter_to_slice(
        out,
        std::iter::once(raw),
        false,
        false,
    );

    match inflation {
        Ok(written) if written == out.len() => Ok(()),
        Ok(written) => Err(ZipInflationError::EarlyEof { written }),
        Err(miniz_oxide::inflate::TINFLStatus::HasMoreOutput) => Ok(()),
        Err(e) => Err(ZipInflationError::BadData {
            msg: format!("{:?}", e),
        }),
    }
}

#[cfg(feature = "libdeflate")]
pub(crate) fn inflate_exact(raw: &[u8], out: &mut [u8]) -> Result<(), ZipInflationError> {
    let inflation = libdeflater::Decompressor::new().deflate_decompress(raw, out);

    match inflation {
        Ok(written) if written == out.len() => Ok(()),
        Ok(written) => Err(ZipInflationError::EarlyEof { written }),
        Err(libdeflater::DecompressionError::InsufficientSpace) => Ok(()),
        Err(e) => Err(ZipInflationError::BadData { msg: e.to_string() }),
    }
}