mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-09 03:57:24 +00:00
serde_keyvalue: fix parsing of quoted strings in a sequence
Parsing a quoted string as the last element of a sequence would fail since ']' was not recognized as a separator. Fix this and factorize the code recognizing separators into a single function to prevent this kind of issue from happening again in the future. BUG=None TEST=cargo test -p serde_keyvalue Change-Id: I1367da843787c40fb6c15a615d7cd036bddd1381 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4054812 Auto-Submit: Alexandre Courbot <acourbot@chromium.org> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Commit-Queue: Alexandre Courbot <acourbot@chromium.org>
This commit is contained in:
parent
ad37ad97dd
commit
171752d9ee
1 changed files with 63 additions and 8 deletions
|
@ -215,6 +215,10 @@ fn any_identifier(s: &str) -> IResult<&str, &str> {
|
|||
ident(s)
|
||||
}
|
||||
|
||||
fn is_separator(c: Option<char>) -> bool {
|
||||
matches!(c, Some(',') | Some(']') | None)
|
||||
}
|
||||
|
||||
/// Serde deserializer for key-values strings.
|
||||
pub struct KeyValueDeserializer<'de> {
|
||||
/// Full input originally received for parsing.
|
||||
|
@ -316,11 +320,12 @@ impl<'de> KeyValueDeserializer<'de> {
|
|||
|
||||
self.input = remainder;
|
||||
|
||||
// The character following a string will be either a comma or EOS. If we have something
|
||||
// else, this means an unquoted string should probably have been quoted.
|
||||
match self.peek_char() {
|
||||
Some(',') | None => Ok(res),
|
||||
Some(_) => Err(self.error_here(ErrorKind::InvalidCharInString)),
|
||||
// The character following a string will be either a comma, a closing bracket, or EOS. If
|
||||
// we have something else, this means an unquoted string should probably have been quoted.
|
||||
if is_separator(self.peek_char()) {
|
||||
Ok(res)
|
||||
} else {
|
||||
Err(self.error_here(ErrorKind::InvalidCharInString))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,8 +401,8 @@ impl<'de> de::MapAccess<'de> for KeyValueDeserializer<'de> {
|
|||
Ok(val)
|
||||
}
|
||||
// Ok if we are parsing a boolean where an empty value means true.
|
||||
Some(',') | Some(']') | None => Ok(val),
|
||||
Some(_) => Err(self.error_here(ErrorKind::ExpectedEqual)),
|
||||
c if is_separator(c) => Ok(val),
|
||||
_ => Err(self.error_here(ErrorKind::ExpectedEqual)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,7 +558,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut KeyValueDeserializer<'de> {
|
|||
{
|
||||
match self.peek_char() {
|
||||
// If we have no value following, then we are dealing with a boolean flag.
|
||||
Some(',') | None => return self.deserialize_bool(visitor),
|
||||
c if is_separator(c) => return self.deserialize_bool(visitor),
|
||||
// Opening bracket means we have a sequence.
|
||||
Some('[') => return self.deserialize_seq(visitor),
|
||||
_ => (),
|
||||
|
@ -1408,6 +1413,56 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_vector_of_strings() {
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
struct TestStruct {
|
||||
strs: Vec<String>,
|
||||
}
|
||||
|
||||
// Unquoted strings
|
||||
let res: TestStruct =
|
||||
from_key_values(r#"strs=[singleword,camel_cased,kebab-cased]"#).unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
TestStruct {
|
||||
strs: vec![
|
||||
"singleword".into(),
|
||||
"camel_cased".into(),
|
||||
"kebab-cased".into()
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
// All quoted strings
|
||||
let res: TestStruct =
|
||||
from_key_values(r#"strs=["first string","second string","third string"]"#).unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
TestStruct {
|
||||
strs: vec![
|
||||
"first string".into(),
|
||||
"second string".into(),
|
||||
"third string".into()
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
// Mix
|
||||
let res: TestStruct =
|
||||
from_key_values(r#"strs=[unquoted,"quoted string",'quoted with escape "']"#).unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
TestStruct {
|
||||
strs: vec![
|
||||
"unquoted".into(),
|
||||
"quoted string".into(),
|
||||
"quoted with escape \"".into()
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_vector_of_structs() {
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
|
|
Loading…
Reference in a new issue