Implemented enum tuple deserialization.

Issue #225
This commit is contained in:
Azriel Hoh 2018-10-10 11:36:46 +13:00
parent 9a69c17a4e
commit 4f28c2f639
2 changed files with 68 additions and 9 deletions

View file

@ -11,7 +11,8 @@ extern crate serde_derive;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
struct Config { struct Config {
plain: MyEnum, plain: MyEnum,
// tuple: MyEnum, plain_table: MyEnum,
tuple: MyEnum,
#[serde(rename = "struct")] #[serde(rename = "struct")]
structv: MyEnum, structv: MyEnum,
newtype: MyEnum, newtype: MyEnum,
@ -29,12 +30,13 @@ enum MyEnum {
fn main() { fn main() {
let toml_str = r#" let toml_str = r#"
plain = "Plain" plain = "Plain"
# tuple = { 0 = 123, 1 = true } plain_table = { Plain = {} }
tuple = { Tuple = { 0 = 123, 1 = true } }
struct = { Struct = { value = 123 } } struct = { Struct = { value = 123 } }
newtype = { NewType = "value" } newtype = { NewType = "value" }
my_enum = [ my_enum = [
{ Plain = {} }, { Plain = {} },
# { Tuple = { 0 = 123, 1 = true } }, { Tuple = { 0 = 123, 1 = true } },
{ NewType = "value" }, { NewType = "value" },
{ Struct = { value = 123 } } { Struct = { value = 123 } }
]"#; ]"#;

View file

@ -162,6 +162,12 @@ enum ErrorKind {
/// A struct was expected but something else was found /// A struct was expected but something else was found
ExpectedString, ExpectedString,
/// A tuple with a certain number of elements was expected but something else was found
ExpectedTuple(usize),
/// An empty table was expected but entries were found
ExpectedEmptyTable,
/// Dotted key attempted to extend something that is not a table. /// Dotted key attempted to extend something that is not a table.
DottedKeyInvalidType, DottedKeyInvalidType,
@ -757,7 +763,7 @@ impl<'de> de::EnumAccess<'de> for InlineTableDeserializer<'de> {
None => { None => {
return Err(Error::from_kind(ErrorKind::Wanted { return Err(Error::from_kind(ErrorKind::Wanted {
expected: "table with exactly 1 entry", expected: "table with exactly 1 entry",
found: "empty map", found: "empty table",
})) }))
} }
}; };
@ -772,8 +778,19 @@ impl<'de> de::VariantAccess<'de> for InlineTableDeserializer<'de> {
type Error = Error; type Error = Error;
fn unit_variant(self) -> Result<(), Self::Error> { fn unit_variant(self) -> Result<(), Self::Error> {
// TODO: Error handling if there are entries match self.next_value.expect("Expected value").e {
E::InlineTable(values) | E::DottedTable(values) => {
if values.len() == 0 {
Ok(()) Ok(())
} else {
Err(Error::from_kind(ErrorKind::ExpectedEmptyTable))
}
}
e @ _ => Err(Error::from_kind(ErrorKind::Wanted {
expected: "table",
found: e.type_name(),
})),
}
} }
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error> fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
@ -785,12 +802,46 @@ impl<'de> de::VariantAccess<'de> for InlineTableDeserializer<'de> {
)) ))
} }
fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where where
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
let next_value = self.next_value.expect("Expected value");
match next_value.e {
E::InlineTable(values) | E::DottedTable(values) => {
let tuple_values = values
.into_iter()
.enumerate()
.filter_map(|(index, (key, value))| {
// TODO: Is this expensive?
if key == format!("{}", index) {
Some(value)
} else {
// TODO: Err()
unimplemented!() unimplemented!()
} }
})
.collect::<Vec<_>>(); // TODO: is this expensive?
if tuple_values.len() == len {
de::Deserializer::deserialize_seq(
ValueDeserializer::new(Value {
e: E::Array(tuple_values),
start: next_value.start,
end: next_value.end,
}),
visitor,
)
} else {
Err(Error::from_kind(ErrorKind::ExpectedTuple(len)))
}
}
e @ _ => Err(Error::from_kind(ErrorKind::Wanted {
expected: "table",
found: e.type_name(),
})),
}
}
fn struct_variant<V>( fn struct_variant<V>(
self, self,
@ -1470,7 +1521,11 @@ impl fmt::Display for Error {
ErrorKind::MultilineStringKey => "multiline strings are not allowed for key".fmt(f)?, ErrorKind::MultilineStringKey => "multiline strings are not allowed for key".fmt(f)?,
ErrorKind::Custom => self.inner.message.fmt(f)?, ErrorKind::Custom => self.inner.message.fmt(f)?,
ErrorKind::ExpectedString => "expected string".fmt(f)?, ErrorKind::ExpectedString => "expected string".fmt(f)?,
ErrorKind::DottedKeyInvalidType => "dotted key attempted to extend non-table type".fmt(f)?, ErrorKind::ExpectedTuple(l) => write!(f, "expected tuple with length {}", l)?,
ErrorKind::ExpectedEmptyTable => "expected empty table".fmt(f)?,
ErrorKind::DottedKeyInvalidType => {
"dotted key attempted to extend non-table type".fmt(f)?
}
ErrorKind::__Nonexhaustive => panic!(), ErrorKind::__Nonexhaustive => panic!(),
} }
@ -1515,6 +1570,8 @@ impl error::Error for Error {
ErrorKind::MultilineStringKey => "invalid multiline string for key", ErrorKind::MultilineStringKey => "invalid multiline string for key",
ErrorKind::Custom => "a custom error", ErrorKind::Custom => "a custom error",
ErrorKind::ExpectedString => "expected string", ErrorKind::ExpectedString => "expected string",
ErrorKind::ExpectedTuple(_) => "expected tuple",
ErrorKind::ExpectedEmptyTable => "expected empty table",
ErrorKind::DottedKeyInvalidType => "dotted key invalid type", ErrorKind::DottedKeyInvalidType => "dotted key invalid type",
ErrorKind::__Nonexhaustive => panic!(), ErrorKind::__Nonexhaustive => panic!(),
} }