CS3700-project3/hptp/src/msg.rs

85 lines
2.2 KiB
Rust

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<u8>,
seg_idx: SegIdx,
// is_final_packet: bool,
},
}
#[derive(Clone, Debug)]
pub enum DownMsg {
/// `idxs` must be distinct and in increasing order.
Ack { idxs: Vec<SegIdx> },
}
#[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<Self, DesError>;
fn ser_to(&self, buf: &mut [u8]) -> usize;
}
type BO = byteorder::LE;
impl SerDes for UpMsg {
fn des(buf: &[u8]) -> Result<Self, DesError> {
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<Self, DesError> {
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
}
}
}
}