frame_picker/
lib.rs

1// We're not using the standard library
2#![no_std]
3
4/// Frame metadata module
5pub mod frame_meta;
6/// Iap2 frame metadata module
7pub mod iap2_frame_meta;
8use core::marker::PhantomData;
9
10use frame_meta::FrameMeta;
11
12/// An error type indicating that there are no frames available
13#[derive(Debug, PartialEq, Eq, Clone, Copy)]
14pub struct Empty;
15
16/// An error type indicating that the storage is full
17#[derive(Debug, PartialEq, Eq, Clone, Copy)]
18pub struct Full;
19
20/// A struct for storing and handling network frame data
21#[derive(Debug)]
22pub struct FramePicker<const N: usize, M: FrameMeta> {
23    storage: [u8; N],
24    read_at: usize,
25    /// The number of bytes dropped
26    pub dropped : usize,
27    _marker : PhantomData<M>,
28}
29
30impl<const N: usize, M: FrameMeta> FramePicker<N, M> {
31    /// Creates a new FramePicker
32    pub fn new() -> Self {
33        Self {
34            storage: [0; N],
35            read_at: 0,
36            dropped: 0,
37            _marker: PhantomData,
38        }
39    }
40
41    /// Feeds data into the FramePicker
42    /// Returns a Full error if the storage is full
43    pub fn feed_data(&mut self, data: &[u8]) -> Result<usize, Full> {
44        if self.read_at + data.len() > N {
45            return Err(Full);
46        }
47
48        let len = data.len();
49        self.storage[self.read_at..self.read_at + len].copy_from_slice(&data[..len]);
50        self.read_at += len;
51        self.align_buffer_with_header();
52        Ok(len)
53    }
54
55    /// Aligns the buffer with the header
56    fn align_buffer_with_header(&mut self) {
57        let mut search_at: usize = 0;
58        loop {
59            if self.read_at - search_at < M::frame_header_len() {
60                break;
61            }
62            if M::frame_match(&self.storage[search_at..self.read_at]) {
63                break;
64            } else {
65                search_at += 1;
66            }
67        }
68        if search_at > 0 {
69            self.dropped += search_at;
70            self.storage.copy_within(search_at..self.read_at, 0);
71            self.read_at -= search_at;
72        }
73    }
74
75    /// Checks if the FramePicker contains a frame
76    pub fn contain_frame(&self) -> bool {
77        if self.read_at < M::frame_header_len() {
78            return false;
79        }
80        M::frame_match(self.storage[..self.read_at].as_ref())
81    }
82
83    /// Checks if the frame is complete
84    pub fn frame_complete(&self) -> bool {
85        if self.read_at < M::frame_header_len() {
86            return false;
87        }
88        let total_len = M::frame_totol_len(self.storage[..self.read_at].as_ref());
89        total_len > 0 && total_len <= self.read_at
90    }
91
92    /// Acquires a frame
93    pub fn acquire_frame(&mut self) -> Result<&[u8], Empty> {
94        if self.frame_complete() {
95            let total_len = M::frame_totol_len(self.storage[..self.read_at].as_ref());
96            let data = &self.storage[..total_len];
97            Ok(data)
98        } else {
99            Err(Empty)
100        }
101    }
102
103    /// Releases a frame
104    pub fn release_frame(&mut self) -> Result<(), Empty> {
105        if self.frame_complete() {
106            let total_len = M::frame_totol_len(self.storage[..self.read_at].as_ref());
107            self.storage.copy_within(total_len..self.read_at, 0);
108            self.read_at -= total_len;
109            self.align_buffer_with_header();
110            Ok(())
111        } else {
112            Err(Empty)
113        }
114    }
115
116    /// Dequeues a frame with a function
117    pub fn dequeue_frame_with<F,R>(&mut self, f: F) -> Result<R, Empty>
118    where
119        F: FnOnce(&[u8]) -> R,
120    {
121        if let Ok(frame) = self.acquire_frame() {
122            let result = f(frame);
123            self.release_frame().unwrap();
124            Ok(result)
125        } else {
126            Err(Empty)
127        }
128    }
129}
130#[cfg(test)]
131mod tests {
132    use super::*;
133
134    fn picker() -> FramePicker::<500,iap2_frame_meta::Iap2FrameMeta> {
135        FramePicker::<500,iap2_frame_meta::Iap2FrameMeta>::new()
136    }
137
138    #[test]
139    fn test_feed_handshake() {
140        let mut picker = picker();
141        let shake = [0xff, 0x55, 0x02, 0x00, 0xee, 0x10];
142        assert_eq!(picker.feed_data(&shake[..]), Ok(6));
143        assert_eq!(picker.dropped, 0);
144        assert_eq!(picker.read_at, 6);
145        assert!(picker.contain_frame());
146        assert_eq!(picker.frame_complete(), true);
147
148        assert_eq!(picker.acquire_frame(), Ok(&shake[..]));
149        assert_eq!(picker.release_frame(), Ok(()));
150    }
151
152    #[test]
153    fn test_feed_normal_data() {
154        let mut picker = picker();
155        let normal_data = [0xff, 0x5a, 0x00, 0x0a, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a];
156        assert_eq!(picker.feed_data(&normal_data[..]), Ok(10));
157        assert_eq!(picker.dropped, 0);
158        assert_eq!(picker.read_at, 10);
159        assert!(picker.contain_frame());
160        assert_eq!(picker.frame_complete(), true);
161
162        assert_eq!(picker.acquire_frame(), Ok(&normal_data[..]));
163        assert_eq!(picker.release_frame(), Ok(()));
164    }
165
166    #[test]
167    fn test_feed_data_exceed_storage() {
168        let mut picker = FramePicker::<10,iap2_frame_meta::Iap2FrameMeta>::new();
169        let normal_data = [0xff, 0x5a, 0x00, 0x0b, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b];
170        assert_eq!(picker.feed_data(&normal_data[..]), Err(Full));
171        assert_eq!(picker.read_at, 0);
172        assert_eq!(picker.contain_frame(), false);
173        assert_eq!(picker.frame_complete(), false);
174    }
175
176    #[test]
177    fn test_feed_data_with_dropped() {
178        let mut picker = picker();
179        let normal_data = [0x00, 0x00, 0xff, 0x5a, 0x00, 0x0a, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a];
180        assert_eq!(picker.feed_data(&normal_data[..]), Ok(12));
181        assert_eq!(picker.dropped, 2);
182        assert_eq!(picker.read_at, 10);
183        assert_eq!(picker.contain_frame(), true);
184        assert_eq!(picker.frame_complete(), true);
185
186        assert_eq!(picker.feed_data(&normal_data[..]), Ok(12));
187        assert_eq!(picker.dropped, 2);
188        assert_eq!(picker.read_at, 10+12);
189        assert_eq!(picker.release_frame(), Ok(()));
190        assert_eq!(picker.release_frame(), Ok(()));
191    }
192
193    #[test]
194    fn test_short_frame() {
195        let mut picker = picker();
196        let normal_data = [0xff, 0x5a, 0x00, 0x0a, 0x05, 0x06, 0x07, 0x08, 0x09];
197        assert_eq!(picker.feed_data(&normal_data[..]), Ok(9));
198        assert_eq!(picker.dropped, 0);
199        assert_eq!(picker.read_at, 9);
200        assert!(picker.contain_frame());
201        assert_eq!(picker.frame_complete(), false);
202
203        assert_eq!(picker.feed_data(&[0x0a, 0xff, 0x5a]), Ok(3));
204        assert_eq!(picker.frame_complete(), true);
205        assert_eq!(picker.release_frame(), Ok(()));
206
207        assert_eq!(picker.feed_data(&[0x00, 0x0a, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a]), Ok(8));
208        assert_eq!(picker.frame_complete(), true);
209    }
210
211    #[test]
212    fn test_header_not_complete() {
213        let mut picker = picker();
214        let data1 = [0x32,0x34,0x42,0x33,0x52,0x42, 0x32, 0x31, 0x93,0x32,0xff];
215        let data2 = [0x5a,0x00,0x0a,0x05,0x06,0x07,0x08,0x09,0x0a];
216        assert_eq!(picker.feed_data(&data1[..]), Ok(11));
217        assert_eq!(picker.dropped, 6);
218        assert_eq!(picker.contain_frame(), false);
219
220        assert_eq!(picker.feed_data(&data2[..]), Ok(9));
221        assert_eq!(picker.dropped, 10);
222        assert_eq!(picker.contain_frame(), true);
223
224    }
225
226}