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 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}