#![cfg_attr(docsrs, doc(cfg(feature = "delta")))]
use crate::error::Error;
use crate::traits::{Algorithm, RawDecoder, RawEncoder, RawProgress};
pub const MIN_DISTANCE: usize = 1;
pub const MAX_DISTANCE: usize = 256;
#[derive(Debug, Clone, Copy, Default)]
pub struct Delta;
#[derive(Debug, Clone, Copy)]
pub struct EncoderConfig {
pub dist: usize,
}
impl Default for EncoderConfig {
fn default() -> Self {
Self { dist: 1 }
}
}
#[derive(Debug, Clone, Copy)]
pub struct DecoderConfig {
pub dist: usize,
}
impl Default for DecoderConfig {
fn default() -> Self {
Self { dist: 1 }
}
}
impl Algorithm for Delta {
const NAME: &'static str = "delta";
type Encoder = Encoder;
type Decoder = Decoder;
type EncoderConfig = EncoderConfig;
type DecoderConfig = DecoderConfig;
fn encoder_with(cfg: EncoderConfig) -> Encoder {
Encoder::new(cfg.dist)
}
fn decoder_with(cfg: DecoderConfig) -> Decoder {
Decoder::new(cfg.dist)
}
}
#[derive(Debug, Clone)]
struct History {
buf: [u8; MAX_DISTANCE],
dist: usize,
pos: usize,
valid: bool,
}
impl History {
const fn new(dist: usize) -> Self {
Self {
buf: [0u8; MAX_DISTANCE],
dist,
pos: 0,
valid: false,
}
}
fn check(&mut self) -> Result<(), Error> {
if self.valid {
return Ok(());
}
if (MIN_DISTANCE..=MAX_DISTANCE).contains(&self.dist) {
self.valid = true;
Ok(())
} else {
Err(Error::Unsupported)
}
}
fn reset(&mut self) {
self.buf = [0u8; MAX_DISTANCE];
self.pos = 0;
}
}
#[derive(Debug, Clone)]
pub struct Encoder {
hist: History,
}
impl Encoder {
pub const fn new(dist: usize) -> Self {
Self {
hist: History::new(dist),
}
}
}
impl RawEncoder for Encoder {
fn raw_encode(&mut self, input: &[u8], output: &mut [u8]) -> Result<RawProgress, Error> {
self.hist.check()?;
let n = input.len().min(output.len());
let h = &mut self.hist;
for i in 0..n {
let orig = input[i];
let prev = h.buf[h.pos];
output[i] = orig.wrapping_sub(prev);
h.buf[h.pos] = orig;
h.pos += 1;
if h.pos == h.dist {
h.pos = 0;
}
}
Ok(RawProgress {
consumed: n,
written: n,
done: false,
})
}
fn raw_finish(&mut self, _output: &mut [u8]) -> Result<RawProgress, Error> {
self.hist.check()?;
Ok(RawProgress {
consumed: 0,
written: 0,
done: true,
})
}
fn raw_reset(&mut self) {
self.hist.reset();
}
}
#[derive(Debug, Clone)]
pub struct Decoder {
hist: History,
}
impl Decoder {
pub const fn new(dist: usize) -> Self {
Self {
hist: History::new(dist),
}
}
}
impl RawDecoder for Decoder {
fn raw_decode(&mut self, input: &[u8], output: &mut [u8]) -> Result<RawProgress, Error> {
self.hist.check()?;
let n = input.len().min(output.len());
let h = &mut self.hist;
for i in 0..n {
let prev = h.buf[h.pos];
let orig = input[i].wrapping_add(prev);
output[i] = orig;
h.buf[h.pos] = orig;
h.pos += 1;
if h.pos == h.dist {
h.pos = 0;
}
}
Ok(RawProgress {
consumed: n,
written: n,
done: false,
})
}
fn raw_finish(&mut self, _output: &mut [u8]) -> Result<RawProgress, Error> {
self.hist.check()?;
Ok(RawProgress {
consumed: 0,
written: 0,
done: true,
})
}
fn raw_reset(&mut self) {
self.hist.reset();
}
}