pub fn rle_encode_channel(input: &[u8]) -> Vec<u8> {
let n = input.len();
let mut out = Vec::with_capacity(n + n / 128 + 16);
let mut i = 0;
while i < n {
let mut run = 1;
while run < 130 && i + run < n && input[i + run] == input[i] {
run += 1;
}
if run >= 3 {
out.push(u8::try_from(run + 125).expect("run length is at most 130"));
out.push(input[i]);
i += run;
} else {
let mut lit_end = i + 1;
while lit_end - i < 128 && lit_end < n {
if lit_end + 2 < n
&& input[lit_end] == input[lit_end + 1]
&& input[lit_end + 1] == input[lit_end + 2]
{
break;
}
lit_end += 1;
}
let lit = lit_end - i;
out.push(u8::try_from(lit - 1).expect("literal run is at most 128"));
out.extend_from_slice(&input[i..lit_end]);
i = lit_end;
}
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn literal_run() {
assert_eq!(rle_encode_channel(&[1, 2, 3, 4]), vec![3, 1, 2, 3, 4]);
}
#[test]
fn repeat_run() {
assert_eq!(rle_encode_channel(&[7, 7, 7, 7, 7]), vec![130, 7]);
}
#[test]
fn empty() {
assert_eq!(rle_encode_channel(&[]), Vec::<u8>::new());
}
}