#![cfg_attr(docsrs, doc(cfg(feature = "packbits")))]
use alloc::vec::Vec;
use crate::error::Error;
use crate::traits::{Algorithm, RawDecoder, RawEncoder, RawProgress};
#[derive(Debug, Clone, Copy, Default)]
pub struct PackBits;
impl Algorithm for PackBits {
const NAME: &'static str = "packbits";
type Encoder = Encoder;
type Decoder = Decoder;
type EncoderConfig = ();
type DecoderConfig = ();
fn encoder_with(_: ()) -> Encoder {
Encoder::new()
}
fn decoder_with(_: ()) -> Decoder {
Decoder::new()
}
}
const MAX_LITERAL: usize = 128;
const MAX_RUN: usize = 128;
const MIN_RUN: usize = 3;
#[derive(Debug, Default)]
pub struct Encoder {
literal: Vec<u8>,
run: Option<(u8, usize)>,
pending: Vec<u8>,
head: usize,
finished: bool,
}
impl Encoder {
pub const fn new() -> Self {
Self {
literal: Vec::new(),
run: None,
pending: Vec::new(),
head: 0,
finished: false,
}
}
fn drain_pending(&mut self, out: &mut [u8]) -> usize {
let avail = self.pending.len() - self.head;
let n = avail.min(out.len());
out[..n].copy_from_slice(&self.pending[self.head..self.head + n]);
self.head += n;
if self.head == self.pending.len() {
self.pending.clear();
self.head = 0;
}
n
}
fn flush_literal(&mut self) {
if self.literal.is_empty() {
return;
}
debug_assert!(self.literal.len() <= MAX_LITERAL);
self.pending.push((self.literal.len() - 1) as u8);
self.pending.extend_from_slice(&self.literal);
self.literal.clear();
}
fn flush_run(&mut self) {
if let Some((byte, count)) = self.run.take() {
debug_assert!((MIN_RUN..=MAX_RUN).contains(&count));
let hdr = -((count as i32) - 1) as i8 as u8;
self.pending.push(hdr);
self.pending.push(byte);
}
}
fn feed(&mut self, b: u8) {
match self.run {
Some((byte, count)) if byte == b && count < MAX_RUN => {
self.run = Some((byte, count + 1));
}
Some((byte, count)) => {
if byte == b {
self.flush_literal();
self.flush_run();
self.run = Some((b, 1));
} else if count >= MIN_RUN {
self.flush_literal();
self.flush_run();
self.run = Some((b, 1));
} else {
self.run = None;
for _ in 0..count {
self.push_literal(byte);
}
self.run = Some((b, 1));
}
}
None => {
self.run = Some((b, 1));
}
}
}
fn push_literal(&mut self, b: u8) {
self.literal.push(b);
if self.literal.len() == MAX_LITERAL {
self.flush_literal();
}
}
fn finalize(&mut self) {
if let Some((byte, count)) = self.run.take() {
if count >= MIN_RUN {
self.flush_literal();
self.run = Some((byte, count));
self.flush_run();
} else {
for _ in 0..count {
self.push_literal(byte);
}
self.flush_literal();
}
} else {
self.flush_literal();
}
}
}
impl RawEncoder for Encoder {
fn raw_encode(&mut self, input: &[u8], output: &mut [u8]) -> Result<RawProgress, Error> {
let mut consumed = 0usize;
let mut written = 0usize;
if self.head < self.pending.len() {
written += self.drain_pending(&mut output[written..]);
}
while consumed < input.len() {
if self.pending.len().saturating_sub(self.head) >= output.len().saturating_sub(written)
{
if written < output.len() {
written += self.drain_pending(&mut output[written..]);
}
if self.head < self.pending.len() {
break;
}
}
self.feed(input[consumed]);
consumed += 1;
if self.head < self.pending.len() && written < output.len() {
written += self.drain_pending(&mut output[written..]);
}
}
if self.head < self.pending.len() && written < output.len() {
written += self.drain_pending(&mut output[written..]);
}
Ok(RawProgress {
consumed,
written,
done: false,
})
}
fn raw_finish(&mut self, output: &mut [u8]) -> Result<RawProgress, Error> {
if self.finished && self.head >= self.pending.len() {
return Ok(RawProgress {
consumed: 0,
written: 0,
done: true,
});
}
if !self.finished {
self.finalize();
self.finished = true;
}
let mut written = 0usize;
if self.head < self.pending.len() {
written += self.drain_pending(&mut output[written..]);
}
let done = self.head >= self.pending.len();
Ok(RawProgress {
consumed: 0,
written,
done,
})
}
fn raw_reset(&mut self) {
self.literal.clear();
self.run = None;
self.pending.clear();
self.head = 0;
self.finished = false;
}
}
#[derive(Debug, Clone, Copy)]
enum DecState {
Header,
Literal { remaining: u8 },
NeedRunByte { count: u8 },
Run { byte: u8, remaining: u8 },
}
#[derive(Debug, Clone, Copy)]
pub struct Decoder {
state: DecState,
}
impl Decoder {
pub const fn new() -> Self {
Self {
state: DecState::Header,
}
}
}
impl Default for Decoder {
fn default() -> Self {
Self::new()
}
}
impl RawDecoder for Decoder {
fn raw_decode(&mut self, input: &[u8], output: &mut [u8]) -> Result<RawProgress, Error> {
let mut consumed = 0usize;
let mut written = 0usize;
loop {
match self.state {
DecState::Header => {
if consumed == input.len() {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
let n = input[consumed] as i8;
consumed += 1;
if n >= 0 {
self.state = DecState::Literal {
remaining: (n as u8) + 1,
};
} else if n == -128 {
} else {
self.state = DecState::NeedRunByte {
count: ((-(n as i16)) as u8) + 1,
};
}
}
DecState::Literal { remaining } => {
if remaining == 0 {
self.state = DecState::Header;
continue;
}
if consumed == input.len() || written == output.len() {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
let in_avail = input.len() - consumed;
let out_avail = output.len() - written;
let n = (remaining as usize).min(in_avail).min(out_avail);
output[written..written + n].copy_from_slice(&input[consumed..consumed + n]);
consumed += n;
written += n;
let new_remaining = remaining - n as u8;
self.state = if new_remaining == 0 {
DecState::Header
} else {
DecState::Literal {
remaining: new_remaining,
}
};
}
DecState::NeedRunByte { count } => {
if consumed == input.len() {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
let byte = input[consumed];
consumed += 1;
self.state = DecState::Run {
byte,
remaining: count,
};
}
DecState::Run { byte, remaining } => {
if remaining == 0 {
self.state = DecState::Header;
continue;
}
if written == output.len() {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
let out_avail = output.len() - written;
let n = (remaining as usize).min(out_avail);
for slot in &mut output[written..written + n] {
*slot = byte;
}
written += n;
let new_remaining = remaining - n as u8;
self.state = if new_remaining == 0 {
DecState::Header
} else {
DecState::Run {
byte,
remaining: new_remaining,
}
};
}
}
}
}
fn raw_finish(&mut self, output: &mut [u8]) -> Result<RawProgress, Error> {
let mut written = 0usize;
if let DecState::Run { byte, remaining } = self.state {
let out_avail = output.len() - written;
let n = (remaining as usize).min(out_avail);
for slot in &mut output[written..written + n] {
*slot = byte;
}
written += n;
let new_remaining = remaining - n as u8;
self.state = if new_remaining == 0 {
DecState::Header
} else {
DecState::Run {
byte,
remaining: new_remaining,
}
};
}
match self.state {
DecState::Header => Ok(RawProgress {
consumed: 0,
written,
done: true,
}),
DecState::Run { .. } => Ok(RawProgress {
consumed: 0,
written,
done: false,
}),
DecState::Literal { .. } | DecState::NeedRunByte { .. } => Err(Error::UnexpectedEnd),
}
}
fn raw_reset(&mut self) {
self.state = DecState::Header;
}
}