From f8458abf499bf06c7d2a74f31df5c51a6aebbbb8 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 6 Jun 2023 15:57:00 +0900 Subject: [PATCH] serde_keyvalue: allow structs with default values to be left unspecified Allow optional structs which members all have default values to have their values omitted. This is convenient when we want to specify a flag that can take optional extra arguments. BUG=b:217480278 TEST=cargo test -p serde_keyvalue Change-Id: If2920834f3221146439fc6b8ac54cd9cb215cb9e Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4596440 Commit-Queue: Alexandre Courbot Auto-Submit: Alexandre Courbot Reviewed-by: Keiichi Watanabe --- serde_keyvalue/src/key_values.rs | 74 +++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/serde_keyvalue/src/key_values.rs b/serde_keyvalue/src/key_values.rs index 386ec0aabe..85ea898010 100644 --- a/serde_keyvalue/src/key_values.rs +++ b/serde_keyvalue/src/key_values.rs @@ -771,7 +771,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut KeyValueDeserializer<'de> { Ok(val) } } else { - Err(self.error_here(ErrorKind::ExpectedOpenBracket)) + // The `EmptyMapAccess` failing to parse means that this sequence must take arguments, + // i.e. that an opening bracket is expected. + visitor + .visit_map(EmptyMapAccess) + .map_err(|_| self.error_here(ErrorKind::ExpectedOpenBracket)) } } @@ -818,7 +822,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut KeyValueDeserializer<'de> { if self.peek_char() == Some('[') { self.next_char(); } else { - return Err(self.error_here(ErrorKind::ExpectedOpenBracket)); + // The `EmptyMapAccess` failing to parse means that this struct must take + // arguments, i.e. that an opening bracket is expected. + return visitor + .visit_map(EmptyMapAccess) + .map_err(|_| self.error_here(ErrorKind::ExpectedOpenBracket)); } } @@ -1243,6 +1251,68 @@ mod tests { assert!(from_key_values::(kv).is_err()); } + #[test] + fn deserialize_optional_struct_with_default() { + #[derive(Deserialize, PartialEq, Debug)] + struct DefaultStruct { + #[serde(default)] + param: u32, + } + + #[derive(Deserialize, PartialEq, Debug)] + struct TestStruct { + flag: Option, + } + + // Specify member explicitly + let kv = "flag=[param=12]"; + let res: TestStruct = from_key_values(kv).unwrap(); + assert_eq!( + res, + TestStruct { + flag: Some(DefaultStruct { param: 12 }) + } + ); + + // No member specified, braces present. + let kv = "flag=[]"; + let res: TestStruct = from_key_values(kv).unwrap(); + assert_eq!( + res, + TestStruct { + flag: Some(DefaultStruct { param: 0 }) + } + ); + + // No member specified, no braces. + let kv = "flag="; + let res: TestStruct = from_key_values(kv).unwrap(); + assert_eq!( + res, + TestStruct { + flag: Some(DefaultStruct { param: 0 }) + } + ); + + // No member specified, no braces, no equal sign. + let kv = "flag"; + let res: TestStruct = from_key_values(kv).unwrap(); + assert_eq!( + res, + TestStruct { + flag: Some(DefaultStruct { param: 0 }) + } + ); + + // No closing brace. + let kv = "flag=["; + assert!(from_key_values::(kv).is_err()); + + // No opening brace. + let kv = "flag=]"; + assert!(from_key_values::(kv).is_err()); + } + #[test] fn deserialize_enum() { #[derive(Deserialize, PartialEq, Debug)]