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 <acourbot@chromium.org>
Auto-Submit: Alexandre Courbot <acourbot@chromium.org>
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
This commit is contained in:
Alexandre Courbot 2023-06-06 15:57:00 +09:00 committed by crosvm LUCI
parent f1f0503070
commit f8458abf49

View file

@ -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::<TestStruct>(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<DefaultStruct>,
}
// 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::<TestStruct>(kv).is_err());
// No opening brace.
let kv = "flag=]";
assert!(from_key_values::<TestStruct>(kv).is_err());
}
#[test]
fn deserialize_enum() {
#[derive(Deserialize, PartialEq, Debug)]