deframe/
lib.rs

1//! # deframe
2//! A data deframer for embedded and no_std applications
3
4#![no_std]
5#![deny(warnings)]
6#![allow(dead_code)]
7
8pub struct Deframer<const N: usize> {
9    remainder: [u8; N],
10    remainder_length: usize,
11}
12
13#[derive(Clone, Copy, PartialEq, Debug)]
14pub enum DeframeError {
15    Overflow,
16}
17
18impl<const N: usize> Deframer<N> {
19    pub fn new() -> Self {
20        Self {
21            remainder: [0; N],
22            remainder_length: 0,
23        }
24    }
25
26    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> {
27        // check if the last read had some dangling/remainding bytes after the last linebreak
28        let with_remainder = self.remainder_length != 0;
29
30        if !with_remainder {
31            let frame_end_result =  get_frame_end(&mut data_frame.iter());
32            let frame_end_pos = if frame_end_result.is_some() { 
33                frame_end_result.unwrap() + 1
34            } else {
35                // If no frame end is found, then all the data is reserve data
36                0
37            };
38        
39            self.remainder_length = data_frame.len() - frame_end_pos;
40            self.remainder[0..self.remainder_length]
41                .copy_from_slice(&data_frame[frame_end_pos..data_frame.len()]);
42
43            let mut data: [u8; N] = [0; N];
44            if frame_end_pos > N {
45                return Err(DeframeError::Overflow);
46            }
47            data[0..frame_end_pos].copy_from_slice(&data_frame[0..frame_end_pos]);
48            return Ok((data, frame_end_pos));
49        }
50
51        // Keep finding the next valid position until our data is within the buffer size
52        let mut iter = data_frame.iter();
53        let mut last_valid_pos: usize = N;
54        while last_valid_pos + self.remainder_length > N {
55            let frame_end_result = get_frame_end(&mut iter);
56            if frame_end_result.is_some() {
57                last_valid_pos = frame_end_result.unwrap() + 1;
58            } else {
59                last_valid_pos = 0;
60                break;
61            }
62        }
63
64        // No frame break was found, in this case all the current data must be pushed to the
65        // remainder (for the next deframe call) and no data returned to the user
66        if last_valid_pos == 0 {
67            if data_frame.len() + self.remainder_length > N {
68                return Err(DeframeError::Overflow);
69            }
70            self.remainder[self.remainder_length..data_frame.len() + self.remainder_length].copy_from_slice(&data_frame[0..data_frame.len()]);
71            self.remainder_length = data_frame.len() + self.remainder_length;
72            return Ok(([0; N], 0));
73        }
74
75        // If there is remainding line data from the previous reader, prepend it
76        let mut appended: [u8; N] = [0; N];
77        appended[0..self.remainder_length]
78            .copy_from_slice(&self.remainder[0..self.remainder_length]);
79
80        let end_pos = self.remainder_length + last_valid_pos;
81
82        if end_pos > N {
83            return Err(DeframeError::Overflow);
84        }
85
86        // [remainder...trimmed_data]
87        appended[self.remainder_length..end_pos].copy_from_slice(&data_frame[0..last_valid_pos]);
88
89        self.remainder_length = data_frame.len() - last_valid_pos;
90        
91        if self.remainder_length > N {
92            return Err(DeframeError::Overflow);
93        }
94        self.remainder[0..self.remainder_length].copy_from_slice(&data_frame[last_valid_pos..data_frame.len()]);
95       
96        // This data should be valid for the CSV parser
97        return Ok((appended, end_pos));
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use core::slice::Iter;
104
105    use crate::{DeframeError, Deframer};
106
107    /// The frame end, which is an ASCII linebreak for these tests
108    const FRAME_END: u8 = 0x0A;
109    /// For these tests, we simply denote a frame by an ASCII line-break (similar to CSV)
110    const GET_FRAME_END: fn(iter: &mut Iter<u8>) -> Option<usize> = |iter| iter.rposition(|&x| x == FRAME_END);
111
112    #[test]
113    fn finds_the_correct_frame_end() {
114        let mut deframer = Deframer::<4>::new();
115        let (result, len) = deframer.deframe(&[FRAME_END, 0x01, 0x02, 0x03], GET_FRAME_END).unwrap();
116        assert_eq!(result[0..len], [FRAME_END]);
117
118        let mut deframer = Deframer::<4>::new();
119        let (result, len) = deframer.deframe(&[0x01, FRAME_END, 0x02, 0x03], GET_FRAME_END).unwrap();
120        assert_eq!(len, 2);
121        assert_eq!(result[0..len], [0x01, FRAME_END]);
122
123        let mut deframer = Deframer::<4>::new();
124        let (result, len) = deframer.deframe(&[0x01, 0x02, 0x03, FRAME_END], GET_FRAME_END).unwrap();
125        assert_eq!(len, 4);
126        assert_eq!(result[0..len], [0x01, 0x02, 0x03, FRAME_END]);
127    }
128
129    #[test]
130    fn has_the_correct_remainder() {
131        let mut deframer = Deframer::<16>::new();
132        let (result, len) = deframer.deframe(&[FRAME_END, 0x01, 0x02, 0x03], GET_FRAME_END).unwrap();
133        assert_eq!(result[0..len], [FRAME_END]);
134        assert_eq!(deframer.remainder_length, 3);
135
136        let (result, len) = deframer.deframe(&[0x04, 0x05, FRAME_END, 0x06], GET_FRAME_END).unwrap();
137        assert_eq!(deframer.remainder_length, 1);
138        assert_eq!(deframer.remainder[0..deframer.remainder_length], [0x06]);
139        assert_eq!(result[0..len], [0x01, 0x02, 0x03, 0x04, 0x05, FRAME_END]);
140
141        let (result, len) = deframer.deframe(&[0x07, 0x08, 0x09, 0x10, FRAME_END, 0x11, 0x22], GET_FRAME_END).unwrap();
142        assert_eq!(deframer.remainder_length, 2);
143        assert_eq!(deframer.remainder[0..deframer.remainder_length], [0x11, 0x22]);
144        assert_eq!(result[0..len], [0x06, 0x07, 0x08, 0x09, 0x10, FRAME_END]);
145    }
146
147    #[test]
148    fn correctly_overflows() {
149        let mut deframer = Deframer::<2>::new();
150        
151        // Overflows because the data_frame provider is too large for the allocated buffer
152        let result = deframer.deframe(&[0x01, 0x02, 0x03, FRAME_END], GET_FRAME_END);
153        assert_eq!(result.is_err(), true);
154
155        let mut deframer = Deframer::<2>::new();
156        
157        let result = deframer.deframe(&[0x01], GET_FRAME_END);
158        assert_eq!(result.is_err(), false);
159        assert_eq!(deframer.remainder_length, 1);
160        
161        let result = deframer.deframe(&[0x02], GET_FRAME_END);
162        assert_eq!(result.is_err(), false);
163        assert_eq!(deframer.remainder_length, 2);
164        
165        let result = deframer.deframe(&[0x03], GET_FRAME_END);
166        assert_eq!(result.is_err(), true);
167        assert_eq!(result.err().unwrap(), DeframeError::Overflow);
168    }
169
170    #[test]
171    fn remainder_increases() {
172        let mut deframer = Deframer::<4>::new();
173      
174        let (_data, len) = deframer.deframe(&[0x01], GET_FRAME_END).unwrap();
175        assert_eq!(deframer.remainder_length, 1);
176        assert_eq!(len, 0);
177      
178        let (_data, len) = deframer.deframe(&[0x02], GET_FRAME_END).unwrap();
179        assert_eq!(deframer.remainder_length, 2);
180        assert_eq!(len, 0);
181      
182        let (_data, len) = deframer.deframe(&[0x03], GET_FRAME_END).unwrap();
183        assert_eq!(deframer.remainder_length, 3);
184        assert_eq!(len, 0);
185      
186        let (data, len) = deframer.deframe(&[FRAME_END], GET_FRAME_END).unwrap();
187        assert_eq!(deframer.remainder_length, 0);
188        assert_eq!(len, 4);
189        assert_eq!(data, [0x01, 0x02, 0x03, FRAME_END]);
190    }
191}