summaryrefslogtreecommitdiff
path: root/serde_dhall
diff options
context:
space:
mode:
Diffstat (limited to 'serde_dhall')
-rw-r--r--serde_dhall/src/lib.rs17
-rw-r--r--serde_dhall/src/serde.rs102
-rw-r--r--serde_dhall/tests/de.rs2
3 files changed, 48 insertions, 73 deletions
diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs
index 0a53420..55e098c 100644
--- a/serde_dhall/src/lib.rs
+++ b/serde_dhall/src/lib.rs
@@ -182,16 +182,19 @@ pub use value::Value;
#[doc(hidden)]
pub mod value {
use dhall::syntax::Builtin;
- use dhall::{Normalized, NormalizedExpr, Parsed};
+ use dhall::{Normalized, NormalizedExpr, Parsed, SimpleValue};
- use super::de::{Error, Result};
+ use super::de::Error;
/// A Dhall value
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Value(Normalized);
impl Value {
- pub fn from_str(s: &str, ty: Option<&Value>) -> Result<Self> {
+ pub fn from_str(
+ s: &str,
+ ty: Option<&Value>,
+ ) -> super::de::Result<Self> {
Value::from_str_using_dhall_error_type(s, ty).map_err(Error::Dhall)
}
fn from_str_using_dhall_error_type(
@@ -205,8 +208,10 @@ pub mod value {
};
Ok(Value(typed.normalize()))
}
- pub(crate) fn to_expr(&self) -> NormalizedExpr {
- self.0.to_expr()
+ pub(crate) fn to_simple_value(
+ &self,
+ ) -> Result<SimpleValue, NormalizedExpr> {
+ self.0.to_simple_value()
}
pub(crate) fn as_normalized(&self) -> &Normalized {
&self.0
@@ -241,7 +246,7 @@ pub mod value {
impl super::de::sealed::Sealed for Value {}
impl super::de::Deserialize for Value {
- fn from_dhall(v: &Value) -> Result<Self> {
+ fn from_dhall(v: &Value) -> super::de::Result<Self> {
Ok(v.clone())
}
}
diff --git a/serde_dhall/src/serde.rs b/serde_dhall/src/serde.rs
index 4fd7815..9cb67d1 100644
--- a/serde_dhall/src/serde.rs
+++ b/serde_dhall/src/serde.rs
@@ -4,25 +4,31 @@ use serde::de::value::{
MapAccessDeserializer, MapDeserializer, SeqDeserializer,
};
-use dhall::syntax::{ExprKind, LitKind};
-use dhall::NormalizedExpr;
+use dhall::syntax::LitKind;
+use dhall::{SValKind, SimpleValue};
use crate::de::{Deserialize, Error, Result};
use crate::Value;
impl<'a, T> crate::de::sealed::Sealed for T where T: serde::Deserialize<'a> {}
+struct Deserializer<'a>(Cow<'a, SimpleValue>);
+
impl<'a, T> Deserialize for T
where
T: serde::Deserialize<'a>,
{
fn from_dhall(v: &Value) -> Result<Self> {
- T::deserialize(Deserializer(Cow::Owned(v.to_expr())))
+ let sval = v.to_simple_value().map_err(|expr| {
+ Error::Deserialize(format!(
+ "this cannot be deserialized into the serde data model: {}",
+ expr
+ ))
+ })?;
+ T::deserialize(Deserializer(Cow::Owned(sval)))
}
}
-struct Deserializer<'a>(Cow<'a, NormalizedExpr>);
-
impl<'de: 'a, 'a> serde::de::IntoDeserializer<'de, Error> for Deserializer<'a> {
type Deserializer = Deserializer<'a>;
fn into_deserializer(self) -> Self::Deserializer {
@@ -38,17 +44,11 @@ impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> {
V: serde::de::Visitor<'de>,
{
use std::convert::TryInto;
- use ExprKind::*;
use LitKind::*;
- let expr = self.0.as_ref();
- let not_serde_compatible = || {
- Err(Error::Deserialize(format!(
- "this cannot be deserialized into the serde data model: {}",
- expr
- )))
- };
+ use SValKind::*;
- match expr.kind() {
+ let val = |x| Deserializer(Cow::Borrowed(x));
+ match self.0.kind() {
Lit(Bool(x)) => visitor.visit_bool(*x),
Lit(Natural(x)) => {
if let Ok(x64) = (*x).try_into() {
@@ -69,54 +69,25 @@ impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> {
}
}
Lit(Double(x)) => visitor.visit_f64((*x).into()),
- TextLit(x) => {
- // Normal form ensures that the tail is empty.
- assert!(x.tail().is_empty());
- visitor.visit_str(x.head())
+ Text(x) => visitor.visit_str(x),
+ List(xs) => {
+ visitor.visit_seq(SeqDeserializer::new(xs.iter().map(val)))
}
- EmptyListLit(..) => {
- visitor.visit_seq(SeqDeserializer::new(None::<()>.into_iter()))
- }
- NEListLit(xs) => visitor.visit_seq(SeqDeserializer::new(
- xs.iter().map(|x| Deserializer(Cow::Borrowed(x))),
+ Optional(None) => visitor.visit_none(),
+ Optional(Some(x)) => visitor.visit_some(val(x)),
+ Record(m) => visitor.visit_map(MapDeserializer::new(
+ m.iter().map(|(k, v)| (k.as_ref(), val(v))),
)),
- SomeLit(x) => visitor.visit_some(Deserializer(Cow::Borrowed(x))),
- App(f, x) => match f.kind() {
- Builtin(dhall::syntax::Builtin::OptionalNone) => {
- visitor.visit_none()
- }
- Field(y, name) => match y.kind() {
- UnionType(..) => {
- let name: String = name.into();
- visitor.visit_enum(MapAccessDeserializer::new(
- MapDeserializer::new(
- Some((name, Deserializer(Cow::Borrowed(x))))
- .into_iter(),
- ),
- ))
- }
- _ => not_serde_compatible(),
- },
- _ => not_serde_compatible(),
- },
- RecordLit(m) => visitor
- .visit_map(MapDeserializer::new(m.iter().map(|(k, v)| {
- (k.as_ref(), Deserializer(Cow::Borrowed(v)))
- }))),
- Field(y, name) => match y.kind() {
- UnionType(..) => {
- let name: String = name.into();
- visitor.visit_enum(MapAccessDeserializer::new(
- MapDeserializer::new(Some((name, ())).into_iter()),
- ))
- }
- _ => not_serde_compatible(),
- },
- Const(..) | Var(..) | Lam(..) | Pi(..) | Let(..) | Annot(..)
- | Assert(..) | Builtin(..) | BinOp(..) | BoolIf(..)
- | RecordType(..) | UnionType(..) | Merge(..) | ToMap(..)
- | Projection(..) | ProjectionByExpr(..) | Completion(..)
- | Import(..) => not_serde_compatible(),
+ Union(field_name, Some(x)) => visitor.visit_enum(
+ MapAccessDeserializer::new(MapDeserializer::new(
+ Some((field_name.as_str(), val(x))).into_iter(),
+ )),
+ ),
+ Union(field_name, None) => visitor.visit_enum(
+ MapAccessDeserializer::new(MapDeserializer::new(
+ Some((field_name.as_str(), ())).into_iter(),
+ )),
+ ),
}
}
@@ -124,14 +95,11 @@ impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> {
where
V: serde::de::Visitor<'de>,
{
- use ExprKind::*;
- let expr = self.0.as_ref();
-
- match expr.kind() {
+ let val = |x| Deserializer(Cow::Borrowed(x));
+ match self.0.kind() {
// Blindly takes keys in sorted order.
- RecordLit(m) => visitor.visit_seq(SeqDeserializer::new(
- m.iter().map(|(_, v)| Deserializer(Cow::Borrowed(v))),
- )),
+ SValKind::Record(m) => visitor
+ .visit_seq(SeqDeserializer::new(m.iter().map(|(_, v)| val(v)))),
_ => self.deserialize_any(visitor),
}
}
diff --git a/serde_dhall/tests/de.rs b/serde_dhall/tests/de.rs
index 74912dd..4042611 100644
--- a/serde_dhall/tests/de.rs
+++ b/serde_dhall/tests/de.rs
@@ -51,6 +51,8 @@ fn test_de_typed() {
Y(i64),
}
assert_eq!(parse::<Baz>("< X | Y: Integer >.X"), Baz::X);
+
+ assert!(from_str_auto_type::<Baz>("< X | Y: Integer >.Y").is_err());
}
#[test]