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=valueorkey="quoted value" - Escaped strings:
"value with \"quotes\" and \\backslashes"
§What This Type Does NOT Do
- Parse the status code or divider (use
ParsedLinefor 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
impl ControlLine
Sourcepub fn remainder(&self) -> &str
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");Sourcepub fn is_empty(&self) -> bool
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());Sourcepub fn is_next_quoted(&self) -> bool
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());Sourcepub fn is_next_mapping(&self, key: Option<&str>, quoted: bool) -> bool
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- IfSome, checks that the key matches this valuequoted- Iftrue, 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));Sourcepub fn peek_key(&self) -> Option<&str>
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);Sourcepub fn pop(&mut self, quoted: bool, escaped: bool) -> Result<String, Error>
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- Iftrue, expects and removes surrounding quotesescaped- Iftrue, 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
quotedistruebut 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");Sourcepub fn pop_mapping(
&mut self,
quoted: bool,
escaped: bool,
) -> Result<(String, String), Error>
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- Iftrue, expects the value to be quotedescaped- Iftrue, processes escape sequences in the value
§Errors
Returns Error::Protocol if:
- The next entry is not a
KEY=VALUEmapping quotedistruebut 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());