From 92918a5b01a26630d37a28c9eac6afae4bef1b1a Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 6 Sep 2022 18:31:30 +0900 Subject: [PATCH] serde_keyvalue: use nom-based methods for deserialize_any These methods are better to predict the type of what follows than just parsing the next character. For instance, '1foo' was interpreted as an integer whereas it should be a string. BUG=b:218223240 BUG=b:241300017 TEST=cargo test -p serde_keyvalue TEST=cargo test Change-Id: I9a0a3cb73e06783784d47450de7d291adf41aa53 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3889330 Auto-Submit: Alexandre Courbot Reviewed-by: Daniel Verkamp --- serde_keyvalue/src/key_values.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/serde_keyvalue/src/key_values.rs b/serde_keyvalue/src/key_values.rs index 7e96a069c2..81d380280f 100644 --- a/serde_keyvalue/src/key_values.rs +++ b/serde_keyvalue/src/key_values.rs @@ -436,19 +436,22 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut KeyValueDeserializer<'de> { where V: serde::de::Visitor<'de>, { + // If we have no value following, then we are dealing with a boolean flag. match self.peek_char() { - Some('0'..='9') => self.deserialize_u64(visitor), - Some('-') => self.deserialize_i64(visitor), - Some('"') => self.deserialize_string(visitor), - // Only possible option here is boolean flag. - Some(',') | None => self.deserialize_bool(visitor), - _ => { - // We probably have an unquoted string, but possibly a boolean as well. - match any_identifier(self.input) { - Ok((_, "true")) | Ok((_, "false")) => self.deserialize_bool(visitor), - _ => self.deserialize_str(visitor), - } - } + Some(',') | None => return self.deserialize_bool(visitor), + _ => (), + } + + // This is ambiguous as technically any argument could be an unquoted string. However we + // don't have any type information here, so try to guess it on a best-effort basis... + if any_number::(self.input).is_ok() { + self.deserialize_i64(visitor) + } else if any_number::(self.input).is_ok() { + self.deserialize_u64(visitor) + } else if any_bool(self.input).is_ok() { + self.deserialize_bool(visitor) + } else { + self.deserialize_str(visitor) } }