use super::StreamDecoder;
use crate::{DecodeError, Frame, Table};
fn rzcobs_decode(data: &[u8]) -> Result<Vec<u8>, DecodeError> {
let mut res = vec![];
let mut data = data.iter().rev().cloned();
while let Some(x) = data.next() {
match x {
0 => return Err(DecodeError::Malformed),
0x01..=0x7f => {
for i in 0..7 {
if x & (1 << (6 - i)) == 0 {
res.push(data.next().ok_or(DecodeError::Malformed)?);
} else {
res.push(0);
}
}
}
0x80..=0xfe => {
let n = (x & 0x7f) + 7;
res.push(0);
for _ in 0..n {
res.push(data.next().ok_or(DecodeError::Malformed)?);
}
}
0xff => {
for _ in 0..134 {
res.push(data.next().ok_or(DecodeError::Malformed)?);
}
}
}
}
res.reverse();
Ok(res)
}
pub struct Rzcobs<'a> {
table: &'a Table,
raw: Vec<u8>,
}
impl<'a> Rzcobs<'a> {
pub fn new(table: &'a Table) -> Self {
Self {
table,
raw: Vec::new(),
}
}
}
impl StreamDecoder for Rzcobs<'_> {
fn received(&mut self, mut data: &[u8]) {
if self.raw.is_empty() {
while data.first() == Some(&0) {
data = &data[1..]
}
}
self.raw.extend_from_slice(data);
}
fn decode(&mut self) -> Result<Frame<'_>, DecodeError> {
let zero = self
.raw
.iter()
.position(|&x| x == 0)
.ok_or(DecodeError::UnexpectedEof)?;
let frame = rzcobs_decode(&self.raw[..zero]);
if let Some(nonzero) = self.raw[zero..].iter().position(|&x| x != 0) {
self.raw.drain(0..zero + nonzero);
} else {
self.raw.clear();
}
assert!(self.raw.is_empty() || self.raw[0] != 0);
let frame: Vec<u8> = frame?;
match self.table.decode(&frame) {
Ok((frame, _consumed)) => Ok(frame),
Err(DecodeError::UnexpectedEof) => Err(DecodeError::Malformed),
Err(DecodeError::Malformed) => Err(DecodeError::Malformed),
}
}
}