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