Parser

Struct Parser 

Source
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: CompatibilityTable

Implementations§

Source§

impl Parser

Source

pub fn new() -> Self

Create a default, empty Parser with an internal buffer capacity of 128 bytes.

Examples found in repository?
examples/basic.rs (line 6)
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}
Source

pub fn with_capacity(size: usize) -> Self

Create an empty parser, setting the initial internal buffer capcity.

Source

pub fn with_support(table: CompatibilityTable) -> Self

Create a parser, directly supplying a CompatibilityTable.

Uses the default initial buffer capacity of 128 bytes.

Source

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.

Source

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?
examples/basic.rs (line 9)
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}
Source

pub fn linemode_enabled(&self) -> bool

Get whether the remote end supports and is using linemode.

Source

pub fn escape_iac<T>(data: T) -> Bytes
where Bytes: From<T>,

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]);
Source

pub fn unescape_iac<T>(data: T) -> Bytes
where Bytes: From<T>,

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]);
Source

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.

Source

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.

Source

pub fn _wont(&mut self, option: u8) -> Option<TelnetEvents>

Indicate to the other side that you are not wanting to utilize an option.

§Arguments

option - A u8 representing the telnet option code that you want to disable locally.

§Returns

Option<TelnetEvents::DataSend> - A DataSend event to be processed, or None if the option is already disabled.

Source

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.

Source

pub fn _dont(&mut self, option: u8) -> Option<TelnetEvents>

Indicate to the other side that you would like them to stop utilizing an option.

§Arguments

option - A u8 representing the telnet option code that you want to disable remotely.

§Returns

Option<TelnetEvents::DataSend> - A DataSend event to be processed, or None if the option is already disabled.

Source

pub fn subnegotiation<T>(&mut self, option: u8, data: T) -> Option<TelnetEvents>
where Bytes: From<T>,

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.

Source

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?
examples/basic.rs (line 37)
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}
Source

pub fn send_text(&mut self, text: &str) -> TelnetEvents

Directly send a string, with appended \r\n, to the remote end, along with an IAC (255) GOAHEAD (249) sequence.

§Returns

TelnetEvents::DataSend - A DataSend event to be processed.

§Notes

The string will have IAC (255) bytes escaped before being sent.

Trait Implementations§

Source§

impl Default for Parser

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for Parser

§

impl RefUnwindSafe for Parser

§

impl Send for Parser

§

impl Sync for Parser

§

impl Unpin for Parser

§

impl UnwindSafe for Parser

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.