use super::*;
use crate::bit_io::BitWriter;
use crate::blocks::literals_section::{LiteralsSection, LiteralsSectionType};
use crate::decoding::scratch::HuffmanScratch;
use crate::huff0::huff0_encoder::{HuffmanEncoder, HuffmanTable as EncTable};
use alloc::vec::Vec;
fn build_huf4x_block(data: &[u8]) -> (LiteralsSection, Vec<u8>) {
assert!(data.len() >= 4, "encode4x requires at least 4 bytes");
let table = EncTable::build_from_data(data);
let mut source: Vec<u8> = Vec::new();
{
let mut writer = BitWriter::from(&mut source);
let mut encoder = HuffmanEncoder::new(&table, &mut writer);
encoder.encode4x(data, true);
writer.flush();
}
let section = LiteralsSection {
ls_type: LiteralsSectionType::Compressed,
regenerated_size: data.len() as u32,
compressed_size: Some(source.len() as u32),
num_streams: Some(4),
};
(section, source)
}
fn roundtrip_assert(data: &[u8]) -> u8 {
let (section, source) = build_huf4x_block(data);
let mut scratch = HuffmanScratch::new();
let mut target = Vec::new();
let bytes_read = decode_literals(§ion, &mut scratch, None, &source, &mut target)
.expect("decode_literals must succeed on a well-formed roundtrip");
assert_eq!(
bytes_read as usize,
source.len(),
"decoder must consume every byte of the literals block"
);
assert_eq!(
target, data,
"decoded literals must match the encoder input"
);
scratch.table.max_num_bits
}
fn roundtrip_with_max_bits_range(data: &[u8], expected: core::ops::RangeInclusive<u8>) {
let m = roundtrip_assert(data);
assert!(
expected.contains(&m),
"max_num_bits {} outside expected range {:?} for this fixture — \
test no longer exercises the intended gate regime",
m,
expected
);
}
#[test]
fn burst_gate_lower_boundary_short_skewed_alphabet() {
let mut data: Vec<u8> = Vec::with_capacity(36);
data.extend_from_slice(&[
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22,
]);
roundtrip_with_max_bits_range(&data, 5..=11);
}
#[test]
fn burst_gate_upper_boundary_long_mid_alphabet() {
let mut data: Vec<u8> = Vec::with_capacity(4096);
for i in 0..4096u32 {
data.push((i.wrapping_mul(0x9E37_79B1) % 97) as u8);
}
roundtrip_with_max_bits_range(&data, 6..=11);
}
#[test]
fn burst_simd_fallback_refill_reentry_long_streams() {
let mut data: Vec<u8> = Vec::with_capacity(16 * 1024);
for i in 0..16 * 1024u32 {
data.push((i % 67) as u8);
}
roundtrip_with_max_bits_range(&data, 5..=8);
}
#[test]
fn burst_gate_sweep_sizes_and_alphabets() {
let sizes = [
16usize, 17, 31, 32, 33, 63, 64, 65, 127, 128, 129, 255, 256, 257, 511, 512, 513, 1023,
1024, 1025, 4096,
];
for &n in &sizes {
let mut bin: Vec<u8> = Vec::with_capacity(n);
for i in 0..n {
bin.push((i & 1) as u8);
}
roundtrip_assert(&bin);
let mut sm: Vec<u8> = Vec::with_capacity(n);
for i in 0..n {
sm.push((i % 16) as u8);
}
roundtrip_assert(&sm);
if n >= 128 {
let mut wide: Vec<u8> = Vec::with_capacity(n);
for i in 0..n {
wide.push((i.wrapping_mul(2_654_435_761) % 97) as u8);
}
roundtrip_assert(&wide);
}
}
}
#[test]
fn burst_gate_malformed_small_regen_returns_error() {
let mut data: Vec<u8> = Vec::with_capacity(256);
for i in 0..256u32 {
data.push((i % 67) as u8);
}
let (mut section, source) = build_huf4x_block(&data);
section.regenerated_size = 1;
let mut scratch = HuffmanScratch::new();
let mut target = Vec::new();
let result = decode_literals(§ion, &mut scratch, None, &source, &mut target);
assert!(
result.is_err(),
"decoder must reject the malformed header instead of panicking; \
got Ok({})",
result.unwrap_or(0)
);
}