use super::{
flat_magsgn_capacity, unstuff_magsgn, FlatBitReader, ForwardBitReader, MelDecoder,
ReverseBitReader,
};
#[test]
fn reader_state_and_bit_consumption_match_pre_split_goldens() {
let data = [0xAA, 0xFF, 0x01, 0x7F, 0x80];
let mut forward = ForwardBitReader::<0xFF>::new(&data);
assert_eq!(u64::from(forward.fetch()), 0x3F81_FFAA);
forward.advance(5);
assert_eq!(u64::from(forward.fetch()), 0x01FC_0FFD);
forward.advance(19);
assert_eq!(u64::from(forward.fetch()), 0xFFFF_C03F);
assert_eq!(
(forward.pos, forward.bits, forward.tmp, forward.unstuff),
(5, 37, 0x0000_001F_FFFF_C03F, true)
);
let mut reverse = ReverseBitReader::new_mrp(&data);
assert_eq!(u64::from(reverse.fetch()), 0xFF01_7F80);
assert_eq!(reverse.advance(7), 0x55FE_02FF);
assert_eq!(u64::from(reverse.fetch()), 0x55FE_02FF);
assert_eq!(
(
reverse.pos,
reverse.remaining,
reverse.bits,
reverse.tmp,
reverse.unstuff,
),
(-1, 0, 33, 0x0000_0001_55FE_02FF, true)
);
let mel_cases: [(&[u8], usize, [i32; 24]); 4] = [
(
&[0x12, 0x34, 0x56, 0x78],
2,
[
1, 0, 1, 0, 0, 0, 2, 2, 2, 6, 6, 6, 14, 14, 30, 62, 62, 62, 62, 62, 62, 62, 62, 62,
],
),
(
&[0xFF, 0x80, 0xFF, 0xFF, 0x3C, 0x00, 0x00],
7,
[
0, 0, 0, 2, 2, 2, 6, 6, 1, 1, 7, 2, 6, 6, 6, 14, 14, 30, 62, 62, 62, 62, 62, 62,
],
),
(&[0x00; 6], 6, [1; 24]),
(
&[0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0xA5],
6,
[
0, 0, 0, 2, 2, 2, 6, 6, 6, 14, 14, 30, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
62,
],
),
];
for (mel_data, scup, expected) in mel_cases {
let mut mel = MelDecoder::new(mel_data, mel_data.len(), scup);
let runs = expected.map(|_| mel.get_run().expect("MEL run"));
assert_eq!(runs, expected, "MEL data {mel_data:02X?}");
}
let vlc_data = [0x12, 0x34, 0x56, 0x78, 0x9A];
let mut vlc = ReverseBitReader::new_vlc(&vlc_data, vlc_data.len(), 3);
assert_eq!(vlc.fetch(), 0x0000_02B7);
assert_eq!(vlc.advance(9), 0x0000_0001);
assert_eq!(vlc.fetch(), 0x0000_0001);
assert_eq!(
(vlc.pos, vlc.remaining, vlc.bits, vlc.tmp, vlc.unstuff),
(1, 0, 34, 1, false)
);
}
#[test]
fn word_refills_yield_the_same_bits_as_byte_refills() {
let mut seed = 0x1234_5678_u32;
let mut next = move || {
seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;
seed
};
let special = [0xFF_u8, 0x7F, 0x8F, 0x90, 0x00, 0xFE];
for len in 0..=40_usize {
for _ in 0..20 {
let data = (0..len)
.map(|_| {
let draw = next();
if draw % 3 == 0 {
special[(draw >> 8) as usize % special.len()]
} else {
(draw >> 16).to_le_bytes()[0]
}
})
.collect::<Vec<_>>();
let advances = (0..24).map(|_| next() % 33).collect::<Vec<_>>();
let mut forward = ForwardBitReader::<0xFF>::new(&data);
let mut forward_bytes = forward.clone();
let mut reverse = ReverseBitReader::new_mrp(&data);
let mut reverse_bytes = reverse.clone();
for &count in &advances {
if forward_bytes.bits < 32 {
forward_bytes = forward_bytes.fill_bytes();
}
assert_eq!(
u64::from(forward.fetch()),
forward_bytes.tmp & u64::from(u32::MAX),
"forward len {len}"
);
forward.advance(count);
forward_bytes.advance(count);
if reverse_bytes.bits < 32 {
reverse_bytes = reverse_bytes.fill_bytes();
}
assert_eq!(
u64::from(reverse.fetch()),
reverse_bytes.tmp & u64::from(u32::MAX),
"reverse len {len}"
);
reverse.advance(count);
reverse_bytes.advance(count);
}
}
}
}
#[test]
fn flat_magsgn_reader_matches_reservoir_reader() {
let mut state = 0x2545_F491_4F6C_DD1D_u64;
let mut next = move || {
state ^= state << 13;
state ^= state >> 7;
state ^= state << 17;
state
};
for len in 0..300_usize {
for density in [0_u64, 4, 32, 200] {
let data = (0..len)
.map(|_| {
let draw = next();
if draw % 256 < density {
0xFF
} else {
draw.to_le_bytes()[3]
}
})
.collect::<Vec<_>>();
let advances = (0..(len / 2 + 24))
.map(|_| (next() % 33) as u32)
.collect::<Vec<_>>();
let samples = advances.len();
let mut buffer = Vec::with_capacity(flat_magsgn_capacity(samples).expect("capacity"));
let flat = unstuff_magsgn(&data, &mut buffer, samples * 4).expect("unstuffed");
let mut flat = FlatBitReader::new(flat).expect("flat reader");
let mut reservoir = ForwardBitReader::<0xFF>::new(&data);
for (step, &count) in advances.iter().enumerate() {
assert_eq!(
flat.fetch(),
reservoir.fetch(),
"len {len} density {density} step {step}"
);
flat.advance(count);
reservoir.advance(count);
}
}
}
}
#[test]
fn flat_magsgn_unstuffing_requires_reserved_capacity() {
let mut buffer = Vec::new();
assert!(unstuff_magsgn(&[1, 2, 3], &mut buffer, 4).is_none());
assert_eq!(buffer.capacity(), 0, "unstuffing must not allocate");
let capacity = flat_magsgn_capacity(1).expect("one-sample capacity");
let mut buffer = Vec::with_capacity(capacity);
let reserved = buffer.capacity();
let flat = unstuff_magsgn(&[0; 8], &mut buffer, 4).expect("long segment");
assert_eq!(&flat[..4], &[0; 4]);
assert!(
flat.len() <= capacity,
"segment padding must fit its reservation"
);
assert_eq!(
buffer.capacity(),
reserved,
"long segments must not allocate"
);
}