use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompressionType {
None,
Delta,
RunLength,
DeltaRunLength,
DeltaDelta,
}
pub fn compress_delta(values: &[u64]) -> Vec<u8> {
let mut result = Vec::with_capacity(values.len() * 8);
let mut last = 0;
for &value in values {
let delta = value - last;
result.extend_from_slice(&delta.to_le_bytes());
last = value;
}
result
}
pub fn decompress_delta(compressed: &[u8], count: usize) -> Vec<u64> {
let mut result = Vec::with_capacity(count);
let mut last = 0;
for i in 0..count {
let start = i * 8;
let delta = unsafe {
let ptr = compressed.as_ptr().add(start) as *const [u8; 8];
u64::from_le_bytes(*ptr)
};
let value = last + delta;
result.push(value);
last = value;
}
result
}
pub fn compress_delta_float(values: &[f64]) -> Vec<u8> {
let mut result = Vec::with_capacity(values.len() * 8);
let mut last = 0.0;
for &value in values {
let delta = value - last;
result.extend_from_slice(&delta.to_le_bytes());
last = value;
}
result
}
pub fn decompress_delta_float(compressed: &[u8], count: usize) -> Vec<f64> {
let mut result = Vec::with_capacity(count);
let mut last = 0.0;
for i in 0..count {
let start = i * 8;
let delta = unsafe {
let ptr = compressed.as_ptr().add(start) as *const [u8; 8];
f64::from_le_bytes(*ptr)
};
let value = last + delta;
result.push(value);
last = value;
}
result
}
pub fn compress_delta_delta(values: &[u64]) -> Vec<u8> {
let mut result = Vec::with_capacity(values.len() * 8);
if values.is_empty() {
return result;
}
result.extend_from_slice(&values[0].to_le_bytes());
if values.len() == 1 {
return result;
}
let delta1_0 = values[1] - values[0];
result.extend_from_slice(&delta1_0.to_le_bytes());
if values.len() == 2 {
return result;
}
let mut last_delta1 = delta1_0;
for i in 2..values.len() {
let delta1 = values[i] - values[i - 1];
let delta2 = delta1 - last_delta1;
result.extend_from_slice(&delta2.to_le_bytes());
last_delta1 = delta1;
}
result
}
pub fn decompress_delta_delta(compressed: &[u8], count: usize) -> Vec<u64> {
let mut result = Vec::with_capacity(count);
if count == 0 || compressed.len() < 8 {
return result;
}
let first = unsafe {
let ptr = compressed.as_ptr() as *const [u8; 8];
u64::from_le_bytes(*ptr)
};
result.push(first);
if count == 1 {
return result;
}
if compressed.len() < 16 {
return result;
}
let delta1_0 = unsafe {
let ptr = compressed.as_ptr().add(8) as *const [u8; 8];
u64::from_le_bytes(*ptr)
};
let second = first + delta1_0;
result.push(second);
if count == 2 {
return result;
}
let mut current_delta1 = delta1_0;
let mut last_value = second;
for i in 2..count {
let offset = 16 + (i - 2) * 8;
if offset + 8 > compressed.len() {
break;
}
let delta2 = unsafe {
let ptr = compressed.as_ptr().add(offset) as *const [u8; 8];
u64::from_le_bytes(*ptr)
};
let current_delta1_new = current_delta1 + delta2;
let current_value = last_value + current_delta1_new;
result.push(current_value);
last_value = current_value;
current_delta1 = current_delta1_new;
}
result
}
pub fn compress_delta_delta_float(values: &[f64]) -> Vec<u8> {
let mut result = Vec::with_capacity(values.len() * 8);
if values.is_empty() {
return result;
}
result.extend_from_slice(&values[0].to_le_bytes());
if values.len() == 1 {
return result;
}
let delta1_0 = values[1] - values[0];
result.extend_from_slice(&delta1_0.to_le_bytes());
if values.len() == 2 {
return result;
}
let mut last_delta1 = delta1_0;
for i in 2..values.len() {
let delta1 = values[i] - values[i - 1];
let delta2 = delta1 - last_delta1;
result.extend_from_slice(&delta2.to_le_bytes());
last_delta1 = delta1;
}
result
}
pub fn decompress_delta_delta_float(compressed: &[u8], count: usize) -> Vec<f64> {
let mut result = Vec::with_capacity(count);
if count == 0 || compressed.len() < 8 {
return result;
}
let first = unsafe {
let ptr = compressed.as_ptr() as *const [u8; 8];
f64::from_le_bytes(*ptr)
};
result.push(first);
if count == 1 {
return result;
}
if compressed.len() < 16 {
return result;
}
let delta1_0 = unsafe {
let ptr = compressed.as_ptr().add(8) as *const [u8; 8];
f64::from_le_bytes(*ptr)
};
let second = first + delta1_0;
result.push(second);
if count == 2 {
return result;
}
let mut current_delta1 = delta1_0;
let mut last_value = second;
for i in 2..count {
let offset = 16 + (i - 2) * 8;
if offset + 8 > compressed.len() {
break;
}
let delta2 = unsafe {
let ptr = compressed.as_ptr().add(offset) as *const [u8; 8];
f64::from_le_bytes(*ptr)
};
let current_delta1_new = current_delta1 + delta2;
let current_value = last_value + current_delta1_new;
result.push(current_value);
last_value = current_value;
current_delta1 = current_delta1_new;
}
result
}
pub fn compress_run_length(values: &[u64]) -> Vec<u8> {
let mut result = Vec::new();
if values.is_empty() {
return result;
}
let mut current = values[0];
let mut count = 1;
for &value in &values[1..] {
if value == current && count < u16::MAX as u32 {
count += 1;
} else {
result.extend_from_slice(¤t.to_le_bytes());
result.extend_from_slice(&count.to_le_bytes());
current = value;
count = 1;
}
}
result.extend_from_slice(¤t.to_le_bytes());
result.extend_from_slice(&count.to_le_bytes());
result
}
pub fn decompress_run_length(compressed: &[u8]) -> Vec<u64> {
let mut result = Vec::new();
let mut index = 0;
while index + 12 <= compressed.len() {
let value = unsafe {
let ptr = compressed.as_ptr().add(index) as *const [u8; 8];
u64::from_le_bytes(*ptr)
};
let count = unsafe {
let ptr = compressed.as_ptr().add(index + 8) as *const [u8; 4];
u32::from_le_bytes(*ptr)
};
for _ in 0..count {
result.push(value);
}
index += 12;
}
result
}