const RLE_MARKER: u8 = 0xFE;
const MIN_RUN_LENGTH: usize = 3;
pub fn encode(data: &[u8]) -> Vec<u8> {
if data.is_empty() {
return Vec::new();
}
let mut result = Vec::with_capacity(data.len());
let mut i = 0;
while i < data.len() {
let current = data[i];
let mut run_len = 1;
while i + run_len < data.len()
&& data[i + run_len] == current
&& run_len < 255
{
run_len += 1;
}
if run_len >= MIN_RUN_LENGTH || current == RLE_MARKER {
result.push(RLE_MARKER);
result.push(run_len as u8);
result.push(current);
} else {
for j in 0..run_len {
result.push(data[i + j]);
}
}
i += run_len;
}
result
}
pub fn decode(data: &[u8]) -> Vec<u8> {
if data.is_empty() {
return Vec::new();
}
let mut result = Vec::new();
let mut i = 0;
while i < data.len() {
if data[i] == RLE_MARKER {
if i + 2 >= data.len() {
result.extend_from_slice(&data[i..]);
break;
}
let count = data[i + 1] as usize;
let value = data[i + 2];
for _ in 0..count {
result.push(value);
}
i += 3;
} else {
result.push(data[i]);
i += 1;
}
}
result
}
pub fn suitability_score(data: &[u8]) -> f64 {
if data.len() < MIN_RUN_LENGTH {
return 0.0;
}
let mut total_run_bytes = 0usize;
let mut i = 0;
while i < data.len() {
let current = data[i];
let mut run_len = 1;
while i + run_len < data.len() && data[i + run_len] == current {
run_len += 1;
}
if run_len >= MIN_RUN_LENGTH {
total_run_bytes += run_len;
}
i += run_len;
}
total_run_bytes as f64 / data.len() as f64
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_roundtrip() {
let original = vec![
0u8, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 255, 255, 255, 255, 255,
];
let encoded = encode(&original);
let decoded = decode(&encoded);
assert_eq!(original, decoded);
}
#[test]
fn test_no_run_data() {
let original = vec![1u8, 2, 3, 4, 5, 6, 7, 8];
let encoded = encode(&original);
let decoded = decode(&encoded);
assert_eq!(original, decoded);
}
#[test]
fn test_marker_byte_in_data() {
let original = vec![RLE_MARKER, RLE_MARKER, RLE_MARKER, 1u8, 2, 3];
let encoded = encode(&original);
let decoded = decode(&encoded);
assert_eq!(original, decoded);
}
#[test]
fn test_all_same_bytes() {
let original = vec![0xAAu8; 200];
let encoded = encode(&original);
println!(
"200 same bytes: {} → {} bytes (ratio: {:.2}x)",
original.len(),
encoded.len(),
original.len() as f64 / encoded.len() as f64
);
let decoded = decode(&encoded);
assert_eq!(original, decoded);
assert!(encoded.len() < 10, "Çok tekrarlı veri küçülmeli");
}
#[test]
fn test_suitability_score() {
let high_run = vec![0u8; 100]; let low_run: Vec<u8> = (0u8..100).collect(); assert!(suitability_score(&high_run) > 0.9);
assert!(suitability_score(&low_run) < 0.1);
}
}