use flate2::read::ZlibDecoder;
use lz4::block::decompress_to_buffer as LZ4_decompress_to_buffer;
use std::io::Read;
use xz2::read::XzDecoder;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
Io(std::io::Error),
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::Io(e)
}
}
const HEADER_SIZE: usize = 9;
#[allow(dead_code)]
const K_MAX_COMPRESSED_BLOCK_SIZE: usize = 0xffffff;
#[allow(dead_code)]
#[derive(PartialEq)]
enum Kind {
#[allow(dead_code)]
Inherit = -1,
UseGlobal = 0,
Zlib = 1,
Lzma = 2,
OldCompression = 3,
LZ4 = 4,
Zstd = 5,
UndefinedCompression = 6,
}
fn kind_of(buf: &[u8]) -> Kind {
match (buf[0] as char, buf[1] as char) {
('Z', 'L') => Kind::Zlib,
('X', 'Z') => Kind::Lzma,
('L', '4') => Kind::LZ4,
('Z', 'S') => Kind::Zstd,
('C', 'S') => Kind::OldCompression,
_ => Kind::UndefinedCompression,
}
}
pub fn decompress(dst: &mut [u8], mut src: &[u8]) -> Result<usize> {
let _beg = 0;
let mut end = 0;
let buflen = dst.len() as i64;
let mut hdr = [0_u8; HEADER_SIZE];
while end < buflen {
src.read_exact(&mut hdr)?;
let _srcsz = hdr[3] as i64 | (hdr[4] as i64) << 8 | (hdr[5] as i64) << 16;
let tgtsz = hdr[6] as i64 | (hdr[7] as i64) << 8 | (hdr[8] as i64) << 16;
end += tgtsz;
match kind_of(hdr.as_ref()) {
Kind::Inherit => {
unimplemented!()
}
Kind::UseGlobal => {
unimplemented!()
}
Kind::Zlib => {
let mut d = ZlibDecoder::new(src);
d.read_exact(dst.as_mut())?;
return Ok(0);
}
Kind::Lzma => {
let mut d = XzDecoder::new(src);
d.read_exact(dst.as_mut())?;
}
Kind::OldCompression => {
unimplemented!()
}
Kind::LZ4 => {
LZ4_decompress_to_buffer(&src[8..], Some(dst.len() as i32), dst)?;
return Ok(0);
}
Kind::Zstd => {
unimplemented!()
}
Kind::UndefinedCompression => {
unimplemented!()
}
}
}
Ok(0)
}
fn root_compress_algo_level(algo: i32) -> (Kind, i32) {
let kind = algo / 100;
let level = algo % 100;
let kind = match kind {
0 => Kind::UseGlobal,
1 => Kind::Zlib,
2 => Kind::Lzma,
3 => Kind::OldCompression,
4 => Kind::LZ4,
5 => Kind::Zstd,
_ => Kind::UndefinedCompression,
};
(kind, level)
}
pub fn compress(src: Vec<u8>, compression: i32) -> Result<Vec<u8>> {
assert_eq!(compression, 1);
let (kind, level) = root_compress_algo_level(compression);
if kind == Kind::UseGlobal || level == 0 || src.len() < 512 {
return Ok(src);
}
unimplemented!();
}