From eff2ed3b51fecf4e6799690c09ce35daa6e51280 Mon Sep 17 00:00:00 2001 From: Azriel Hoh Date: Wed, 10 Oct 2018 08:59:46 +1300 Subject: Implement deserialization for unit and struct variants. Issue #225 --- src/de.rs | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-) (limited to 'src/de.rs') diff --git a/src/de.rs b/src/de.rs index 491ae47..5de4f6a 100644 --- a/src/de.rs +++ b/src/de.rs @@ -585,7 +585,27 @@ impl<'de> de::Deserializer<'de> for ValueDeserializer<'de> { { match self.value.e { E::String(val) => visitor.visit_enum(val.into_deserializer()), - _ => Err(Error::from_kind(ErrorKind::ExpectedString)) + E::InlineTable(values) | E::DottedTable(values) => { + if values.len() != 1 { + Err(Error::from_kind(ErrorKind::Wanted { + expected: "exactly 1 element", + found: if values.is_empty() { + "zero elements" + } else { + "more than 1 element" + }, + })) + } else { + visitor.visit_enum(InlineTableDeserializer { + values: values.into_iter(), + next_value: None, + }) + } + } + e @ _ => Err(Error::from_kind(ErrorKind::Wanted { + expected: "string or table", + found: e.type_name(), + })), } } @@ -724,6 +744,70 @@ impl<'de> de::MapAccess<'de> for InlineTableDeserializer<'de> { } } +impl<'de> de::EnumAccess<'de> for InlineTableDeserializer<'de> { + type Error = Error; + type Variant = Self; + + fn variant_seed(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: de::DeserializeSeed<'de>, + { + let (key, value) = match self.values.next() { + Some(pair) => pair, + None => { + return Err(Error::from_kind(ErrorKind::Wanted { + expected: "table with exactly 1 entry", + found: "empty map", + })) + } + }; + self.next_value = Some(value); + + seed.deserialize(StrDeserializer::new(key)) + .map(|val| (val, self)) + } +} + +impl<'de> de::VariantAccess<'de> for InlineTableDeserializer<'de> { + type Error = Error; + + fn unit_variant(self) -> Result<(), Self::Error> { + // TODO: Error handling if there are entries + Ok(()) + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + seed.deserialize(ValueDeserializer::new( + self.next_value.expect("Expected value"), + )) + } + + fn tuple_variant(self, _len: usize, _visitor: V) -> Result + where + V: de::Visitor<'de>, + { + unimplemented!() + } + + fn struct_variant( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + de::Deserializer::deserialize_struct( + ValueDeserializer::new(self.next_value.expect("Expected value")), + "", // TODO: this should be the variant name + fields, + visitor, + ) + } +} impl<'a> Deserializer<'a> { /// Creates a new deserializer which will be deserializing the string @@ -1510,6 +1594,21 @@ enum E<'a> { DottedTable(Vec<(Cow<'a, str>, Value<'a>)>), } +impl<'a> E<'a> { + fn type_name(&self) -> &'static str { + match *self { + E::String(..) => "string", + E::Integer(..) => "integer", + E::Float(..) => "float", + E::Boolean(..) => "boolean", + E::Datetime(..) => "datetime", + E::Array(..) => "array", + E::InlineTable(..) => "inline table", + E::DottedTable(..) => "dotted table", + } + } +} + impl<'a> Value<'a> { fn same_type(&self, other: &Value<'a>) -> bool { match (&self.e, &other.e) { -- cgit v1.2.3