use byteorder::{ReadBytesExt, BigEndian};
#[derive(Debug, Clone, Copy)]
pub enum Condition {
Never,
Always,
Eq,
Ne,
Gt,
}
#[derive(Debug, Clone, Copy)]
pub enum Format { BoundedCounter, UnboundedCounter, ASCIIList, BinaryList }
#[derive(Debug)]
pub struct Parameter {
pub code: u16,
pub update_disabled: bool,
pub target_save: bool,
pub threshold_comparison: Condition,
pub format: Format,
pub value: Vec<u8>,
}
#[derive(Debug)]
pub struct Page {
pub page: u8,
pub subpage: Option<u8>,
pub saved: bool,
pub data: Vec<u8>,
}
impl Page {
pub fn parse_params(&self) -> Option<Vec<Parameter>> {
let mut params = vec![];
let mut current_param: usize = 0;
let len = self.data.len();
while current_param < len {
if current_param + 4 > len {
return None; }
let code = (&self.data[current_param .. current_param + 2]).read_u16::<BigEndian>().unwrap();
let control = self.data[current_param + 2];
let plen = self.data[current_param + 3] as usize;
current_param += 4;
if current_param + plen > len {
return None; }
params.push(Parameter {
code: code,
update_disabled: control & 0b1000_0000 != 0,
target_save: control & 0b10_0000 != 0,
threshold_comparison: {
use self::Condition::*;
match (control & 0b1_0000 != 0, (control & 0b1100) >> 2) {
(false, _) => Never,
(true, 0b00) => Always,
(true, 0b01) => Eq,
(true, 0b10) => Ne,
(true, 0b11) => Gt,
_ => unreachable!(),
}
},
format: match control & 0b11 {
0b00 => Format::BoundedCounter,
0b01 => Format::ASCIIList,
0b10 => Format::UnboundedCounter,
0b11 => Format::BinaryList,
_ => unreachable!(),
},
value: self.data[current_param .. current_param+plen].to_vec(),
});
current_param += plen;
}
Some(params)
}
}
pub fn parse(data: &[u8]) -> Option<Page> {
if data.len() < 4 {
return None;
}
let len = ((&data[2..4]).read_u16::<BigEndian>().unwrap() + 4) as usize;
if data.len() < len {
return None;
}
Some(Page {
saved: data[0] & 0b1000_0000 == 0,
page: data[0] & 0b11_1111,
subpage: match (data[0] & 0b100_0000 != 0, data[1]) {
(false, 0) => None,
(false, _) => { return None },
(true, sp) => Some(sp),
},
data: data[4 .. len].to_vec(),
})
}