ControlLine

Struct ControlLine 

Source
pub struct ControlLine { /* private fields */ }
Expand description

A parser for space-delimited control protocol response content.

ControlLine provides methods for parsing the content portion of control protocol responses, which often contain space-separated values and KEY=VALUE mappings. It maintains an internal position to track parsing progress.

§Conceptual Role

After extracting the content from a ParsedLine, ControlLine is used to parse individual entries from that content. It supports:

  • Unquoted values: value1 value2 value3
  • Quoted values: "value with spaces"
  • Key-value mappings: key=value or key="quoted value"
  • Escaped strings: "value with \"quotes\" and \\backslashes"

§What This Type Does NOT Do

  • Parse the status code or divider (use ParsedLine for that)
  • Handle multi-line data blocks
  • Validate semantic correctness of values

§Thread Safety

ControlLine is Send but not Sync due to internal mutable state for tracking the parse position. For concurrent access, create separate ControlLine instances.

§Example

use stem_rs::protocol::ControlLine;

// Parse space-separated values
let mut line = ControlLine::new("hello world test");
assert_eq!(line.pop(false, false).unwrap(), "hello");
assert_eq!(line.pop(false, false).unwrap(), "world");
assert_eq!(line.pop(false, false).unwrap(), "test");
assert!(line.is_empty());

// Parse quoted values
let mut line = ControlLine::new("\"hello world\" test");
assert_eq!(line.pop(true, false).unwrap(), "hello world");
assert_eq!(line.pop(false, false).unwrap(), "test");

// Parse key=value mappings
let mut line = ControlLine::new("key=value other=\"quoted\"");
let (k, v) = line.pop_mapping(false, false).unwrap();
assert_eq!(k, "key");
assert_eq!(v, "value");
let (k2, v2) = line.pop_mapping(true, false).unwrap();
assert_eq!(k2, "other");
assert_eq!(v2, "quoted");

Implementations§

Source§

impl ControlLine

Source

pub fn new(content: &str) -> Self

Creates a new ControlLine parser for the given content.

The parser starts at the beginning of the content string.

§Arguments
  • content - The content string to parse
§Example
use stem_rs::protocol::ControlLine;

let line = ControlLine::new("key=value other=data");
assert!(!line.is_empty());
Source

pub fn remainder(&self) -> &str

Returns the unparsed remainder of the content.

Leading whitespace is trimmed from the returned string.

§Example
use stem_rs::protocol::ControlLine;

let mut line = ControlLine::new("hello world");
assert_eq!(line.remainder(), "hello world");
line.pop(false, false).unwrap();
assert_eq!(line.remainder(), "world");
Source

pub fn is_empty(&self) -> bool

Returns true if there is no more content to parse.

§Example
use stem_rs::protocol::ControlLine;

let mut line = ControlLine::new("hello");
assert!(!line.is_empty());
line.pop(false, false).unwrap();
assert!(line.is_empty());

let empty = ControlLine::new("");
assert!(empty.is_empty());
Source

pub fn is_next_quoted(&self) -> bool

Returns true if the next entry is a quoted value.

Checks if the next non-whitespace character is a double quote (").

§Example
use stem_rs::protocol::ControlLine;

let line = ControlLine::new("\"quoted\" unquoted");
assert!(line.is_next_quoted());

let line2 = ControlLine::new("unquoted \"quoted\"");
assert!(!line2.is_next_quoted());
Source

pub fn is_next_mapping(&self, key: Option<&str>, quoted: bool) -> bool

Returns true if the next entry is a KEY=VALUE mapping.

Optionally checks that the key matches a specific value and/or that the value is quoted.

§Arguments
  • key - If Some, checks that the key matches this value
  • quoted - If true, checks that the value is quoted
§Example
use stem_rs::protocol::ControlLine;

let line = ControlLine::new("key=value");
assert!(line.is_next_mapping(None, false));
assert!(line.is_next_mapping(Some("key"), false));
assert!(!line.is_next_mapping(Some("other"), false));

let quoted = ControlLine::new("key=\"value\"");
assert!(quoted.is_next_mapping(None, true));
assert!(quoted.is_next_mapping(Some("key"), true));
Source

pub fn peek_key(&self) -> Option<&str>

Returns the key of the next entry if it’s a KEY=VALUE mapping.

Returns None if the next entry is not a mapping.

§Example
use stem_rs::protocol::ControlLine;

let line = ControlLine::new("mykey=myvalue");
assert_eq!(line.peek_key(), Some("mykey"));

let no_mapping = ControlLine::new("just a value");
assert_eq!(no_mapping.peek_key(), None);
Source

pub fn pop(&mut self, quoted: bool, escaped: bool) -> Result<String, Error>

Removes and returns the next space-separated entry.

Advances the internal position past the extracted entry.

§Arguments
  • quoted - If true, expects and removes surrounding quotes
  • escaped - If true, processes escape sequences in the value
§Escape Sequences

When escaped is true, the following sequences are processed:

  • \\n → newline
  • \\r → carriage return
  • \\t → tab
  • \\\\ → backslash
  • \\" → double quote
§Errors

Returns Error::Protocol if:

  • No more content to parse
  • quoted is true but the next entry doesn’t start with a quote
  • A quoted string is not properly terminated
§Example
use stem_rs::protocol::ControlLine;

// Unquoted values
let mut line = ControlLine::new("hello world");
assert_eq!(line.pop(false, false).unwrap(), "hello");
assert_eq!(line.pop(false, false).unwrap(), "world");

// Quoted values
let mut line = ControlLine::new("\"hello world\" test");
assert_eq!(line.pop(true, false).unwrap(), "hello world");

// Escaped values
let mut line = ControlLine::new("\"hello\\nworld\"");
assert_eq!(line.pop(true, true).unwrap(), "hello\nworld");
Source

pub fn pop_mapping( &mut self, quoted: bool, escaped: bool, ) -> Result<(String, String), Error>

Removes and returns the next KEY=VALUE mapping.

Parses the next entry as a key-value pair separated by =. Advances the internal position past the extracted mapping.

§Arguments
  • quoted - If true, expects the value to be quoted
  • escaped - If true, processes escape sequences in the value
§Errors

Returns Error::Protocol if:

  • The next entry is not a KEY=VALUE mapping
  • quoted is true but the value is not quoted
  • A quoted string is not properly terminated
§Example
use stem_rs::protocol::ControlLine;

// Simple mapping
let mut line = ControlLine::new("key=value other=data");
let (k, v) = line.pop_mapping(false, false).unwrap();
assert_eq!(k, "key");
assert_eq!(v, "value");

// Quoted mapping
let mut line = ControlLine::new("key=\"hello world\"");
let (k, v) = line.pop_mapping(true, false).unwrap();
assert_eq!(k, "key");
assert_eq!(v, "hello world");

// Error: not a mapping
let mut line = ControlLine::new("not_a_mapping");
assert!(line.pop_mapping(false, false).is_err());

Auto Trait Implementations§

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> Same for T

Source§

type Output = T

Should always be Self
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.