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