85 lines
2.2 KiB
Rust
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
|
|
}
|
|
}
|
|
}
|
|
}
|