#[cfg(test)]
mod chandata_test;
use super::channum::*;
use shared::error::{Error, Result};
const PADDING: usize = 4;
fn nearest_padded_value_length(l: usize) -> usize {
let mut n = PADDING * (l / PADDING);
if n < l {
n += PADDING;
}
n
}
const CHANNEL_DATA_LENGTH_SIZE: usize = 2;
const CHANNEL_DATA_NUMBER_SIZE: usize = CHANNEL_DATA_LENGTH_SIZE;
const CHANNEL_DATA_HEADER_SIZE: usize = CHANNEL_DATA_LENGTH_SIZE + CHANNEL_DATA_NUMBER_SIZE;
#[derive(Default, Debug)]
pub struct ChannelData {
pub data: Vec<u8>, pub number: ChannelNumber,
pub raw: Vec<u8>,
}
impl PartialEq for ChannelData {
fn eq(&self, other: &Self) -> bool {
self.data == other.data && self.number == other.number
}
}
impl ChannelData {
#[inline]
pub fn reset(&mut self) {
self.raw.clear();
self.data.clear();
}
pub fn encode(&mut self) {
self.raw.clear();
self.write_header();
self.raw.extend_from_slice(&self.data);
let padded = nearest_padded_value_length(self.raw.len());
let bytes_to_add = padded - self.raw.len();
if bytes_to_add > 0 {
self.raw.extend_from_slice(&vec![0; bytes_to_add]);
}
}
pub fn decode(&mut self) -> Result<()> {
let buf = &self.raw;
if buf.len() < CHANNEL_DATA_HEADER_SIZE {
return Err(Error::ErrUnexpectedEof);
}
let num = u16::from_be_bytes([buf[0], buf[1]]);
self.number = ChannelNumber(num);
if !self.number.valid() {
return Err(Error::ErrInvalidChannelNumber);
}
let l = u16::from_be_bytes([
buf[CHANNEL_DATA_NUMBER_SIZE],
buf[CHANNEL_DATA_NUMBER_SIZE + 1],
]) as usize;
if l > buf[CHANNEL_DATA_HEADER_SIZE..].len() {
return Err(Error::ErrBadChannelDataLength);
}
self.data = buf[CHANNEL_DATA_HEADER_SIZE..CHANNEL_DATA_HEADER_SIZE + l].to_vec();
Ok(())
}
pub fn write_header(&mut self) {
if self.raw.len() < CHANNEL_DATA_HEADER_SIZE {
self.raw
.resize(self.raw.len() + CHANNEL_DATA_HEADER_SIZE, 0);
}
self.raw[..CHANNEL_DATA_NUMBER_SIZE].copy_from_slice(&self.number.0.to_be_bytes());
self.raw[CHANNEL_DATA_NUMBER_SIZE..CHANNEL_DATA_HEADER_SIZE]
.copy_from_slice(&(self.data.len() as u16).to_be_bytes());
}
pub fn is_channel_data(buf: &[u8]) -> bool {
if buf.len() < CHANNEL_DATA_HEADER_SIZE {
return false;
}
if u16::from_be_bytes([
buf[CHANNEL_DATA_NUMBER_SIZE],
buf[CHANNEL_DATA_NUMBER_SIZE + 1],
]) > buf[CHANNEL_DATA_HEADER_SIZE..].len() as u16
{
return false;
}
let num = ChannelNumber(u16::from_be_bytes([buf[0], buf[1]]));
num.valid()
}
}