From 82d62c4d7d423817a4fd9d6294d27d18d60bcd22 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 11 Apr 2019 13:11:52 +0200 Subject: Add basic deserialization support Closes #13 --- dhall/src/error.rs | 3 ++ dhall/src/lib.rs | 7 ++--- dhall/src/serde.rs | 68 ++++++++++++++++++++++++++++++++++++++--- dhall/src/traits/deserialize.rs | 2 +- dhall/src/traits/static_type.rs | 24 +++++++++++++++ 5 files changed, 95 insertions(+), 9 deletions(-) (limited to 'dhall/src') diff --git a/dhall/src/error.rs b/dhall/src/error.rs index 9e64b7e..cfd6f09 100644 --- a/dhall/src/error.rs +++ b/dhall/src/error.rs @@ -25,5 +25,8 @@ quick_error! { from() display("{:?}", err) } + Deserialize(err: String) { + display("{}", err) + } } } diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs index c218aeb..8af5af9 100644 --- a/dhall/src/lib.rs +++ b/dhall/src/lib.rs @@ -39,14 +39,13 @@ //! //! #[derive(Debug, Deserialize, SimpleStaticType)] //! struct Point { -//! x: usize, -//! y: usize, +//! x: u64, +//! y: u64, //! } //! //! fn main() { //! // Some dhall data -//! // ./Point can be populated using Point::get_type().to_string() -//! let data = "{ x = 1, y = 1 + 1 } : ./Point"; +//! let data = "{ x = 1, y = 1 + 1 }"; //! //! // Convert the dhall string to a Point. //! let point: Point = diff --git a/dhall/src/serde.rs b/dhall/src/serde.rs index 4ac4f3d..196bda1 100644 --- a/dhall/src/serde.rs +++ b/dhall/src/serde.rs @@ -1,9 +1,69 @@ -use crate::error::Result; -use crate::expr::Type; +use crate::error::{Error, Result}; +use crate::expr::{Normalized, Type}; use crate::traits::Deserialize; +use dhall_core::*; +use std::borrow::Cow; impl<'a, T: serde::Deserialize<'a>> Deserialize<'a> for T { - fn from_str(_s: &'a str, _ty: Option<&Type>) -> Result { - unimplemented!() + fn from_str(s: &'a str, ty: Option<&Type>) -> Result { + let expr = Normalized::from_str(s, ty)?; + T::deserialize(Deserializer(Cow::Owned(expr.0))) + } +} + +struct Deserializer<'a>(Cow<'a, SubExpr>); + +impl serde::de::Error for Error { + fn custom(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::Deserialize(msg.to_string()) + } +} + +impl<'de: 'a, 'a> serde::de::IntoDeserializer<'de, Error> for Deserializer<'a> { + type Deserializer = Deserializer<'a>; + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + +impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> { + type Error = Error; + fn deserialize_any(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + use std::convert::TryInto; + use ExprF::*; + match self.0.as_ref().as_ref() { + NaturalLit(n) => match (*n).try_into() { + Ok(n64) => visitor.visit_u64(n64), + Err(_) => match (*n).try_into() { + Ok(n32) => visitor.visit_u32(n32), + Err(_) => unimplemented!(), + }, + }, + IntegerLit(n) => match (*n).try_into() { + Ok(n64) => visitor.visit_i64(n64), + Err(_) => match (*n).try_into() { + Ok(n32) => visitor.visit_i32(n32), + Err(_) => unimplemented!(), + }, + }, + RecordLit(m) => visitor.visit_map( + serde::de::value::MapDeserializer::new(m.iter().map( + |(k, v)| (k.as_ref(), Deserializer(Cow::Borrowed(v))), + )), + ), + _ => unimplemented!(), + } + } + + serde::forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any } } diff --git a/dhall/src/traits/deserialize.rs b/dhall/src/traits/deserialize.rs index 5271a65..1fbdfe1 100644 --- a/dhall/src/traits/deserialize.rs +++ b/dhall/src/traits/deserialize.rs @@ -8,7 +8,7 @@ pub trait Deserialize<'a>: Sized { impl<'a> Deserialize<'a> for Parsed { /// Simply parses the provided string. Ignores the /// provided type. - fn from_str(s: &'a str, _ty: Option<&Type>) -> Result { + fn from_str(s: &'a str, _: Option<&Type>) -> Result { Ok(Parsed::parse_str(s)?) } } diff --git a/dhall/src/traits/static_type.rs b/dhall/src/traits/static_type.rs index b402ca9..6c41e3f 100644 --- a/dhall/src/traits/static_type.rs +++ b/dhall/src/traits/static_type.rs @@ -47,12 +47,36 @@ impl SimpleStaticType for Natural { } } +impl SimpleStaticType for u32 { + fn get_simple_static_type() -> SimpleType { + mktype(dhall_expr!(Natural)) + } +} + +impl SimpleStaticType for u64 { + fn get_simple_static_type() -> SimpleType { + mktype(dhall_expr!(Natural)) + } +} + impl SimpleStaticType for Integer { fn get_simple_static_type() -> SimpleType { mktype(dhall_expr!(Integer)) } } +impl SimpleStaticType for i32 { + fn get_simple_static_type() -> SimpleType { + mktype(dhall_expr!(Integer)) + } +} + +impl SimpleStaticType for i64 { + fn get_simple_static_type() -> SimpleType { + mktype(dhall_expr!(Integer)) + } +} + impl SimpleStaticType for String { fn get_simple_static_type() -> SimpleType { mktype(dhall_expr!(Text)) -- cgit v1.2.3