1#![no_std]
2
3#[derive(Debug)]
4pub struct ModbusBuffer<const CAPACITY: usize> {
5 ring_buffer: [Option<u8>;CAPACITY],
6 head: usize,
8 tail: usize,
10 size: usize,
11 min_frame_len: usize,
13 max_frame_len: usize,
15 overwrite: bool,
17}
18impl<const CAPACITY: usize> ModbusBuffer<CAPACITY> {
19
20 #[allow(clippy::new_without_default)]
22 pub fn new() -> Self {
23
24 assert!(CAPACITY > 4);
25 ModbusBuffer {
26 ring_buffer: [None; CAPACITY],
27 head: 0,
28 tail: 0,
29 size: 0,
30 min_frame_len: 3,
31 max_frame_len: CAPACITY,
32 overwrite: true,
33 }
34 }
35
36 pub fn min_frame_len(mut self, min_frame_len: usize) -> Self {
38 self.min_frame_len = min_frame_len;
39 self
40 }
41
42 pub fn max_frame_len(mut self, max_frame_len: usize) -> Self {
44 self.max_frame_len = max_frame_len;
45 self
46 }
47
48 pub fn overwrite(mut self, overwrite: bool) -> Self {
50 self.overwrite = overwrite;
51 self
52 }
53
54 pub fn push(&mut self, item: u8) {
57 if self.size == CAPACITY {
58 if self.overwrite {
60 self.ring_buffer[self.head] = Some(item);
61 self.head = (self.head + 1) % CAPACITY;
62 self.tail = (self.tail + 1) % CAPACITY;
63 } else {
64 panic!("ModbusBuffer exceed its capacity!");
65 }
66
67 } else {
68 self.ring_buffer[self.tail] = Some(item);
70 self.tail = (self.tail + 1) % CAPACITY;
71 self.size += 1;
72 }
73 }
74
75 pub fn pop(&mut self) -> Option<u8> {
77 if self.size == 0 {
78 None
79 } else {
80 let item = self.ring_buffer[self.head];
81 self.ring_buffer[self.head] = None;
82 self.head = (self.head + 1) % CAPACITY;
83 self.size -= 1;
84 item
85 }
86 }
87
88 pub fn len(&self) -> usize {
90 self.size
91 }
92
93 pub fn is_empty(&self) -> bool {
95 self.size == 0
96 }
97
98 pub fn is_full(&self) -> bool {
100 self.size == CAPACITY
101 }
102
103 fn frame(&self, output_buffer: &mut [u8;CAPACITY]) -> Option<usize> {
105 let mut index = 0;
106
107 if self.size > 0 {
108 if self.head < self.tail {
109 self.ring_buffer[self.head..self.tail]
111 .iter()
112 .for_each(|d| {
113 output_buffer[index] = d.unwrap();
114 index += 1;
115 });
116 } else {
117 self.ring_buffer[self.head..CAPACITY]
120 .iter()
121 .for_each(|d| {
122 output_buffer[index] = d.unwrap();
123 index += 1;
124 });
125
126 self.ring_buffer[0..self.tail]
128 .iter()
129 .for_each(|d| {
130 output_buffer[index] = d.unwrap();
131 index += 1;
132 });
133 }
134 }
135 Some(self.size)
136 }
137
138 fn crc16(data: &[u8]) -> u16 {
140 let mut crc = 0xFFFF;
141 for x in data {
142 crc ^= u16::from(*x);
143 for _ in 0..8 {
144 #[allow(clippy::branches_sharing_code)]
147 if (crc & 0x0001) != 0 {
148 crc >>= 1;
149 crc ^= 0xA001;
150 } else {
151 crc >>= 1;
152 }
153 }
154 }
155 crc << 8 | crc >> 8
156 }
157
158 fn check_crc(frame: &[u8]) -> bool {
160 if frame.len() > 4 {
161 let crc = Self::crc16(&frame[..frame.len()-2]);
162 let expected_crc = [((crc & 0xff00) >> 8) as u8, (crc & 0x00ff) as u8];
163 expected_crc == frame[frame.len()-2..]
164 } else {
165 false
166 }
167
168 }
169
170 fn try_decode_buffer(&self, buffer: &[u8]) -> Option<(usize, usize)> {
172 let mut window_size = self.min_frame_len + 2;
173 if buffer.len() < window_size {
174 return None
175 }
176
177 while window_size <= buffer.len() {
178 for i in 0..=buffer.len() - window_size {
179 if Self::check_crc(&buffer[i..i + window_size]) {
181 return Some((i, i + window_size - 2));
182 }
183
184 if buffer.len() == window_size {
185 return None;
186 }
187 let j = buffer.len() - i - window_size;
189 if Self::check_crc(&buffer[j..j + window_size]) {
190 return Some((j, j + window_size - 2));
191 }
192 }
193 window_size += 1;
194 }
195 None
196 }
197
198 pub fn try_decode_frame(&mut self, buffer: &mut [u8;CAPACITY]) -> Option<usize> {
200 if self.size == 0 || self.size < self.min_frame_len {
201 return None
202 }
203
204 let mut frame = [0u8;CAPACITY];
205 let len = self.frame(&mut frame).expect("Should have a frame");
207
208 if let Some((head, tail)) = self.try_decode_buffer(&frame[..len]) {
209 let len_to_remove = tail + 2 ;
222 for _ in 0..len_to_remove {
223 self.pop();
224 }
225
226 let frame_length = tail - head;
228
229 buffer[..frame_length].copy_from_slice(&frame[head..tail]);
231
232 Some(frame_length)
234 } else {
235 None
236 }
237 }
238}
239
240
241#[cfg(test)]
242mod tests {
243 use super::*;
244
245 #[test]
246 #[should_panic]
247 fn test_overflow_should_panic() {
248 let mut buff = ModbusBuffer::<8>::new()
249 .overwrite(false);
250
251 buff.push(0x00);
252 buff.push(0x01);
253 buff.push(0x02);
254 buff.push(0x03);
255 buff.push(0x04);
256 buff.push(0x05);
257 buff.push(0x06);
258 buff.push(0x07);
259
260 buff.push(0x08);
262
263 }
264
265 #[test]
266 fn test_overflow_should_not_panic() {
267 let mut buff = ModbusBuffer::<8>::new();
268
269 buff.push(0x00);
270 buff.push(0x01);
271 buff.push(0x02);
272
273 let mut buffer = [0u8;8];
274 let len = buff.frame(&mut buffer);
275 assert_eq!(len, Some(3usize));
276 assert_eq!(buffer, [0u8, 1, 2, 0, 0, 0, 0, 0]);
277
278 buff.push(0x03);
279 buff.push(0x04);
280 buff.push(0x05);
281 buff.push(0x06);
282 buff.push(0x07);
283
284 let len = buff.frame(&mut buffer);
285 assert_eq!(len, Some(8usize));
286 assert_eq!(buffer, [0u8, 1, 2, 3, 4, 5, 6, 7]);
287
288 buff.push(0x08);
290
291 let len = buff.frame(&mut buffer);
292 assert_eq!(len, Some(8usize));
293 assert_eq!(buffer, [1u8, 2, 3, 4, 5, 6, 7, 8]);
294
295 }
296
297 #[test]
298 fn test_receive_request() {
299 let mut buff = ModbusBuffer::<10>::new();
300
301 buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); let mut output = [0u8;10];
311 let len = buff.try_decode_frame(&mut output);
312 assert_eq!(len, Some(6));
313 assert_eq!(output, [0x12u8, 0x06, 0x22, 0x22, 0xAB, 0xCD, 0, 0, 0, 0]);
314
315 }
316
317 #[test]
318 fn test_receive_multiple_request() {
319 let mut buff = ModbusBuffer::<10>::new();
320 let mut output = [0u8;10];
321
322 buff.push(0x12); buff.push(0x06); let len = buff.try_decode_frame(&mut output);
327 assert_eq!(len, None);
328
329 buff.push(0x22); buff.push(0x22); let len = buff.try_decode_frame(&mut output);
334 assert_eq!(len, None);
335
336 buff.push(0xAB); buff.push(0xCD); let len = buff.try_decode_frame(&mut output);
341 assert_eq!(len, None);
342
343 buff.push(0x9F); buff.push(0xBE); let len = buff.try_decode_frame(&mut output);
348 assert_eq!(len, Some(6));
349
350 assert_eq!(output, [0x12u8, 0x06, 0x22, 0x22, 0xAB, 0xCD, 0, 0, 0, 0]);
351
352 let len = buff.try_decode_frame(&mut output);
354 assert_eq!(len, None);
355
356 buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); let mut output = [0u8;10];
367 let len = buff.try_decode_frame(&mut output);
368 assert_eq!(len, Some(6));
369 assert_eq!(output, [0x12u8, 0x06, 0x22, 0x22, 0xAB, 0xCD, 0, 0, 0, 0]);
370
371 buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); let mut output = [0u8;10];
382 let len = buff.try_decode_frame(&mut output);
383 assert_eq!(len, Some(6));
384 assert_eq!(output, [0x12u8, 0x06, 0x22, 0x22, 0xAB, 0xCD, 0, 0, 0, 0]);
385
386 buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); let mut output = [0u8;10];
397 let len = buff.try_decode_frame(&mut output);
398 assert_eq!(len, Some(6));
399 assert_eq!(output, [0x12u8, 0x06, 0x22, 0x22, 0xAB, 0xCD, 0, 0, 0, 0]);
400
401 buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); let mut output = [0u8;10];
412 let len = buff.try_decode_frame(&mut output);
413 assert_eq!(len, Some(6));
414 assert_eq!(output, [0x12u8, 0x06, 0x22, 0x22, 0xAB, 0xCD, 0, 0, 0, 0]);
415
416 }
417
418 #[test]
419 fn test_noise_on_head() {
420 let mut buff = ModbusBuffer::<10>::new();
421
422 buff.push(0x01); assert_eq!(buff.len(), 1usize);
424 buff.push(0x02); assert_eq!(buff.len(), 2usize);
426 buff.push(0x03); assert_eq!(buff.len(), 3usize);
428 buff.push(0x01); assert_eq!(buff.len(), 4usize);
430 buff.push(0x02); assert_eq!(buff.len(), 5usize);
432 buff.push(0x03); assert_eq!(buff.len(), 6usize);
434
435 buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); assert_eq!(buff.len(), 10usize);
446
447 let mut output = [0u8;10];
448 let len = buff.try_decode_frame(&mut output);
449 assert_eq!(len, Some(6));
450 assert_eq!(output, [0x12u8, 0x06, 0x22, 0x22, 0xAB, 0xCD, 0, 0, 0, 0]);
451
452 assert_eq!(buff.len(), 0usize);
453
454 }
455
456 #[test]
457 fn test_data_remain_on_tail() {
458 let mut buff = ModbusBuffer::<20>::new();
459
460 buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); let mut output = [0u8;20];
481
482 let len = buff.try_decode_frame(&mut output);
484 assert_eq!(len, Some(6));
485 assert_eq!(buff.len(), 8usize);
486
487 let len = buff.try_decode_frame(&mut output);
489 assert_eq!(len, Some(6));
490 assert_eq!(buff.len(), 0usize);
491
492 }
493
494 #[test]
495 fn test_data_remain_on_tail_with_overlap() {
496 let mut buff = ModbusBuffer::<15>::new();
499
500 buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); buff.push(0x12); buff.push(0x06); buff.push(0x22); buff.push(0x22); buff.push(0xAB); buff.push(0xCD); buff.push(0x9F); buff.push(0xBE); let mut output = [0u8;15];
521
522 let len = buff.try_decode_frame(&mut output);
524 assert_eq!(len, Some(6));
525 assert_eq!(buff.len(), 0usize);
526 }
527
528 #[test]
529 fn buffer_empty() {
530 let mut buff = ModbusBuffer::<10>::new();
531
532 assert_eq!(buff.len(), 0);
533 let p = buff.pop();
534 assert_eq!(p, None);
535 let mut temp = [0u8;10];
536 let q = buff.try_decode_frame(&mut temp);
537 assert_eq!(q, None);
538 }
539
540}