use crate::alloc::vec::Vec;
const RLE_ESCAPE: u8 = 0xFF;
pub fn rle_encode(data: &[u8]) -> Vec<u8> {
let mut out = Vec::with_capacity(data.len());
let mut i = 0;
while i < data.len() {
let b = data[i];
let mut run_len = 1;
while i + run_len < data.len() && data[i + run_len] == b && run_len < 258 {
run_len += 1;
}
if run_len >= 4 {
out.push(RLE_ESCAPE);
out.push((run_len - 3) as u8);
out.push(b);
i += run_len;
} else {
for _ in 0..run_len {
if b == RLE_ESCAPE {
out.push(RLE_ESCAPE);
out.push(0x00); } else {
out.push(b);
}
}
i += run_len;
}
}
out
}
pub fn rle_decode(data: &[u8]) -> Vec<u8> {
#[cfg(feature = "std")]
{
if data.len() > 20000 && data.len() < 30000 {
let _ = std::fs::write("rle_input.bin", data);
std::println!("[RLE] Dumped {} bytes to rle_input.bin", data.len());
}
}
let mut out = Vec::with_capacity(data.len());
let mut i = 0;
while i < data.len() {
if data[i] == RLE_ESCAPE {
if i + 1 >= data.len() {
out.push(RLE_ESCAPE);
i += 1;
continue;
}
let code = data[i + 1];
if code == 0x00 {
out.push(RLE_ESCAPE);
i += 2;
} else {
if i + 2 >= data.len() {
out.push(RLE_ESCAPE);
out.push(code);
i += 2;
continue;
}
let run_len = (code as usize) + 3;
let byte = data[i + 2];
for _ in 0..run_len {
out.push(byte);
}
i += 3;
}
} else {
out.push(data[i]);
i += 1;
}
}
out
}