use haagenti_core::{CompressionLevel, Compressor};
use haagenti_zstd::ZstdCompressor;
use std::io::Cursor;
fn main() {
let input1 = b"ABCDABCDABCDABCD";
test_encoding("1-seq (16 bytes)", input1);
let input2 = b"ABCDEFGHABCDEFGHABCDEFGHABCDEFGH";
test_encoding("1-seq (32 bytes)", input2);
let mut input3 = Vec::new();
for _ in 0..10 {
input3.extend_from_slice(b"ABCD");
}
input3.extend_from_slice(b"XXXX");
for _ in 0..5 {
input3.extend_from_slice(b"EFGH");
}
test_encoding("2-seq (64 bytes)", &input3);
let mut input4 = Vec::new();
for _ in 0..10 {
input4.extend_from_slice(b"ABCD");
}
input4.extend_from_slice(b"XX");
for _ in 0..8 {
input4.extend_from_slice(b"EFGH");
}
input4.extend_from_slice(b"YY");
for _ in 0..5 {
input4.extend_from_slice(b"IJKL");
}
test_encoding("3-seq (96 bytes)", &input4);
}
fn test_encoding(name: &str, input: &[u8]) {
let compressor = ZstdCompressor::with_level(CompressionLevel::Fast);
let compressed = compressor.compress(input).unwrap();
let ref_compressed = zstd::encode_all(Cursor::new(input), 1).unwrap();
let block_header =
compressed[6] as u32 | ((compressed[7] as u32) << 8) | ((compressed[8] as u32) << 16);
let block_type = (block_header >> 1) & 0x03;
let _block_size = block_header >> 3;
let seq_count = if block_type == 2 {
let block_start = 9;
let lit_header = compressed[block_start];
let lit_size_type = (lit_header >> 2) & 0x03;
let (lit_header_size, lit_size) = match lit_size_type {
0 => (1, (lit_header >> 3) as usize),
1 => (
2,
((lit_header >> 4) as usize) | ((compressed[block_start + 1] as usize) << 4),
),
_ => (3, 0),
};
let seq_start = block_start + lit_header_size + lit_size;
compressed[seq_start] as usize
} else {
0
};
let result = match zstd::decode_all(Cursor::new(&compressed)) {
Ok(decoded) if decoded == input => "OK",
Ok(_) => "MISMATCH",
Err(_) => "FAILED",
};
println!(
"{}: {} ({} seqs, block_type={}, {} bytes compressed)",
name,
result,
seq_count,
block_type,
compressed.len()
);
if result == "FAILED" && seq_count >= 2 {
println!(" Our bitstream: {:02x?}", &compressed[9..]);
println!(" Ref bitstream: {:02x?}", &ref_compressed[9..]);
let block_start = 9;
let lit_header = compressed[block_start];
let lit_size_type = (lit_header >> 2) & 0x03;
let (lit_header_size, lit_size) = match lit_size_type {
0 => (1, (lit_header >> 3) as usize),
1 => (
2,
((lit_header >> 4) as usize) | ((compressed[block_start + 1] as usize) << 4),
),
_ => (3, 0),
};
let seq_start = block_start + lit_header_size + lit_size;
let seq_section = &compressed[seq_start..];
println!(" Our seq section: {:02x?}", seq_section);
let ref_lit_header = ref_compressed[block_start];
let ref_lit_size_type = (ref_lit_header >> 2) & 0x03;
let (ref_lit_header_size, ref_lit_size) = match ref_lit_size_type {
0 => (1, (ref_lit_header >> 3) as usize),
1 => (
2,
((ref_lit_header >> 4) as usize)
| ((ref_compressed[block_start + 1] as usize) << 4),
),
_ => (3, 0),
};
let ref_seq_start = block_start + ref_lit_header_size + ref_lit_size;
let ref_block_header = ref_compressed[6] as u32
| ((ref_compressed[7] as u32) << 8)
| ((ref_compressed[8] as u32) << 16);
let ref_block_type = (ref_block_header >> 1) & 0x03;
if ref_block_type == 2 {
let ref_seq_section = &ref_compressed[ref_seq_start..];
println!(" Ref seq section: {:02x?}", ref_seq_section);
} else {
println!(" Ref uses block_type={}", ref_block_type);
}
}
}