pub type RlePair = (usize, u8);
pub fn encode(data: &[u8]) -> Vec<RlePair> {
if data.is_empty() {
return Vec::new();
}
let mut pairs = Vec::new();
let mut current = data[0];
let mut count = 1;
for &byte in &data[1..] {
if byte == current {
count += 1;
} else {
pairs.push((count, current));
current = byte;
count = 1;
}
}
pairs.push((count, current));
pairs
}
pub fn decode(pairs: &[RlePair]) -> Vec<u8> {
let total: usize = pairs.iter().map(|(c, _)| *c).sum();
let mut out = Vec::with_capacity(total);
for &(count, byte) in pairs {
for _ in 0..count {
out.push(byte);
}
}
out
}
pub fn encode_compact(data: &[u8]) -> Vec<u8> {
let pairs = encode(data);
let mut out = Vec::with_capacity(pairs.len() * 2);
for (mut count, byte) in pairs {
while count > 0 {
let chunk = count.min(255);
out.push(chunk as u8);
out.push(byte);
count -= chunk;
}
}
out
}
pub fn decode_compact(data: &[u8]) -> Option<Vec<u8>> {
if !data.len().is_multiple_of(2) {
return None;
}
let mut out = Vec::new();
let mut i = 0;
while i < data.len() {
let count = data[i] as usize;
let byte = data[i + 1];
for _ in 0..count {
out.push(byte);
}
i += 2;
}
Some(out)
}
pub fn compression_ratio(data: &[u8]) -> (usize, usize) {
let pairs = encode(data);
(pairs.len() * 2, data.len())
}
pub fn run_count(data: &[u8]) -> usize {
if data.is_empty() {
return 0;
}
let mut count = 1;
for i in 1..data.len() {
if data[i] != data[i - 1] {
count += 1;
}
}
count
}