libmudtelnet_rs/
events.rs1use alloc::vec::Vec;
29
30use bytes::{BufMut, Bytes, BytesMut};
31
32use crate::telnet::op_command::{IAC, SB, SE};
33use crate::Parser;
34
35#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
37#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
38pub struct TelnetIAC {
39 pub command: u8,
40}
41
42impl TelnetIAC {
43 #[must_use]
44 pub fn new(command: u8) -> Self {
45 Self { command }
46 }
47
48 #[must_use]
50 pub fn to_bytes(self) -> Bytes {
51 Bytes::copy_from_slice(&[IAC, self.command])
52 }
53
54 #[must_use]
55 #[deprecated(since = "0.2.1", note = "Use `to_bytes` instead.")]
56 pub fn into_bytes(self) -> Bytes {
57 self.to_bytes()
58 }
59}
60
61#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
63#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
64pub struct TelnetNegotiation {
65 pub command: u8,
66 pub option: u8,
67}
68
69impl TelnetNegotiation {
70 #[must_use]
71 pub fn new(command: u8, option: u8) -> Self {
72 Self { command, option }
73 }
74
75 #[must_use]
77 pub fn to_bytes(self) -> Bytes {
78 Bytes::copy_from_slice(&[IAC, self.command, self.option])
79 }
80
81 #[must_use]
82 #[deprecated(since = "0.2.1", note = "Use `to_bytes` instead.")]
83 pub fn into_bytes(self) -> Bytes {
84 self.to_bytes()
85 }
86}
87
88#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
90pub struct TelnetSubnegotiation {
91 pub option: u8,
92 pub buffer: Bytes,
93}
94
95#[cfg(feature = "arbitrary")]
96impl<'a> arbitrary::Arbitrary<'a> for TelnetSubnegotiation {
97 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
98 let option = u.arbitrary()?;
99 let buffer: Vec<u8> = u.arbitrary()?;
100 Ok(Self {
101 option,
102 buffer: Bytes::from(buffer),
103 })
104 }
105}
106
107impl TelnetSubnegotiation {
108 pub fn new(option: u8, buffer: Bytes) -> Self {
109 Self { option, buffer }
110 }
111
112 #[must_use]
113 pub fn to_bytes(self) -> Bytes {
114 let head = [IAC, SB, self.option];
115 let parsed = &Parser::escape_iac(self.buffer)[..];
116 let tail = [IAC, SE];
117 let mut buf = BytesMut::with_capacity(head.len() + parsed.len() + tail.len());
118 buf.put(&head[..]);
119 buf.put(parsed);
120 buf.put(&tail[..]);
121 buf.freeze()
122 }
123
124 #[must_use]
125 #[deprecated(since = "0.2.1", note = "Use `to_bytes` instead.")]
126 pub fn into_bytes(self) -> Bytes {
127 self.to_bytes()
128 }
129}
130
131#[derive(Clone, Debug, Eq, PartialEq)]
133#[non_exhaustive]
134pub enum TelnetEvents {
135 IAC(TelnetIAC),
137 Negotiation(TelnetNegotiation),
139 Subnegotiation(TelnetSubnegotiation),
141 DataReceive(Bytes),
143 DataSend(Bytes),
145 DecompressImmediate(Bytes),
147}
148
149impl From<TelnetIAC> for TelnetEvents {
150 fn from(iac: TelnetIAC) -> Self {
151 TelnetEvents::IAC(iac)
152 }
153}
154
155impl From<TelnetNegotiation> for TelnetEvents {
156 fn from(neg: TelnetNegotiation) -> Self {
157 TelnetEvents::Negotiation(neg)
158 }
159}
160
161impl From<TelnetSubnegotiation> for TelnetEvents {
162 fn from(sub: TelnetSubnegotiation) -> Self {
163 TelnetEvents::Subnegotiation(sub)
164 }
165}
166
167impl TelnetEvents {
168 #[deprecated(since = "0.2.1", note = "Construct enum variant directly or use into.")]
170 pub fn build_send(buffer: Bytes) -> Self {
171 TelnetEvents::DataSend(buffer)
172 }
173
174 #[deprecated(since = "0.2.1", note = "Construct enum variant directly or use into.")]
176 pub fn build_receive(buffer: Bytes) -> Self {
177 TelnetEvents::DataReceive(buffer)
178 }
179
180 #[must_use]
182 #[deprecated(since = "0.2.1", note = "Construct enum variant directly or use into.")]
183 pub fn build_iac(command: u8) -> TelnetEvents {
184 TelnetEvents::IAC(TelnetIAC::new(command))
185 }
186
187 #[must_use]
189 #[deprecated(since = "0.2.1", note = "Construct enum variant directly or use into.")]
190 pub fn build_negotiation(command: u8, option: u8) -> Self {
191 TelnetEvents::Negotiation(TelnetNegotiation::new(command, option))
192 }
193
194 #[deprecated(since = "0.2.1", note = "Construct enum variant directly or use into.")]
196 pub fn build_subnegotiation(option: u8, buffer: Bytes) -> Self {
197 TelnetEvents::Subnegotiation(TelnetSubnegotiation::new(option, buffer))
198 }
199
200 #[must_use]
201 pub fn to_bytes(self) -> Bytes {
202 match self {
203 TelnetEvents::IAC(iac) => iac.to_bytes(),
204 TelnetEvents::Negotiation(neg) => neg.to_bytes(),
205 TelnetEvents::Subnegotiation(sub) => sub.to_bytes(),
206 TelnetEvents::DataReceive(data)
207 | TelnetEvents::DataSend(data)
208 | TelnetEvents::DecompressImmediate(data) => data,
209 }
210 }
211}
212
213#[allow(clippy::from_over_into)]
217impl Into<Bytes> for TelnetIAC {
218 fn into(self) -> Bytes {
219 self.to_bytes()
220 }
221}
222
223#[allow(clippy::from_over_into)]
224impl Into<Vec<u8>> for TelnetIAC {
225 fn into(self) -> Vec<u8> {
226 self.to_bytes().into()
227 }
228}
229
230#[allow(clippy::from_over_into)]
231impl Into<Bytes> for TelnetNegotiation {
232 fn into(self) -> Bytes {
233 self.to_bytes()
234 }
235}
236
237#[allow(clippy::from_over_into)]
238impl Into<Vec<u8>> for TelnetNegotiation {
239 fn into(self) -> Vec<u8> {
240 self.to_bytes().into()
241 }
242}
243
244#[allow(clippy::from_over_into)]
245impl Into<Bytes> for TelnetSubnegotiation {
246 fn into(self) -> Bytes {
247 self.to_bytes()
248 }
249}
250
251#[allow(clippy::from_over_into)]
252impl Into<Vec<u8>> for TelnetSubnegotiation {
253 fn into(self) -> Vec<u8> {
254 self.to_bytes().into()
255 }
256}