use haagenti_core::Compressor;
use haagenti_zstd::ZstdCompressor;
fn main() {
let input = b"ABCDABCDABCDABCD";
let compressor = ZstdCompressor::new();
let ours = compressor.compress(input).unwrap();
println!("Our output ({} bytes): {:02x?}", ours.len(), &ours);
let mut pos = 0;
println!(
"\n0x{:04x}: Magic = {:02x} {:02x} {:02x} {:02x}",
pos, ours[0], ours[1], ours[2], ours[3]
);
pos += 4;
let fhd = ours[pos];
println!("0x{:04x}: FHD = 0x{:02x} (binary: {:08b})", pos, fhd, fhd);
let single_segment = (fhd >> 5) & 1 != 0;
let fcs_flag = (fhd >> 6) & 3;
println!(
" Single_Segment = {}, FCS_flag = {}",
single_segment, fcs_flag
);
pos += 1;
if !single_segment {
let wd = ours[pos];
println!("0x{:04x}: Window_Descriptor = 0x{:02x}", pos, wd);
let exp = wd >> 3;
let mantissa = wd & 7;
let window_base = 1u64 << (10 + exp);
let window_size = window_base + window_base / 8 * mantissa as u64;
println!(
" exp={}, mantissa={}, window_size={} bytes",
exp, mantissa, window_size
);
pos += 1;
}
let bh = u32::from_le_bytes([ours[pos], ours[pos + 1], ours[pos + 2], 0]);
println!(
"0x{:04x}: Block header = {:02x} {:02x} {:02x}",
pos,
ours[pos],
ours[pos + 1],
ours[pos + 2]
);
let last = bh & 1;
let block_type = (bh >> 1) & 3;
let block_size = (bh >> 3) as usize;
println!(
" last={}, type={}, size={}",
last, block_type, block_size
);
pos += 3;
let block_end = pos + block_size;
println!("0x{:04x}: Block content ({} bytes):", pos, block_size);
let lit_byte = ours[pos];
let lit_type = lit_byte & 3;
let size_format = (lit_byte >> 2) & 3;
println!(" 0x{:04x}: Literals header = 0x{:02x}", pos, lit_byte);
println!(" type={}, size_format={}", lit_type, size_format);
let (lit_size, header_len) = match size_format {
0 | 2 => ((lit_byte >> 3) as usize, 1usize),
1 => {
let size = ((ours[pos] >> 4) as usize) | ((ours[pos + 1] as usize) << 4);
(size, 2)
}
3 => {
let size = ((ours[pos] >> 4) as usize)
| ((ours[pos + 1] as usize) << 4)
| ((ours[pos + 2] as usize) << 12);
(size, 3)
}
_ => unreachable!(),
};
println!(" lit_size={}, header_len={}", lit_size, header_len);
pos += header_len;
print!(" 0x{:04x}: Literals: ", pos);
for i in 0..lit_size {
print!("{:02x} ", ours[pos + i]);
}
println!(
"(\"{}\")",
String::from_utf8_lossy(&ours[pos..pos + lit_size])
);
pos += lit_size;
println!(" 0x{:04x}: Sequences section:", pos);
let seq_count = ours[pos];
println!(" Count byte: 0x{:02x} = {}", seq_count, seq_count);
pos += 1;
if seq_count > 0 {
let mode_byte = ours[pos];
println!(" Mode byte: 0x{:02x} = {:08b}", mode_byte, mode_byte);
let ll_mode = mode_byte & 3;
let of_mode = (mode_byte >> 2) & 3;
let ml_mode = (mode_byte >> 4) & 3;
println!(
" LL_mode={}, OF_mode={}, ML_mode={}",
ll_mode, of_mode, ml_mode
);
pos += 1;
if ll_mode == 1 && of_mode == 1 && ml_mode == 1 {
println!(
" RLE symbols: LL={}, OF={}, ML={}",
ours[pos],
ours[pos + 1],
ours[pos + 2]
);
pos += 3;
}
println!(
" Bitstream ({} bytes): {:02x?}",
block_end - pos,
&ours[pos..block_end]
);
}
println!("\n=== Sequence interpretation ===");
println!("LL code 4 -> literal_length = 4");
println!("OF code 1 -> offset_value = (1 << 1) + 0 = 2");
println!(" Using repeat_offset_2 = 4, actual offset = 4");
println!("ML code 9 -> match_length = 3 + 9 = 12");
println!();
println!("Decoding:");
println!("1. Copy 4 literals: ABCD");
println!("2. Copy 12 bytes from offset 4: ABCDABCDABCD");
println!("Result: ABCDABCDABCDABCD (16 bytes)");
println!("\n=== Reference decode ===");
match zstd::decode_all(std::io::Cursor::new(&ours)) {
Ok(dec) => {
println!("SUCCESS: {} bytes", dec.len());
println!("Content: {:?}", String::from_utf8_lossy(&dec));
}
Err(e) => println!("FAILED: {:?}", e),
}
}