diff options
author | Azriel Hoh <azriel91@gmail.com> | 2018-10-10 08:59:46 +1300 |
---|---|---|
committer | Azriel Hoh <azriel91@gmail.com> | 2018-11-10 11:06:34 +1300 |
commit | eff2ed3b51fecf4e6799690c09ce35daa6e51280 (patch) | |
tree | bde557a12a1ed32e0870a3f70a93581d0832f3ee /src | |
parent | 3aec5a918a6cb39fa32e8a56725a3c2fc0ed6bc2 (diff) | |
download | milf-rs-eff2ed3b51fecf4e6799690c09ce35daa6e51280.tar.gz milf-rs-eff2ed3b51fecf4e6799690c09ce35daa6e51280.zip |
Implement deserialization for unit and struct variants.
Issue #225
Diffstat (limited to 'src')
-rw-r--r-- | src/de.rs | 101 |
1 files changed, 100 insertions, 1 deletions
@@ -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<V>(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<T>(self, seed: T) -> Result<T::Value, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + seed.deserialize(ValueDeserializer::new( + self.next_value.expect("Expected value"), + )) + } + + fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> + where + V: de::Visitor<'de>, + { + unimplemented!() + } + + fn struct_variant<V>( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> + 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) { |