#![cfg(feature = "bcj2")]
use compcol::bcj2;
fn lcg(seed: &mut u64) -> u8 {
*seed = seed
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
(*seed >> 33) as u8
}
fn rand_bytes(n: usize, mut seed: u64) -> Vec<u8> {
(0..n).map(|_| lcg(&mut seed)).collect()
}
fn roundtrip(input: &[u8]) {
let (main, call, jump, rc) = bcj2::encode(input);
let got = bcj2::decode(&main, &call, &jump, &rc, input.len()).expect("decode ok");
assert_eq!(got, input, "BCJ2 round-trip mismatch (len={})", input.len());
}
#[test]
fn random_payloads() {
for (n, seed) in [
(0usize, 1u64),
(1, 2),
(7, 3),
(256, 4),
(4096, 5),
(65537, 6),
] {
roundtrip(&rand_bytes(n, seed));
}
}
#[test]
fn synthetic_x86_with_branches() {
let mut v = Vec::new();
let mut s = 99u64;
for k in 0..400u32 {
for _ in 0..(lcg(&mut s) % 5) {
v.push(lcg(&mut s));
}
match k % 3 {
0 => {
v.push(0xE8);
v.extend_from_slice(&k.wrapping_mul(13).to_le_bytes());
}
1 => {
v.push(0xE9);
v.extend_from_slice(&(0xDEAD_0000u32 ^ k).to_le_bytes());
}
_ => {
v.push(0x0F);
v.push(0x80 | (lcg(&mut s) & 0x0F));
v.extend_from_slice(&k.to_le_bytes());
}
}
}
v.extend_from_slice(&[0u8; 8]);
roundtrip(&v);
}
#[test]
fn errors_on_truncation() {
let (main, call, jump, rc) = bcj2::encode(b"hello world payload");
assert!(bcj2::decode(&main, &call, &jump, &rc, 10_000).is_err());
assert!(bcj2::decode(&main, &call, &jump, &[0u8; 2], 5).is_err());
}