aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAzriel Hoh <azriel91@gmail.com>2018-10-10 08:59:46 +1300
committerAzriel Hoh <azriel91@gmail.com>2018-11-10 11:06:34 +1300
commiteff2ed3b51fecf4e6799690c09ce35daa6e51280 (patch)
treebde557a12a1ed32e0870a3f70a93581d0832f3ee /src
parent3aec5a918a6cb39fa32e8a56725a3c2fc0ed6bc2 (diff)
downloadmilf-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.rs101
1 files changed, 100 insertions, 1 deletions
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<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) {