gdbstub/protocol/
recv_packet.rs

1use crate::util::managed_vec::CapacityError;
2use crate::util::managed_vec::ManagedVec;
3#[cfg(feature = "trace-pkt")]
4use alloc::string::String;
5use managed::ManagedSlice;
6
7enum State {
8    Ready,
9    Body,
10    Checksum1,
11    Checksum2,
12}
13
14/// Receives a packet incrementally using a asynchronous state machine.
15pub struct RecvPacketStateMachine {
16    state: State,
17    idx: usize,
18}
19
20impl RecvPacketStateMachine {
21    pub fn new() -> Self {
22        RecvPacketStateMachine {
23            state: State::Ready,
24            idx: 0,
25        }
26    }
27
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}