use crate::decoders::StreamDecoder;
use crate::error::{Error, Result};
pub struct RunLengthDecoder;
impl StreamDecoder for RunLengthDecoder {
fn decode(&self, input: &[u8]) -> Result<Vec<u8>> {
let mut output = Vec::new();
let mut i = 0;
while i < input.len() {
let length = input[i];
i += 1;
match length {
0..=127 => {
let count = length as usize + 1;
if i + count > input.len() {
return Err(Error::Decode(format!(
"RunLengthDecode: not enough data for literal run (need {}, have {})",
count,
input.len() - i
)));
}
output.extend_from_slice(&input[i..i + count]);
i += count;
},
128 => {
break;
},
129..=255 => {
let count = 257 - length as usize;
if i >= input.len() {
return Err(Error::Decode(
"RunLengthDecode: missing byte for run".to_string(),
));
}
let byte = input[i];
i += 1;
output.resize(output.len() + count, byte);
},
}
}
Ok(output)
}
fn name(&self) -> &str {
"RunLengthDecode"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_runlength_decode_literal() {
let decoder = RunLengthDecoder;
let input = vec![4, b'H', b'e', b'l', b'l', b'o'];
let output = decoder.decode(&input).unwrap();
assert_eq!(output, b"Hello");
}
#[test]
fn test_runlength_decode_run() {
let decoder = RunLengthDecoder;
let input = vec![252, b'A'];
let output = decoder.decode(&input).unwrap();
assert_eq!(output, b"AAAAA");
}
#[test]
fn test_runlength_decode_mixed() {
let decoder = RunLengthDecoder;
let input = vec![1, b'H', b'i', 254, b'X'];
let output = decoder.decode(&input).unwrap();
assert_eq!(output, b"HiXXX");
}
#[test]
fn test_runlength_decode_eod_marker() {
let decoder = RunLengthDecoder;
let input = vec![1, b'H', b'i', 128, 99, 99, 99];
let output = decoder.decode(&input).unwrap();
assert_eq!(output, b"Hi");
}
#[test]
fn test_runlength_decode_max_literal() {
let decoder = RunLengthDecoder;
let mut input = vec![127];
input.extend_from_slice(&[b'A'; 128]);
let output = decoder.decode(&input).unwrap();
assert_eq!(output.len(), 128);
assert_eq!(output, vec![b'A'; 128]);
}
#[test]
fn test_runlength_decode_max_run() {
let decoder = RunLengthDecoder;
let input = vec![129, b'B'];
let output = decoder.decode(&input).unwrap();
assert_eq!(output.len(), 128);
assert_eq!(output, vec![b'B'; 128]);
}
#[test]
fn test_runlength_decode_empty() {
let decoder = RunLengthDecoder;
let input = vec![];
let output = decoder.decode(&input).unwrap();
assert_eq!(output, b"");
}
#[test]
fn test_runlength_decode_insufficient_data_literal() {
let decoder = RunLengthDecoder;
let input = vec![4, b'A', b'B', b'C'];
let result = decoder.decode(&input);
assert!(result.is_err());
}
#[test]
fn test_runlength_decode_missing_run_byte() {
let decoder = RunLengthDecoder;
let input = vec![252];
let result = decoder.decode(&input);
assert!(result.is_err());
}
#[test]
fn test_runlength_decoder_name() {
let decoder = RunLengthDecoder;
assert_eq!(decoder.name(), "RunLengthDecode");
}
}