use super::seg::SegIdx; pub use super::seg::{DOWN_HEADER_SIZE, MAX_TOTAL_PACKET_SIZE, UP_HEADER_SIZE}; use byteorder::ByteOrder; #[derive(Clone, Debug)] pub enum UpMsg { Data { payload: Vec, seg_idx: SegIdx, // is_final_packet: bool, }, } #[derive(Clone, Debug)] pub enum DownMsg { /// `idxs` must be distinct and in increasing order. Ack { idxs: Vec }, } #[derive(Error, Debug)] #[error("deserialization failed; malformed packet")] pub struct DesError; pub trait SerDes: Sized { // For both methods: `buf.len()` must be >= `MAX_SERIALIZED_SIZE` fn des(buf: &[u8]) -> Result; fn ser_to(&self, buf: &mut [u8]) -> usize; } type BO = byteorder::LE; impl SerDes for UpMsg { fn des(buf: &[u8]) -> Result { if buf.len() < UP_HEADER_SIZE { Err(DesError) } else { Ok(UpMsg::Data { seg_idx: BO::read_u32(&buf[0..4]), payload: buf[4..].into(), }) } } fn ser_to(&self, buf: &mut [u8]) -> usize { match self { UpMsg::Data { payload, seg_idx } => { let len = payload.len(); BO::write_u32(&mut buf[0..4], *seg_idx); buf[4..4 + len].copy_from_slice(&payload[..]); 4 + len } } } } impl SerDes for DownMsg { fn des(buf: &[u8]) -> Result { let mut idxs = vec![]; for (i, b) in buf.iter().cloned().enumerate() { for j in 0..8 { if b & (1 << j) != 0 { idxs.push((i * 8 + j) as SegIdx); } } } Ok(DownMsg::Ack { idxs }) } fn ser_to(&self, buf: &mut [u8]) -> usize { match self { DownMsg::Ack { idxs } => { let mut max_i = 0; for seg_idx in idxs.iter().cloned() { let i = seg_idx as usize / 8; let j = (seg_idx % 8) as u8; buf[i] |= 1 << j; max_i = std::cmp::max(i, max_i); } max_i + 1 } } } }