use std::io::Cursor;
fn main() {
test_raw_block();
test_one_sequence();
test_two_sequences();
test_reference_compression();
}
fn test_raw_block() {
println!("\n=== Test: Raw block (no sequences) ===");
let input = b"hello world";
let mut frame = Vec::new();
frame.extend_from_slice(&0xFD2FB528u32.to_le_bytes());
frame.push(0x00);
frame.push(0x48);
let block_header = (11u32 << 3) | 0x01; frame.extend_from_slice(&block_header.to_le_bytes()[0..3]);
frame.extend_from_slice(input);
println!("Frame hex: {:02x?}", frame);
match zstd::decode_all(Cursor::new(&frame)) {
Ok(decoded) if decoded == input => println!("Result: OK"),
Ok(decoded) => println!(
"Result: MISMATCH - got {:?}",
String::from_utf8_lossy(&decoded)
),
Err(e) => println!("Result: FAILED - {:?}", e),
}
}
fn test_one_sequence() {
println!("\n=== Test: Compressed block with 1 sequence ===");
let expected = b"abcdabcd";
let mut frame = Vec::new();
frame.extend_from_slice(&0xFD2FB528u32.to_le_bytes());
frame.push(0x00);
frame.push(0x48);
let mut block = Vec::new();
block.push(0x20);
block.extend_from_slice(b"abcd");
block.push(0x01);
block.push(0x00);
use haagenti_zstd::block::Sequence;
use haagenti_zstd::compress::EncodedSequence;
use haagenti_zstd::fse::{FseBitWriter, InterleavedTansEncoder};
let seq = Sequence::new(4, 2, 4); let enc = EncodedSequence::from_sequence(&seq);
println!(
" Encoded: ll_code={}, of_code={}, ml_code={}",
enc.ll_code, enc.of_code, enc.ml_code
);
println!(
" Extras: ll={}({}b), of={}({}b), ml={}({}b)",
enc.ll_extra, enc.ll_bits, enc.of_extra, enc.of_bits, enc.ml_extra, enc.ml_bits
);
let mut tans = InterleavedTansEncoder::new_predefined();
let (ll_log, of_log, ml_log) = tans.accuracy_logs();
tans.init_states(enc.ll_code, enc.of_code, enc.ml_code);
let (ll_state, of_state, ml_state) = tans.get_states();
println!(
" States: LL={}, OF={}, ML={}",
ll_state, of_state, ml_state
);
let mut bits = FseBitWriter::new();
if enc.ll_bits > 0 {
bits.write_bits(enc.ll_extra, enc.ll_bits);
}
if enc.ml_bits > 0 {
bits.write_bits(enc.ml_extra, enc.ml_bits);
}
if enc.of_bits > 0 {
bits.write_bits(enc.of_extra, enc.of_bits);
}
bits.write_bits(ml_state, ml_log);
bits.write_bits(of_state, of_log);
bits.write_bits(ll_state, ll_log);
let bitstream = bits.finish();
println!(" Bitstream: {:02x?}", bitstream);
block.extend_from_slice(&bitstream);
let block_size = block.len() as u32;
let block_header = (block_size << 3) | 0x05; frame.extend_from_slice(&block_header.to_le_bytes()[0..3]);
frame.extend_from_slice(&block);
println!(" Frame hex: {:02x?}", frame);
match zstd::decode_all(Cursor::new(&frame)) {
Ok(decoded) if decoded == expected => println!(" Result: OK"),
Ok(decoded) => println!(
" Result: MISMATCH - got {:?}",
String::from_utf8_lossy(&decoded)
),
Err(e) => println!(" Result: FAILED - {:?}", e),
}
}
fn test_two_sequences() {
println!("\n=== Test: Compressed block with 2 sequences ===");
let expected = b"abcdefghXabcdefghYabcd";
let mut frame = Vec::new();
frame.extend_from_slice(&0xFD2FB528u32.to_le_bytes());
frame.push(0x00);
frame.push(0x48);
let mut block = Vec::new();
block.push(0x50);
block.extend_from_slice(b"abcdefghXY");
block.push(0x02); block.push(0x00);
use haagenti_zstd::block::Sequence;
use haagenti_zstd::compress::EncodedSequence;
use haagenti_zstd::fse::{FseBitWriter, InterleavedTansEncoder};
let sequences = [Sequence::new(9, 12, 8), Sequence::new(1, 1, 4)];
let encoded: Vec<_> = sequences
.iter()
.map(EncodedSequence::from_sequence)
.collect();
for (i, enc) in encoded.iter().enumerate() {
println!(
" Seq {}: ll_code={}, of_code={}, ml_code={}",
i, enc.ll_code, enc.of_code, enc.ml_code
);
println!(
" extras: ll={}({}b), of={}({}b), ml={}({}b)",
enc.ll_extra, enc.ll_bits, enc.of_extra, enc.of_bits, enc.ml_extra, enc.ml_bits
);
}
let mut tans = InterleavedTansEncoder::new_predefined();
let (ll_log, of_log, ml_log) = tans.accuracy_logs();
let last = &encoded[1];
tans.init_states(last.ll_code, last.of_code, last.ml_code);
let fse_bits = tans.encode_sequence(encoded[0].ll_code, encoded[0].of_code, encoded[0].ml_code);
let (ll_state, of_state, ml_state) = tans.get_states();
println!(
" FSE bits for seq 0: LL({},{}) OF({},{}) ML({},{})",
fse_bits[0].0, fse_bits[0].1, fse_bits[1].0, fse_bits[1].1, fse_bits[2].0, fse_bits[2].1
);
println!(
" Final states: LL={}, OF={}, ML={}",
ll_state, of_state, ml_state
);
let mut bits = FseBitWriter::new();
let seq0 = &encoded[0];
if seq0.ll_bits > 0 {
bits.write_bits(seq0.ll_extra, seq0.ll_bits);
}
if seq0.ml_bits > 0 {
bits.write_bits(seq0.ml_extra, seq0.ml_bits);
}
if seq0.of_bits > 0 {
bits.write_bits(seq0.of_extra, seq0.of_bits);
}
bits.write_bits(fse_bits[0].0, fse_bits[0].1); bits.write_bits(fse_bits[2].0, fse_bits[2].1); bits.write_bits(fse_bits[1].0, fse_bits[1].1);
if last.ll_bits > 0 {
bits.write_bits(last.ll_extra, last.ll_bits);
}
if last.ml_bits > 0 {
bits.write_bits(last.ml_extra, last.ml_bits);
}
if last.of_bits > 0 {
bits.write_bits(last.of_extra, last.of_bits);
}
bits.write_bits(ml_state, ml_log);
bits.write_bits(of_state, of_log);
bits.write_bits(ll_state, ll_log);
let bitstream = bits.finish();
println!(" Bitstream: {:02x?}", bitstream);
block.extend_from_slice(&bitstream);
let block_size = block.len() as u32;
let block_header = (block_size << 3) | 0x05;
frame.extend_from_slice(&block_header.to_le_bytes()[0..3]);
frame.extend_from_slice(&block);
println!(" Frame hex: {:02x?}", frame);
println!(" Block size: {}", block_size);
match zstd::decode_all(Cursor::new(&frame)) {
Ok(decoded) if decoded == expected => println!(" Result: OK"),
Ok(decoded) => println!(
" Result: MISMATCH - got {:?}",
String::from_utf8_lossy(&decoded)
),
Err(e) => println!(" Result: FAILED - {:?}", e),
}
}
fn test_reference_compression() {
println!("\n=== Test: Reference zstd compression ===");
let input = b"abcdefghXabcdefghYabcd";
let compressed = zstd::encode_all(Cursor::new(input.as_slice()), 1).unwrap();
println!(" Reference compressed: {:02x?}", compressed);
println!(" Reference size: {} bytes", compressed.len());
let decoded = zstd::decode_all(Cursor::new(&compressed)).unwrap();
assert_eq!(decoded, input);
println!(" Reference decode: OK");
use haagenti_core::{CompressionLevel, Compressor};
use haagenti_zstd::ZstdCompressor;
let compressor = ZstdCompressor::with_level(CompressionLevel::Fast);
let our_compressed = compressor.compress(input).unwrap();
println!("\n Our compressed: {:02x?}", our_compressed);
println!(" Our size: {} bytes", our_compressed.len());
println!("\n Comparison:");
let max_len = compressed.len().max(our_compressed.len());
for i in 0..max_len {
let ref_byte = compressed
.get(i)
.map(|b| format!("{:02x}", b))
.unwrap_or_else(|| " ".to_string());
let our_byte = our_compressed
.get(i)
.map(|b| format!("{:02x}", b))
.unwrap_or_else(|| " ".to_string());
let marker = if compressed.get(i) == our_compressed.get(i) {
" "
} else {
"*"
};
println!(" {:3}: ref={} our={} {}", i, ref_byte, our_byte, marker);
}
}