Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 121 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,21 @@
.unwrap_or(self.buffer.len())
}

/// Finds the index of the character after the raw string parameter (comma or end of data).
fn find_end_of_raw_string_parameter(&self) -> usize {
self.buffer_index
+ self
.buffer
.get(self.buffer_index..)
.map(|buffer| {
buffer
.iter()
.take_while(|byte| **byte != b',' && !(**byte as char).is_ascii_control())
Comment thread
diondokter marked this conversation as resolved.
Outdated
.count()
})
.unwrap_or(self.buffer.len())
}

fn parse_int_parameter(&self) -> (usize, bool, Option<i32>) {
let mut new_buffer_index = self.buffer_index;
// Get the end index of the current parameter.
Expand Down Expand Up @@ -237,7 +252,7 @@
}
}

fn parse_raw_string_parameter(&self) -> (usize, bool, Option<&'a str>) {
fn parse_raw_string(&self) -> (usize, bool, Option<&'a str>) {
let mut new_buffer_index = self.buffer_index;
// Get the end index of the current string.
let end = self.find_end_of_raw_string();
Expand All @@ -255,6 +270,38 @@
}
}

fn parse_raw_string_parameter(&self) -> (usize, bool, Option<&'a str>) {
let mut new_buffer_index = self.buffer_index;
// Get the end index of the current parameter.
let parameter_end = self.find_end_of_raw_string_parameter();
// Get the bytes in which the string should reside.
let string_slice = &self.buffer[new_buffer_index..parameter_end];

if string_slice.is_empty() {
// We probably hit the end of the buffer.
// The parameter is empty but as it is optional not invalid
// Advance the index to the character after the parameter separator (comma) if it's there.
new_buffer_index =
parameter_end + (self.buffer.get(parameter_end) == Some(&b',')) as usize;
return (new_buffer_index, true, None);
}

let has_comma_after_parameter = if let Some(next_char) = self.buffer.get(parameter_end) {
*next_char == b','
} else {
false
};

// Advance the index to the character after the parameter separator.
new_buffer_index = parameter_end + has_comma_after_parameter as usize;
// If we've found a valid string, then the data may be valid and we allow the closure to set the result ok data.
if let Ok(parameter_value) = core::str::from_utf8(string_slice) {
(new_buffer_index, true, Some(parameter_value))
} else {
(new_buffer_index, false, None)
}
}

/// Finish parsing the command and get the results
pub fn finish(self) -> Result<D, ParseError> {
if self.data_valid {
Expand All @@ -280,7 +327,7 @@

let (buffer_index, data_valid, data) = self.parse_int_parameter();
if let Some(parameter_value) = data {
return CommandParser {

Check failure on line 330 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid,
Expand All @@ -288,7 +335,7 @@
}
.trim_space();
} else {
return CommandParser {

Check failure on line 338 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid: false,
Expand All @@ -314,7 +361,7 @@

let (buffer_index, data_valid, data) = self.parse_string_parameter();
if let Some(parameter_value) = data {
return CommandParser {

Check failure on line 364 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid,
Expand All @@ -322,7 +369,7 @@
}
.trim_space();
} else {
return CommandParser {

Check failure on line 372 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid: false,
Expand All @@ -344,9 +391,41 @@
};
}

let (buffer_index, data_valid, data) = self.parse_raw_string();
if let Some(parameter_value) = data {
return CommandParser {

Check failure on line 396 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid,
data: self.data.tup_cat(parameter_value),
}
.trim_space();
} else {
return CommandParser {

Check failure on line 404 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid: false,
data: self.data.tup_cat(""),
}
.trim_space();
}
}

/// Tries reading a raw string parameter (non-quoted string separated by commas)
pub fn expect_raw_string_parameter(self) -> CommandParser<'a, D::Out> {
// If we're already not valid, then quit
if !self.data_valid {
return CommandParser {
buffer: self.buffer,
buffer_index: self.buffer_index,
data_valid: self.data_valid,
data: self.data.tup_cat(""),
};
}

let (buffer_index, data_valid, data) = self.parse_raw_string_parameter();
if let Some(parameter_value) = data {
return CommandParser {

Check failure on line 428 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid,
Expand All @@ -354,7 +433,7 @@
}
.trim_space();
} else {
return CommandParser {

Check failure on line 436 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid: false,
Expand Down Expand Up @@ -383,7 +462,7 @@
}

let (buffer_index, data_valid, data) = self.parse_int_parameter();
return CommandParser {

Check failure on line 465 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid,
Expand All @@ -407,7 +486,7 @@
}

let (buffer_index, data_valid, data) = self.parse_string_parameter();
return CommandParser {

Check failure on line 489 in src/parser.rs

View workflow job for this annotation

GitHub Actions / Clippy

unneeded `return` statement
buffer: self.buffer,
buffer_index,
data_valid,
Expand All @@ -428,6 +507,28 @@
};
}

let (buffer_index, data_valid, data) = self.parse_raw_string();
return CommandParser {
buffer: self.buffer,
buffer_index,
data_valid,
data: self.data.tup_cat(data),
}
.trim_space();
}

/// Tries reading an optional raw string parameter (non-quoted string separated by commas)
pub fn expect_optional_raw_string_parameter(self) -> CommandParser<'a, D::Out> {
// If we're already not valid, then quit
if !self.data_valid {
return CommandParser {
buffer: self.buffer,
buffer_index: self.buffer_index,
data_valid: self.data_valid,
data: self.data.tup_cat(None),
};
}

let (buffer_index, data_valid, data) = self.parse_raw_string_parameter();
return CommandParser {
buffer: self.buffer,
Expand Down Expand Up @@ -593,4 +694,23 @@
assert_eq!(y, Some("true"));
assert_eq!(z, None);
}

#[test]
fn test_raw_string_parameter() {
let (x, y, raw, z) =
CommandParser::parse(b"+SYSGPIOREAD:654,\"true\",123ABC,-65154\r\nOK\r\n")
.expect_identifier(b"+SYSGPIOREAD:")
.expect_int_parameter()
.expect_string_parameter()
.expect_raw_string_parameter()
.expect_int_parameter()
.expect_identifier(b"\r\nOK\r\n")
.finish()
.unwrap();

assert_eq!(x, 654);
assert_eq!(y, "true");
assert_eq!(raw, "123ABC");
assert_eq!(z, -65154);
}
}
Loading