rfc2217_rs/
parser.rs

1use crate::{codes, command, negotiation, subnegotiation, Command, Negotiation, Subnegotiation};
2
3#[derive(Debug, PartialEq, Eq, Clone, Copy)]
4pub enum Event {
5    Data(u8),
6    Command(Command),
7    Negotiation(Negotiation),
8    Subnegotiation(Subnegotiation),
9}
10
11#[derive(Debug, PartialEq, Eq, Clone, Copy)]
12pub enum Error {
13    SubnegotiationParsing,
14    BufferOverflow,
15}
16
17enum State {
18    Data,
19    Command,
20    Negotiation,
21    SubnegotiationOption,
22    SubnegotiationSubOption,
23    SubnegotiationData,
24    SubnegotiationEnd,
25}
26
27pub struct Parser {
28    state: State,
29    buf: [u8; subnegotiation::MAX_SIZE],
30    buf_cnt: usize,
31}
32
33impl Parser {
34    pub const fn new() -> Self {
35        Self {
36            state: State::Data,
37            buf: [0; subnegotiation::MAX_SIZE],
38            buf_cnt: 0,
39        }
40    }
41
42    pub fn reset(&mut self) {
43        *self = Self::new();
44    }
45
46    pub fn process_byte(&mut self, byte: u8) -> Result<Option<Event>, Error> {
47        match self.state {
48            State::Data => {
49                if byte == codes::IAC {
50                    self.state = State::Command;
51                    return Ok(None);
52                }
53                Ok(Some(Event::Data(byte)))
54            }
55
56            State::Command => {
57                if byte == codes::IAC {
58                    self.state = State::Data;
59                    return Ok(Some(Event::Data(byte)));
60                }
61                self.buf_cnt = 0;
62                self.write_to_buf(codes::IAC)?;
63                self.write_to_buf(byte)?;
64                Ok(self.process_command_byte(byte))
65            }
66
67            State::Negotiation => {
68                self.write_to_buf(byte)?;
69                self.state = State::Data;
70                Ok(Some(Event::Negotiation(Negotiation::deserialize(
71                    &self.buf[..negotiation::SIZE],
72                ))))
73            }
74
75            State::SubnegotiationOption => {
76                self.write_to_buf(byte)?;
77                self.state = State::SubnegotiationSubOption;
78                Ok(None)
79            }
80
81            State::SubnegotiationSubOption => {
82                self.write_to_buf(byte)?;
83                self.state = State::SubnegotiationData;
84                Ok(None)
85            }
86
87            State::SubnegotiationData => {
88                self.write_to_buf(byte)?;
89                if byte == codes::IAC {
90                    self.state = State::SubnegotiationEnd;
91                }
92                Ok(None)
93            }
94
95            State::SubnegotiationEnd => {
96                match byte {
97                    // If the IAC byte repeats it's data
98                    codes::IAC => {
99                        self.write_to_buf(byte)?;
100                        self.state = State::SubnegotiationData;
101                        Ok(None)
102                    }
103                    codes::SE => {
104                        self.write_to_buf(byte)?;
105                        self.state = State::Data;
106                        Ok(Some(Event::Subnegotiation(Subnegotiation::deserialize(
107                            &self.buf[..self.buf_cnt],
108                        ))))
109                    }
110                    _ => Err(Error::SubnegotiationParsing),
111                }
112            }
113        }
114    }
115
116    fn process_command_byte(&mut self, command_code: u8) -> Option<Event> {
117        match command_code {
118            codes::WILL | codes::WONT | codes::DO | codes::DONT => {
119                self.state = State::Negotiation;
120                None
121            }
122            codes::SB => {
123                self.state = State::SubnegotiationOption;
124                None
125            }
126            _ => {
127                self.state = State::Data;
128                Some(Event::Command(Command::deserialize(
129                    &self.buf[..command::SIZE],
130                )))
131            }
132        }
133    }
134
135    fn write_to_buf(&mut self, byte: u8) -> Result<(), Error> {
136        if self.buf_cnt == self.buf.len() {
137            return Err(Error::BufferOverflow);
138        }
139        self.buf[self.buf_cnt] = byte;
140        self.buf_cnt += 1;
141        Ok(())
142    }
143}