#[cfg(feature = "encoder")]
use alloc::vec::Vec;
use crate::Read;
#[cfg(feature = "encoder")]
use crate::Write;
const MAX_DISTANCE: usize = 256;
const _MIN_DISTANCE: usize = 1;
const DIS_MASK: usize = MAX_DISTANCE - 1;
struct Delta {
distance: usize,
history: [u8; MAX_DISTANCE],
pos: u8,
}
impl Delta {
fn new(distance: usize) -> Self {
Self {
distance,
history: [0; MAX_DISTANCE],
pos: 0,
}
}
fn decode(&mut self, buf: &mut [u8]) {
for item in buf {
let pos = self.pos as usize;
let h = self.history[(self.distance.wrapping_add(pos)) & DIS_MASK];
*item = item.wrapping_add(h);
self.history[pos & DIS_MASK] = *item;
self.pos = self.pos.wrapping_sub(1);
}
}
#[cfg(feature = "encoder")]
fn encode(&mut self, buf: &mut [u8]) {
for item in buf {
let pos = self.pos as usize;
let h = self.history[(self.distance.wrapping_add(pos)) & DIS_MASK];
let original = *item;
*item = item.wrapping_sub(h);
self.history[pos & DIS_MASK] = original;
self.pos = self.pos.wrapping_sub(1);
}
}
}
pub struct DeltaReader<R> {
inner: R,
delta: Delta,
}
impl<R> DeltaReader<R> {
pub fn new(inner: R, distance: usize) -> Self {
Self {
inner,
delta: Delta::new(distance),
}
}
pub fn into_inner(self) -> R {
self.inner
}
pub fn inner(&self) -> &R {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut R {
&mut self.inner
}
}
impl<R: Read> Read for DeltaReader<R> {
fn read(&mut self, buf: &mut [u8]) -> crate::Result<usize> {
let n = self.inner.read(buf)?;
if n == 0 {
return Ok(n);
}
self.delta.decode(&mut buf[..n]);
Ok(n)
}
}
#[cfg(feature = "encoder")]
pub struct DeltaWriter<W> {
inner: W,
delta: Delta,
buffer: Vec<u8>,
}
#[cfg(feature = "encoder")]
impl<W> DeltaWriter<W> {
pub fn new(inner: W, distance: usize) -> Self {
Self {
inner,
delta: Delta::new(distance),
buffer: Vec::with_capacity(4096),
}
}
pub fn into_inner(self) -> W {
self.inner
}
pub fn inner(&self) -> &W {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut W {
&mut self.inner
}
}
#[cfg(feature = "encoder")]
impl<W: Write> Write for DeltaWriter<W> {
fn write(&mut self, buf: &[u8]) -> crate::Result<usize> {
let data_size = buf.len();
if data_size > self.buffer.len() {
self.buffer.resize(data_size, 0);
}
self.buffer[..data_size].copy_from_slice(buf);
self.delta.encode(&mut self.buffer[..data_size]);
self.inner.write(&self.buffer[..data_size])
}
fn flush(&mut self) -> crate::Result<()> {
self.inner.flush()
}
}
#[cfg(all(feature = "encoder", feature = "std"))]
#[cfg(test)]
mod tests {
use std::io::Cursor;
use super::*;
#[test]
fn test_delta_roundtrip() {
let test_cases = [
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
vec![1, 2, 3, 1, 2, 3, 1, 2, 3],
vec![42, 13, 255, 0, 128, 64, 32, 99, 200, 150],
vec![100; 20],
vec![0, 255, 0, 255, 0, 255, 0, 255],
(0..300).map(|i| (i % 256) as u8).collect(),
];
let distances = vec![1, 2, 4, 8, 16, 32, 64, 128, 256];
for distance in distances {
for (i, original_data) in test_cases.iter().enumerate() {
let mut encoded_buffer = Vec::new();
let mut writer = DeltaWriter::new(Cursor::new(&mut encoded_buffer), distance);
std::io::copy(&mut original_data.as_slice(), &mut writer)
.expect("Failed to encode data");
let mut decoded_data = Vec::new();
let mut reader = DeltaReader::new(Cursor::new(&encoded_buffer), distance);
std::io::copy(&mut reader, &mut decoded_data).expect("Failed to decode data");
assert_eq!(
original_data, &decoded_data,
"Roundtrip failed for distance {distance} with data set {i}",
);
}
}
}
}