pub struct Parser {
pub options: CompatibilityTable,
/* private fields */
}Expand description
Stateful, event‑driven Telnet parser.
Feed incoming bytes with Parser::receive and iterate the returned
events::TelnetEvents to handle application data, negotiations, and
subnegotiations. The parser minimizes copies by slicing into an internal
buffer and returning bytes::Bytes views where possible.
Fields§
§options: CompatibilityTableImplementations§
Source§impl Parser
impl Parser
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a default, empty Parser with an internal buffer capacity of 128 bytes.
Examples found in repository?
4fn main() {
5 // Minimal demo: feed a few bytes and print parsed events
6 let mut parser = Parser::new();
7
8 // Pretend this came from the network: "hi", doubled IAC, CRLF
9 let events = parser.receive(b"hi \xFF\xFF\r\n");
10 for ev in events {
11 match ev {
12 TelnetEvents::DataReceive(buf) => {
13 println!("DATA : {:?}", String::from_utf8_lossy(&buf));
14 }
15 TelnetEvents::Negotiation(n) => {
16 println!("NEG : cmd={} opt={}", n.command, n.option);
17 }
18 TelnetEvents::Subnegotiation(s) => {
19 println!("SUB : opt={} len={}", s.option, s.buffer.len());
20 }
21 TelnetEvents::IAC(i) => {
22 println!("IAC : cmd={}", i.command);
23 }
24 TelnetEvents::DecompressImmediate(b) => {
25 println!("MCCP : boundary len={}", b.len());
26 }
27 TelnetEvents::DataSend(buf) => {
28 // Bytes that should be written to the socket as-is
29 println!("SEND : {} bytes", buf.len());
30 }
31 _ => {}
32 }
33 }
34
35 // Example: send a GMCP payload (application would write buf to the socket)
36 if let Some(TelnetEvents::DataSend(buf)) =
37 parser.subnegotiation_text(op_option::GMCP, "{\"Core.Ping\":1}")
38 {
39 println!("SEND : {} bytes (GMCP)", buf.len());
40 }
41}Sourcepub fn with_capacity(size: usize) -> Self
pub fn with_capacity(size: usize) -> Self
Create an empty parser, setting the initial internal buffer capcity.
Sourcepub fn with_support(table: CompatibilityTable) -> Self
pub fn with_support(table: CompatibilityTable) -> Self
Create a parser, directly supplying a CompatibilityTable.
Uses the default initial buffer capacity of 128 bytes.
Sourcepub fn with_support_and_capacity(size: usize, table: CompatibilityTable) -> Self
pub fn with_support_and_capacity(size: usize, table: CompatibilityTable) -> Self
Create an parser, setting the initial internal buffer capacity and directly supplying a CompatibilityTable.
Sourcepub fn receive(&mut self, data: &[u8]) -> Vec<TelnetEvents>
pub fn receive(&mut self, data: &[u8]) -> Vec<TelnetEvents>
Receive bytes into the internal buffer.
§Arguments
data- The bytes to be received. This should be sourced from the remote side of a connection.
§Returns
Vec<TelnetEvents> - Any events parsed from the internal buffer with the new bytes.
Examples found in repository?
4fn main() {
5 // Minimal demo: feed a few bytes and print parsed events
6 let mut parser = Parser::new();
7
8 // Pretend this came from the network: "hi", doubled IAC, CRLF
9 let events = parser.receive(b"hi \xFF\xFF\r\n");
10 for ev in events {
11 match ev {
12 TelnetEvents::DataReceive(buf) => {
13 println!("DATA : {:?}", String::from_utf8_lossy(&buf));
14 }
15 TelnetEvents::Negotiation(n) => {
16 println!("NEG : cmd={} opt={}", n.command, n.option);
17 }
18 TelnetEvents::Subnegotiation(s) => {
19 println!("SUB : opt={} len={}", s.option, s.buffer.len());
20 }
21 TelnetEvents::IAC(i) => {
22 println!("IAC : cmd={}", i.command);
23 }
24 TelnetEvents::DecompressImmediate(b) => {
25 println!("MCCP : boundary len={}", b.len());
26 }
27 TelnetEvents::DataSend(buf) => {
28 // Bytes that should be written to the socket as-is
29 println!("SEND : {} bytes", buf.len());
30 }
31 _ => {}
32 }
33 }
34
35 // Example: send a GMCP payload (application would write buf to the socket)
36 if let Some(TelnetEvents::DataSend(buf)) =
37 parser.subnegotiation_text(op_option::GMCP, "{\"Core.Ping\":1}")
38 {
39 println!("SEND : {} bytes (GMCP)", buf.len());
40 }
41}Sourcepub fn linemode_enabled(&self) -> bool
pub fn linemode_enabled(&self) -> bool
Get whether the remote end supports and is using linemode.
Sourcepub fn escape_iac<T>(data: T) -> Bytes
pub fn escape_iac<T>(data: T) -> Bytes
Escape IAC bytes in data that is to be transmitted and treated as a non-IAC sequence.
§Example
[255, 1, 6, 2] -> [255, 255, 1, 6, 2]
use libmudtelnet_rs::Parser;
use libmudtelnet_rs::telnet::op_command::IAC;
let out = Parser::escape_iac(vec![IAC, 1, 6, 2]);
assert_eq!(&out[..], [IAC, IAC, 1, 6, 2]);Sourcepub fn unescape_iac<T>(data: T) -> Bytes
pub fn unescape_iac<T>(data: T) -> Bytes
Reverse escaped IAC bytes for non-IAC sequences and data.
§Example
[255, 255, 1, 6, 2] -> [255, 1, 6, 2]
use libmudtelnet_rs::Parser;
use libmudtelnet_rs::telnet::op_command::IAC;
let out = Parser::unescape_iac(vec![IAC, IAC, 1, 6, 2]);
assert_eq!(&out[..], [IAC, 1, 6, 2]);Sourcepub fn negotiate(&mut self, command: u8, option: u8) -> TelnetEvents
pub fn negotiate(&mut self, command: u8, option: u8) -> TelnetEvents
Negotiate an option.
§Arguments
command - A u8 representing the telnet command code to be negotiated with. Example: WILL (251), WONT (252), DO (253), DONT (254)
option - A u8 representing the telnet option code that is being negotiated.
§Returns
TelnetEvents::DataSend - A DataSend event to be processed.
§Usage
This and other methods meant for sending data to the remote end will generate a TelnetEvents::Send(DataEvent) event.
These Send events contain a buffer that should be sent directly to the remote end, as it will have already been encoded properly.
Sourcepub fn _will(&mut self, option: u8) -> Option<TelnetEvents>
pub fn _will(&mut self, option: u8) -> Option<TelnetEvents>
Indicate to the other side that you are able and wanting to utilize an option.
§Arguments
option - A u8 representing the telnet option code that you want to enable locally.
§Returns
Option<TelnetEvents::DataSend> - The DataSend event to be processed, or None if not supported.
§Notes
This method will do nothing if the option is not “supported” locally via the CompatibilityTable.
Sourcepub fn _wont(&mut self, option: u8) -> Option<TelnetEvents>
pub fn _wont(&mut self, option: u8) -> Option<TelnetEvents>
Sourcepub fn _do(&mut self, option: u8) -> Option<TelnetEvents>
pub fn _do(&mut self, option: u8) -> Option<TelnetEvents>
Indicate to the other side that you would like them to utilize an option.
§Arguments
option - A u8 representing the telnet option code that you want to enable remotely.
§Returns
Option<TelnetEvents::DataSend> - A DataSend event to be processed, or None if the option is not supported or already enabled.
§Notes
This method will do nothing if the option is not “supported” remotely via the CompatibilityTable.
Sourcepub fn _dont(&mut self, option: u8) -> Option<TelnetEvents>
pub fn _dont(&mut self, option: u8) -> Option<TelnetEvents>
Sourcepub fn subnegotiation<T>(&mut self, option: u8, data: T) -> Option<TelnetEvents>
pub fn subnegotiation<T>(&mut self, option: u8, data: T) -> Option<TelnetEvents>
Send a subnegotiation for a locally supported option.
§Arguments
option - A u8 representing the telnet option code for the negotiation.
data - A Bytes containing the data to be sent in the subnegotiation. This data will have all IAC (255) byte values escaped.
§Returns
Option<TelnetEvents::DataSend> - A DataSend event to be processed, or None if the option is not supported or is currently disabled.
§Notes
This method will do nothing if the option is not supported/enabled. For
most options, the client must be the performer (local + local_state). For
GMCP/MSDP specifically, the parser also allows sending when the remote
side has enabled the option (remote + remote_state), reflecting the
de‑facto bidirectional semantics after a WILL/DO handshake.
Sourcepub fn subnegotiation_text(
&mut self,
option: u8,
text: &str,
) -> Option<TelnetEvents>
pub fn subnegotiation_text( &mut self, option: u8, text: &str, ) -> Option<TelnetEvents>
Send a subnegotiation for a locally supported option, using a string instead of raw byte values.
§Arguments
option - A u8 representing the telnet option code for the negotiation.
text - A &str representing the text to be sent in the subnegotation. This data will have all IAC (255) byte values escaped.
§Returns
Option<TelnetEvents::DataSend> - A DataSend event to be processed, or None if the option is not supported or is currently disabled.
§Notes
This method will do nothing if the option is not “supported” locally via the CompatibilityTable.
Examples found in repository?
4fn main() {
5 // Minimal demo: feed a few bytes and print parsed events
6 let mut parser = Parser::new();
7
8 // Pretend this came from the network: "hi", doubled IAC, CRLF
9 let events = parser.receive(b"hi \xFF\xFF\r\n");
10 for ev in events {
11 match ev {
12 TelnetEvents::DataReceive(buf) => {
13 println!("DATA : {:?}", String::from_utf8_lossy(&buf));
14 }
15 TelnetEvents::Negotiation(n) => {
16 println!("NEG : cmd={} opt={}", n.command, n.option);
17 }
18 TelnetEvents::Subnegotiation(s) => {
19 println!("SUB : opt={} len={}", s.option, s.buffer.len());
20 }
21 TelnetEvents::IAC(i) => {
22 println!("IAC : cmd={}", i.command);
23 }
24 TelnetEvents::DecompressImmediate(b) => {
25 println!("MCCP : boundary len={}", b.len());
26 }
27 TelnetEvents::DataSend(buf) => {
28 // Bytes that should be written to the socket as-is
29 println!("SEND : {} bytes", buf.len());
30 }
31 _ => {}
32 }
33 }
34
35 // Example: send a GMCP payload (application would write buf to the socket)
36 if let Some(TelnetEvents::DataSend(buf)) =
37 parser.subnegotiation_text(op_option::GMCP, "{\"Core.Ping\":1}")
38 {
39 println!("SEND : {} bytes (GMCP)", buf.len());
40 }
41}