use crate::error::{Error, Result};
pub fn decompress(
compressed: &[u8],
decompressed_size: usize,
skip_header: bool,
) -> Result<Vec<u8>> {
let data = if skip_header {
if compressed.len() < 4 {
return Err(Error::compression("RLE data too short for header"));
}
&compressed[4..]
} else {
compressed
};
let mut decompressed = vec![0u8; decompressed_size];
let mut src_pos = 0;
let mut dst_pos = 0;
while src_pos < data.len() && dst_pos < decompressed_size {
let one_byte = data[src_pos];
src_pos += 1;
if one_byte & 0x80 != 0 {
let repeat_count = ((one_byte & 0x7F) + 1) as usize;
for _ in 0..repeat_count {
if dst_pos >= decompressed_size || src_pos >= data.len() {
break;
}
decompressed[dst_pos] = data[src_pos];
dst_pos += 1;
src_pos += 1;
}
} else {
dst_pos += (one_byte + 1) as usize;
}
}
Ok(decompressed)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_rle_decompress_with_header() {
let compressed = vec![
0x08, 0x00, 0x00, 0x00, 0x82, 0x41, 0x42, 0x43, 0x01, 0x81, 0x44, 0x45, ];
let result = decompress(&compressed, 8, true).unwrap();
assert_eq!(result, vec![0x41, 0x42, 0x43, 0x00, 0x00, 0x44, 0x45, 0x00]);
}
#[test]
fn test_rle_decompress_no_header() {
let compressed = vec![
0x82, 0x41, 0x42, 0x43, 0x01, 0x81, 0x44, 0x45, ];
let result = decompress(&compressed, 8, false).unwrap();
assert_eq!(result, vec![0x41, 0x42, 0x43, 0x00, 0x00, 0x44, 0x45, 0x00]);
}
}