use ::core::convert::From;
use crate::alloc::vec;
use crate::alloc::vec::Vec;
mod buffer;
pub mod core;
mod stored;
pub mod stream;
mod zlib;
use self::core::*;
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum CompressionLevel {
NoCompression = 0,
BestSpeed = 1,
BestCompression = 9,
UberCompression = 10,
DefaultLevel = 6,
DefaultCompression = -1,
}
impl From<CompressionLevel> for i8 {
fn from(level: CompressionLevel) -> i8 {
level as i8
}
}
impl From<CompressionLevel> for i32 {
fn from(level: CompressionLevel) -> i32 {
level as i32
}
}
impl From<CompressionLevel> for u8 {
fn from(level: CompressionLevel) -> u8 {
if (level as i32) < 0 {
6
} else {
level as u8
}
}
}
pub fn compress_to_vec(input: &[u8], level: u8) -> Vec<u8> {
compress_to_vec_inner(input, level, 0, 0)
}
pub fn compress_to_vec_zlib(input: &[u8], level: u8) -> Vec<u8> {
compress_to_vec_inner(input, level, 1, 0)
}
fn compress_to_vec_inner(mut input: &[u8], level: u8, window_bits: i32, strategy: i32) -> Vec<u8> {
let flags = create_comp_flags_from_zip_params(level.into(), window_bits, strategy);
let mut compressor = CompressorOxide::new(flags);
let mut output = vec![0; ::core::cmp::max(input.len() / 2, 2)];
let mut out_pos = 0;
loop {
let (status, bytes_in, bytes_out) = compress(
&mut compressor,
input,
&mut output[out_pos..],
TDEFLFlush::Finish,
);
out_pos += bytes_out;
match status {
TDEFLStatus::Done => {
output.truncate(out_pos);
break;
}
TDEFLStatus::Okay if bytes_in <= input.len() => {
input = &input[bytes_in..];
if output.len().saturating_sub(out_pos) < 30 {
output.resize(output.len() * 2, 0)
}
}
_ => panic!("Bug! Unexpectedly failed to compress!"),
}
}
output
}
#[cfg(test)]
mod test {
use super::{compress_to_vec, compress_to_vec_inner, CompressionStrategy};
use crate::inflate::decompress_to_vec;
use alloc::vec;
#[test]
fn compress_small() {
let test_data = b"Deflate late";
let check = [
0x73, 0x49, 0x4d, 0xcb, 0x49, 0x2c, 0x49, 0x55, 0x00, 0x11, 0x00,
];
let res = compress_to_vec(test_data, 1);
assert_eq!(&check[..], res.as_slice());
let res = compress_to_vec(test_data, 9);
assert_eq!(&check[..], res.as_slice());
}
#[test]
fn compress_huff_only() {
let test_data = b"Deflate late";
let res = compress_to_vec_inner(test_data, 1, 0, CompressionStrategy::HuffmanOnly as i32);
let d = decompress_to_vec(res.as_slice()).expect("Failed to decompress!");
assert_eq!(test_data, d.as_slice());
}
#[test]
fn compress_rle() {
let test_data = b"Deflate late";
let res = compress_to_vec_inner(test_data, 1, 0, CompressionStrategy::RLE as i32);
let d = decompress_to_vec(res.as_slice()).expect("Failed to decompress!");
assert_eq!(test_data, d.as_slice());
}
#[test]
fn compress_raw() {
let text = b"Hello, zlib!";
let encoded = {
let len = text.len();
let notlen = !len;
let mut encoded = vec![
1,
len as u8,
(len >> 8) as u8,
notlen as u8,
(notlen >> 8) as u8,
];
encoded.extend_from_slice(&text[..]);
encoded
};
let res = compress_to_vec(text, 0);
assert_eq!(encoded, res.as_slice());
}
#[test]
fn short() {
let test_data = [10, 10, 10, 10, 10, 55];
let c = compress_to_vec(&test_data, 9);
let d = decompress_to_vec(c.as_slice()).expect("Failed to decompress!");
assert_eq!(&test_data, d.as_slice());
assert!(c.len() <= 6);
}
}