diff options
Diffstat (limited to 'serde_dhall/src')
| -rw-r--r-- | serde_dhall/src/deserialize.rs | 119 | ||||
| -rw-r--r-- | serde_dhall/src/value.rs | 11 | 
2 files changed, 112 insertions, 18 deletions
diff --git a/serde_dhall/src/deserialize.rs b/serde_dhall/src/deserialize.rs index 6d3aab8..1206033 100644 --- a/serde_dhall/src/deserialize.rs +++ b/serde_dhall/src/deserialize.rs @@ -1,12 +1,17 @@ +use std::borrow::Cow; +use std::collections::BTreeMap; +use std::convert::TryInto as _; +use std::fmt; +  use serde::de::value::{      MapAccessDeserializer, MapDeserializer, SeqDeserializer,  }; -use std::borrow::Cow; +use serde::de::VariantAccess as _;  use dhall::syntax::NumKind;  use crate::value::SimpleValue; -use crate::{Error, ErrorKind, Result, Value}; +use crate::{Error, ErrorKind, Value};  pub trait Sealed {} @@ -38,7 +43,7 @@ pub trait Sealed {}  /// [serde]: https://serde.rs  pub trait FromDhall: Sealed + Sized {      #[doc(hidden)] -    fn from_dhall(v: &Value) -> Result<Self>; +    fn from_dhall(v: &Value) -> crate::Result<Self>;  }  impl<T> Sealed for T where T: serde::de::DeserializeOwned {} @@ -83,7 +88,7 @@ struct Deserializer<'a>(Cow<'a, SimpleValue>);  /// ```  ///  /// [`SimpleValue`]: enum.SimpleValue.html -pub fn from_simple_value<T>(v: SimpleValue) -> Result<T> +pub fn from_simple_value<T>(v: SimpleValue) -> crate::Result<T>  where      T: serde::de::DeserializeOwned,  { @@ -94,7 +99,7 @@ impl<T> FromDhall for T  where      T: serde::de::DeserializeOwned,  { -    fn from_dhall(v: &Value) -> Result<Self> { +    fn from_dhall(v: &Value) -> crate::Result<Self> {          let sval = v.to_simple_value().ok_or_else(|| {              Error(ErrorKind::Deserialize(format!(                  "this cannot be deserialized into the serde data model: {}", @@ -115,7 +120,7 @@ impl<'de: 'a, 'a> serde::de::IntoDeserializer<'de, Error> for Deserializer<'a> {  impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> {      type Error = Error; -    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value> +    fn deserialize_any<V>(self, visitor: V) -> crate::Result<V::Value>      where          V: serde::de::Visitor<'de>,      { @@ -167,7 +172,11 @@ impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> {          }      } -    fn deserialize_tuple<V>(self, _: usize, visitor: V) -> Result<V::Value> +    fn deserialize_tuple<V>( +        self, +        _: usize, +        visitor: V, +    ) -> crate::Result<V::Value>      where          V: serde::de::Visitor<'de>,      { @@ -186,3 +195,99 @@ impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> {          tuple_struct map struct enum identifier ignored_any      }  } + +struct SimpleValueVisitor; + +impl<'de> serde::de::Visitor<'de> for SimpleValueVisitor { +    type Value = SimpleValue; + +    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +        formatter.write_str("any valid Dhall value") +    } + +    fn visit_bool<E>(self, value: bool) -> Result<SimpleValue, E> { +        Ok(SimpleValue::Num(NumKind::Bool(value))) +    } + +    fn visit_i64<E>(self, value: i64) -> Result<SimpleValue, E> { +        // TODO: use `i64` instead of `isize` in `NumKind`. +        Ok(SimpleValue::Num(NumKind::Integer( +            value.try_into().unwrap(), +        ))) +    } + +    fn visit_u64<E>(self, value: u64) -> Result<SimpleValue, E> { +        // TODO: use `u64` instead of `usize` in `NumKind`. +        Ok(SimpleValue::Num(NumKind::Natural( +            value.try_into().unwrap(), +        ))) +    } + +    fn visit_f64<E>(self, value: f64) -> Result<SimpleValue, E> { +        Ok(SimpleValue::Num(NumKind::Double(value.into()))) +    } + +    fn visit_str<E>(self, value: &str) -> Result<SimpleValue, E> { +        Ok(SimpleValue::Text(String::from(value))) +    } + +    fn visit_string<E>(self, value: String) -> Result<SimpleValue, E> { +        Ok(SimpleValue::Text(value)) +    } + +    fn visit_none<E>(self) -> Result<SimpleValue, E> { +        Ok(SimpleValue::Optional(None)) +    } + +    fn visit_some<D>(self, val: D) -> Result<SimpleValue, D::Error> +    where +        D: serde::Deserializer<'de>, +    { +        let val = val.deserialize_any(SimpleValueVisitor)?; +        Ok(SimpleValue::Optional(Some(Box::new(val)))) +    } + +    fn visit_enum<V>(self, visitor: V) -> Result<SimpleValue, V::Error> +    where +        V: serde::de::EnumAccess<'de>, +    { +        let (name, variant): (String, _) = visitor.variant()?; +        // Serde does not allow me to check what kind of variant it is. This will work for dhall +        // values, because there are only two possible kinds of cvariants, but doesn't work in +        // general. Given that the `serde_value` crate ignores enums, I assume this is not fixable +        // :(. +        let val = variant.newtype_variant().ok(); +        Ok(SimpleValue::Union(name, val)) +    } + +    fn visit_seq<V>(self, mut visitor: V) -> Result<SimpleValue, V::Error> +    where +        V: serde::de::SeqAccess<'de>, +    { +        let mut vec = Vec::new(); +        while let Some(elem) = visitor.next_element()? { +            vec.push(elem); +        } +        Ok(SimpleValue::List(vec)) +    } + +    fn visit_map<V>(self, mut visitor: V) -> Result<SimpleValue, V::Error> +    where +        V: serde::de::MapAccess<'de>, +    { +        let mut record = BTreeMap::default(); +        while let Some((key, value)) = visitor.next_entry()? { +            record.insert(key, value); +        } +        Ok(SimpleValue::Record(record)) +    } +} + +impl<'de> serde::de::Deserialize<'de> for SimpleValue { +    fn deserialize<D>(deserializer: D) -> Result<SimpleValue, D::Error> +    where +        D: serde::Deserializer<'de>, +    { +        deserializer.deserialize_any(SimpleValueVisitor) +    } +} diff --git a/serde_dhall/src/value.rs b/serde_dhall/src/value.rs index 79ba75a..d7116d9 100644 --- a/serde_dhall/src/value.rs +++ b/serde_dhall/src/value.rs @@ -377,7 +377,6 @@ impl SimpleType {  }  impl Sealed for Value {} -impl Sealed for SimpleValue {}  impl Sealed for SimpleType {}  impl FromDhall for Value { @@ -385,16 +384,6 @@ impl FromDhall for Value {          Ok(v.clone())      }  } -impl FromDhall for SimpleValue { -    fn from_dhall(v: &Value) -> Result<Self> { -        v.to_simple_value().ok_or_else(|| { -            Error(ErrorKind::Deserialize(format!( -                "this cannot be deserialized into a simple type: {}", -                v -            ))) -        }) -    } -}  impl FromDhall for SimpleType {      fn from_dhall(v: &Value) -> Result<Self> {          v.to_simple_type().ok_or_else(|| {  | 
