use std::io;
use bytes::BytesMut;
#[derive(Debug, Clone)]
pub enum Mode {
Uncompressed,
Compressed,
}
impl Mode {
#[tracing::instrument]
pub fn encode_length(&self, len: usize) -> io::Result<u8> {
if len < self.valid_raw_buffer_min_len() {
panic!("Failed to encode any data. Possible programming error.");
}
let n = match self {
Mode::Uncompressed => len,
Mode::Compressed => {
if let Some(0) = len.checked_rem(4) {
len / 4
} else {
panic!(
"Packet length is not divisible by 4!
This is probably a programming error."
);
}
},
};
if n > self.max_length() {
panic!(
"Provided length would overflow the maximum byte size of {}.
This is probably a programming error, or a change in the
packet definition.",
self.max_length()
);
}
Ok(n as u8)
}
#[tracing::instrument]
pub fn decode_length(&self, src: &BytesMut) -> io::Result<Option<usize>> {
if src.len() < self.valid_raw_buffer_min_len() {
return Ok(None);
}
let n = match src.first() {
Some(n) => match self {
Mode::Uncompressed => *n as usize,
Mode::Compressed => (*n as usize) * 4,
},
None => return Ok(None),
};
if n > self.max_length() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"frame exceeds max_bytes",
));
}
if src.len() < n {
return Ok(None);
}
Ok(Some(n))
}
fn valid_raw_buffer_min_len(&self) -> usize {
4
}
pub const fn max_length(&self) -> usize {
match self {
Mode::Uncompressed => 255,
Mode::Compressed => 1020,
}
}
}