1 use crate::util::managed_vec::CapacityError;
2 use crate::util::managed_vec::ManagedVec;
3 #[cfg(feature = "trace-pkt")]
4 use alloc::string::String;
5 use managed::ManagedSlice;
6 
7 enum State {
8     Ready,
9     Body,
10     Checksum1,
11     Checksum2,
12 }
13 
14 /// Receives a packet incrementally using a asynchronous state machine.
15 pub struct RecvPacketStateMachine {
16     state: State,
17     idx: usize,
18 }
19 
20 impl RecvPacketStateMachine {
new() -> Self21     pub fn new() -> Self {
22         RecvPacketStateMachine {
23             state: State::Ready,
24             idx: 0,
25         }
26     }
27 
pump<'b>( &mut self, packet_buffer: &'b mut ManagedSlice<'_, u8>, byte: u8, ) -> Result<Option<&'b mut [u8]>, CapacityError<u8>>28     pub fn pump<'b>(
29         &mut self,
30         packet_buffer: &'b mut ManagedSlice<'_, u8>,
31         byte: u8,
32     ) -> Result<Option<&'b mut [u8]>, CapacityError<u8>> {
33         let mut buf = ManagedVec::new_with_idx(packet_buffer, self.idx);
34         buf.push(byte)?;
35         self.idx += 1;
36 
37         match self.state {
38             State::Ready => {
39                 if byte == b'$' {
40                     self.state = State::Body;
41                 } else {
42                     self.idx = 0;
43                 }
44             }
45             State::Body => {
46                 if byte == b'#' {
47                     self.state = State::Checksum1;
48                 }
49             }
50             State::Checksum1 => self.state = State::Checksum2,
51             State::Checksum2 => {
52                 self.state = State::Ready;
53                 self.idx = 0;
54             }
55         }
56 
57         if matches!(self.state, State::Ready) {
58             #[cfg(feature = "trace-pkt")]
59             trace!("<-- {}", String::from_utf8_lossy(buf.as_slice()));
60 
61             Ok(Some(packet_buffer))
62         } else {
63             Ok(None)
64         }
65     }
66 }
67