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