#![no_std]
#![deny(warnings)]
#![allow(dead_code)]
pub struct Deframer<const N: usize> {
remainder: [u8; N],
remainder_length: usize,
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum DeframeError {
Overflow,
}
impl<const N: usize> Deframer<N> {
pub fn new() -> Self {
Self {
remainder: [0; N],
remainder_length: 0,
}
}
pub fn deframe(&mut self, data_frame: &[u8], get_frame_end: fn(iter: &mut core::slice::Iter<u8>) -> Option<usize>) -> Result<([u8; N], usize), DeframeError> {
let with_remainder = self.remainder_length != 0;
if !with_remainder {
let frame_end_result = get_frame_end(&mut data_frame.iter());
let frame_end_pos = if frame_end_result.is_some() {
frame_end_result.unwrap() + 1
} else {
0
};
self.remainder_length = data_frame.len() - frame_end_pos;
self.remainder[0..self.remainder_length]
.copy_from_slice(&data_frame[frame_end_pos..data_frame.len()]);
let mut data: [u8; N] = [0; N];
if frame_end_pos > N {
return Err(DeframeError::Overflow);
}
data[0..frame_end_pos].copy_from_slice(&data_frame[0..frame_end_pos]);
return Ok((data, frame_end_pos));
}
let mut iter = data_frame.iter();
let mut last_valid_pos: usize = N;
while last_valid_pos + self.remainder_length > N {
let frame_end_result = get_frame_end(&mut iter);
if frame_end_result.is_some() {
last_valid_pos = frame_end_result.unwrap() + 1;
} else {
last_valid_pos = 0;
break;
}
}
if last_valid_pos == 0 {
if data_frame.len() + self.remainder_length > N {
return Err(DeframeError::Overflow);
}
self.remainder[self.remainder_length..data_frame.len() + self.remainder_length].copy_from_slice(&data_frame[0..data_frame.len()]);
self.remainder_length = data_frame.len() + self.remainder_length;
return Ok(([0; N], 0));
}
let mut appended: [u8; N] = [0; N];
appended[0..self.remainder_length]
.copy_from_slice(&self.remainder[0..self.remainder_length]);
let end_pos = self.remainder_length + last_valid_pos;
if end_pos > N {
return Err(DeframeError::Overflow);
}
appended[self.remainder_length..end_pos].copy_from_slice(&data_frame[0..last_valid_pos]);
self.remainder_length = data_frame.len() - last_valid_pos;
if self.remainder_length > N {
return Err(DeframeError::Overflow);
}
self.remainder[0..self.remainder_length].copy_from_slice(&data_frame[last_valid_pos..data_frame.len()]);
return Ok((appended, end_pos));
}
}
#[cfg(test)]
mod tests {
use core::slice::Iter;
use crate::{DeframeError, Deframer};
const FRAME_END: u8 = 0x0A;
const GET_FRAME_END: fn(iter: &mut Iter<u8>) -> Option<usize> = |iter| iter.rposition(|&x| x == FRAME_END);
#[test]
fn finds_the_correct_frame_end() {
let mut deframer = Deframer::<4>::new();
let (result, len) = deframer.deframe(&[FRAME_END, 0x01, 0x02, 0x03], GET_FRAME_END).unwrap();
assert_eq!(result[0..len], [FRAME_END]);
let mut deframer = Deframer::<4>::new();
let (result, len) = deframer.deframe(&[0x01, FRAME_END, 0x02, 0x03], GET_FRAME_END).unwrap();
assert_eq!(len, 2);
assert_eq!(result[0..len], [0x01, FRAME_END]);
let mut deframer = Deframer::<4>::new();
let (result, len) = deframer.deframe(&[0x01, 0x02, 0x03, FRAME_END], GET_FRAME_END).unwrap();
assert_eq!(len, 4);
assert_eq!(result[0..len], [0x01, 0x02, 0x03, FRAME_END]);
}
#[test]
fn has_the_correct_remainder() {
let mut deframer = Deframer::<16>::new();
let (result, len) = deframer.deframe(&[FRAME_END, 0x01, 0x02, 0x03], GET_FRAME_END).unwrap();
assert_eq!(result[0..len], [FRAME_END]);
assert_eq!(deframer.remainder_length, 3);
let (result, len) = deframer.deframe(&[0x04, 0x05, FRAME_END, 0x06], GET_FRAME_END).unwrap();
assert_eq!(deframer.remainder_length, 1);
assert_eq!(deframer.remainder[0..deframer.remainder_length], [0x06]);
assert_eq!(result[0..len], [0x01, 0x02, 0x03, 0x04, 0x05, FRAME_END]);
let (result, len) = deframer.deframe(&[0x07, 0x08, 0x09, 0x10, FRAME_END, 0x11, 0x22], GET_FRAME_END).unwrap();
assert_eq!(deframer.remainder_length, 2);
assert_eq!(deframer.remainder[0..deframer.remainder_length], [0x11, 0x22]);
assert_eq!(result[0..len], [0x06, 0x07, 0x08, 0x09, 0x10, FRAME_END]);
}
#[test]
fn correctly_overflows() {
let mut deframer = Deframer::<2>::new();
let result = deframer.deframe(&[0x01, 0x02, 0x03, FRAME_END], GET_FRAME_END);
assert_eq!(result.is_err(), true);
let mut deframer = Deframer::<2>::new();
let result = deframer.deframe(&[0x01], GET_FRAME_END);
assert_eq!(result.is_err(), false);
assert_eq!(deframer.remainder_length, 1);
let result = deframer.deframe(&[0x02], GET_FRAME_END);
assert_eq!(result.is_err(), false);
assert_eq!(deframer.remainder_length, 2);
let result = deframer.deframe(&[0x03], GET_FRAME_END);
assert_eq!(result.is_err(), true);
assert_eq!(result.err().unwrap(), DeframeError::Overflow);
}
#[test]
fn remainder_increases() {
let mut deframer = Deframer::<4>::new();
let (_data, len) = deframer.deframe(&[0x01], GET_FRAME_END).unwrap();
assert_eq!(deframer.remainder_length, 1);
assert_eq!(len, 0);
let (_data, len) = deframer.deframe(&[0x02], GET_FRAME_END).unwrap();
assert_eq!(deframer.remainder_length, 2);
assert_eq!(len, 0);
let (_data, len) = deframer.deframe(&[0x03], GET_FRAME_END).unwrap();
assert_eq!(deframer.remainder_length, 3);
assert_eq!(len, 0);
let (data, len) = deframer.deframe(&[FRAME_END], GET_FRAME_END).unwrap();
assert_eq!(deframer.remainder_length, 0);
assert_eq!(len, 4);
assert_eq!(data, [0x01, 0x02, 0x03, FRAME_END]);
}
}