summaryrefslogtreecommitdiff
path: root/serde_dhall/src
diff options
context:
space:
mode:
Diffstat (limited to 'serde_dhall/src')
-rw-r--r--serde_dhall/src/deserialize.rs119
-rw-r--r--serde_dhall/src/value.rs11
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(|| {