oxipng/src/deflate/deflater.rs
2020-04-15 13:26:28 -04:00

31 lines
1.2 KiB
Rust

use crate::atomicmin::AtomicMin;
use crate::{PngError, PngResult};
use libdeflater::{CompressionError, CompressionLvl, Compressor};
pub fn deflate(data: &[u8], max_size: &AtomicMin) -> PngResult<Vec<u8>> {
let mut compressor = Compressor::new(CompressionLvl::best());
let capacity = max_size.get().unwrap_or(data.len() / 2);
let mut dest = Vec::with_capacity(capacity);
unsafe {
// This is ok because the Vec contains Copy-able data (u8)
// and because libdeflater wrapper doesn't try to read
// the bytes from the target.
//
// That said, it should be able to accept MaybeUninit instead,
// so I raised an upstream issue that should make this safer:
// https://github.com/adamkewley/libdeflater/issues/1
dest.set_len(capacity);
}
let len = compressor
.zlib_compress(data, &mut dest)
.map_err(|err| match err {
CompressionError::InsufficientSpace => PngError::DeflatedDataTooLong(capacity),
})?;
if let Some(max) = max_size.get() {
if len > max {
return Err(PngError::DeflatedDataTooLong(max));
}
}
dest.truncate(len);
Ok(dest)
}