blob: 9f3b567ae93f586da28a7d7385061e5eff33b873 [file] [log] [blame]
#[cfg(feature = "trace-pkt")]
use alloc::string::String;
use managed::ManagedSlice;
use crate::util::managed_vec::{CapacityError, ManagedVec};
enum State {
Ready,
Body,
Checksum1,
Checksum2,
}
/// Receives a packet incrementally using a asynchronous state machine.
pub struct RecvPacketStateMachine {
state: State,
idx: usize,
}
impl RecvPacketStateMachine {
pub fn new() -> Self {
RecvPacketStateMachine {
state: State::Ready,
idx: 0,
}
}
pub fn pump<'b>(
&mut self,
packet_buffer: &'b mut ManagedSlice<'_, u8>,
byte: u8,
) -> Result<Option<&'b mut [u8]>, CapacityError<u8>> {
let mut buf = ManagedVec::new_with_idx(packet_buffer, self.idx);
buf.push(byte)?;
self.idx += 1;
match self.state {
State::Ready => {
if byte == b'$' {
self.state = State::Body;
} else {
self.idx = 0;
}
}
State::Body => {
if byte == b'#' {
self.state = State::Checksum1;
}
}
State::Checksum1 => self.state = State::Checksum2,
State::Checksum2 => {
self.state = State::Ready;
self.idx = 0;
}
}
if matches!(self.state, State::Ready) {
#[cfg(feature = "trace-pkt")]
trace!("<-- {}", String::from_utf8_lossy(buf.as_slice()));
Ok(Some(packet_buffer))
} else {
Ok(None)
}
}
}