summaryrefslogtreecommitdiff
path: root/serde_dhall/src
diff options
context:
space:
mode:
authorNadrieril2020-05-10 22:09:43 +0100
committerNadrieril2020-10-28 22:52:41 +0000
commite070270c3f1f10d46281ed7751ff95e15092e7f4 (patch)
tree46c22c75f209c5112030f3db6609ed64ff4888d3 /serde_dhall/src
parent5f3ca811f09dcf6f09fb9b60fcd2664d06762f39 (diff)
Implement serialization
Diffstat (limited to '')
-rw-r--r--serde_dhall/src/deserialize.rs16
-rw-r--r--serde_dhall/src/error.rs11
-rw-r--r--serde_dhall/src/lib.rs6
-rw-r--r--serde_dhall/src/options/de.rs (renamed from serde_dhall/src/options.rs)12
-rw-r--r--serde_dhall/src/options/mod.rs2
-rw-r--r--serde_dhall/src/options/ser.rs67
-rw-r--r--serde_dhall/src/serialize.rs312
-rw-r--r--serde_dhall/src/static_type.rs60
-rw-r--r--serde_dhall/src/value.rs106
9 files changed, 578 insertions, 14 deletions
diff --git a/serde_dhall/src/deserialize.rs b/serde_dhall/src/deserialize.rs
index 12b4703..0e518ea 100644
--- a/serde_dhall/src/deserialize.rs
+++ b/serde_dhall/src/deserialize.rs
@@ -47,8 +47,6 @@ pub trait FromDhall: Sealed + Sized {
impl<T> Sealed for T where T: serde::de::DeserializeOwned {}
-struct Deserializer<'a>(Cow<'a, SimpleValue>);
-
/// Deserialize a Rust value from a Dhall [`SimpleValue`].
///
/// # Example
@@ -109,6 +107,8 @@ where
}
}
+struct Deserializer<'a>(Cow<'a, SimpleValue>);
+
impl<'de: 'a, 'a> serde::de::IntoDeserializer<'de, Error> for Deserializer<'a> {
type Deserializer = Deserializer<'a>;
fn into_deserializer(self) -> Self::Deserializer {
@@ -171,9 +171,19 @@ impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> {
}
}
+ fn deserialize_unit<V>(self, visitor: V) -> crate::Result<V::Value>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ match self.0.as_ref() {
+ SimpleValue::Record(m) if m.is_empty() => visitor.visit_unit(),
+ _ => self.deserialize_any(visitor),
+ }
+ }
+
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
+ bytes byte_buf option unit_struct newtype_struct seq
tuple_struct map struct enum identifier ignored_any
}
}
diff --git a/serde_dhall/src/error.rs b/serde_dhall/src/error.rs
index 896e8b9..3309fe4 100644
--- a/serde_dhall/src/error.rs
+++ b/serde_dhall/src/error.rs
@@ -11,6 +11,7 @@ pub struct Error(pub(crate) ErrorKind);
pub(crate) enum ErrorKind {
Dhall(DhallError),
Deserialize(String),
+ Serialize(String),
}
impl From<ErrorKind> for Error {
@@ -24,6 +25,7 @@ impl std::fmt::Display for Error {
match &self.0 {
ErrorKind::Dhall(err) => write!(f, "{}", err),
ErrorKind::Deserialize(err) => write!(f, "{}", err),
+ ErrorKind::Serialize(err) => write!(f, "{}", err),
}
}
}
@@ -38,3 +40,12 @@ impl serde::de::Error for Error {
ErrorKind::Deserialize(msg.to_string()).into()
}
}
+
+impl serde::ser::Error for Error {
+ fn custom<T>(msg: T) -> Self
+ where
+ T: std::fmt::Display,
+ {
+ ErrorKind::Serialize(msg.to_string()).into()
+ }
+}
diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs
index 8291f74..e236e37 100644
--- a/serde_dhall/src/lib.rs
+++ b/serde_dhall/src/lib.rs
@@ -169,6 +169,7 @@ mod test_readme {
mod deserialize;
mod error;
mod options;
+mod serialize;
mod static_type;
/// Dhall values
mod value;
@@ -176,10 +177,11 @@ mod value;
#[doc(hidden)]
pub use dhall_proc_macros::StaticType;
-pub(crate) use deserialize::Sealed;
pub use deserialize::{from_simple_value, FromDhall};
pub(crate) use error::ErrorKind;
pub use error::{Error, Result};
-pub use options::{from_file, from_str, Deserializer};
+pub use options::de::{from_file, from_str, Deserializer};
+pub use options::ser::{serialize, Serializer};
+pub use serialize::ToDhall;
pub use static_type::StaticType;
pub use value::{NumKind, SimpleType, SimpleValue, Value};
diff --git a/serde_dhall/src/options.rs b/serde_dhall/src/options/de.rs
index 7b27114..8ff794d 100644
--- a/serde_dhall/src/options.rs
+++ b/serde_dhall/src/options/de.rs
@@ -19,20 +19,20 @@ pub struct ManualAnnot<'ty>(&'ty SimpleType);
#[derive(Debug, Clone, Copy)]
pub struct StaticAnnot;
-pub trait HasAnnot<A> {
+pub trait OptionalAnnot<A> {
fn get_annot(a: &A) -> Option<SimpleType>;
}
-impl<T> HasAnnot<NoAnnot> for T {
+impl<T> OptionalAnnot<NoAnnot> for T {
fn get_annot(_: &NoAnnot) -> Option<SimpleType> {
None
}
}
-impl<'ty, T> HasAnnot<ManualAnnot<'ty>> for T {
+impl<'ty, T> OptionalAnnot<ManualAnnot<'ty>> for T {
fn get_annot(a: &ManualAnnot<'ty>) -> Option<SimpleType> {
Some(a.0.clone())
}
}
-impl<T: StaticType> HasAnnot<StaticAnnot> for T {
+impl<T: StaticType> OptionalAnnot<StaticAnnot> for T {
fn get_annot(_: &StaticAnnot) -> Option<SimpleType> {
Some(T::static_type())
}
@@ -252,7 +252,7 @@ impl<'a, A> Deserializer<'a, A> {
fn _parse<T>(&self) -> dhall::error::Result<Value>
where
- T: HasAnnot<A>,
+ T: OptionalAnnot<A>,
{
let parsed = match &self.source {
Source::Str(s) => Parsed::parse_str(s)?,
@@ -287,7 +287,7 @@ impl<'a, A> Deserializer<'a, A> {
/// [`StaticType`]: trait.StaticType.html
pub fn parse<T>(&self) -> Result<T>
where
- T: FromDhall + HasAnnot<A>,
+ T: FromDhall + OptionalAnnot<A>,
{
let val = self
._parse::<T>()
diff --git a/serde_dhall/src/options/mod.rs b/serde_dhall/src/options/mod.rs
new file mode 100644
index 0000000..384f318
--- /dev/null
+++ b/serde_dhall/src/options/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod de;
+pub(crate) mod ser;
diff --git a/serde_dhall/src/options/ser.rs b/serde_dhall/src/options/ser.rs
new file mode 100644
index 0000000..026dd21
--- /dev/null
+++ b/serde_dhall/src/options/ser.rs
@@ -0,0 +1,67 @@
+use crate::{Result, SimpleType, StaticType, ToDhall};
+
+#[derive(Debug, Clone, Copy)]
+pub struct NoAnnot;
+#[derive(Debug, Clone, Copy)]
+pub struct ManualAnnot<'ty>(&'ty SimpleType);
+#[derive(Debug, Clone, Copy)]
+pub struct StaticAnnot;
+
+pub trait RequiredAnnot<A> {
+ fn get_annot(a: &A) -> SimpleType;
+}
+impl<'ty, T> RequiredAnnot<ManualAnnot<'ty>> for T {
+ fn get_annot(a: &ManualAnnot<'ty>) -> SimpleType {
+ a.0.clone()
+ }
+}
+impl<T: StaticType> RequiredAnnot<StaticAnnot> for T {
+ fn get_annot(_: &StaticAnnot) -> SimpleType {
+ T::static_type()
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Serializer<'a, T, A> {
+ data: &'a T,
+ annot: A,
+}
+
+impl<'a, T> Serializer<'a, T, NoAnnot> {
+ pub fn type_annotation<'ty>(
+ self,
+ ty: &'ty SimpleType,
+ ) -> Serializer<'a, T, ManualAnnot<'ty>> {
+ Serializer {
+ annot: ManualAnnot(ty),
+ data: self.data,
+ }
+ }
+
+ pub fn static_type_annotation(self) -> Serializer<'a, T, StaticAnnot> {
+ Serializer {
+ annot: StaticAnnot,
+ data: self.data,
+ }
+ }
+}
+
+impl<'a, T, A> Serializer<'a, T, A> {
+ pub fn to_string(&self) -> Result<String>
+ where
+ T: ToDhall + RequiredAnnot<A>,
+ {
+ let val = self.data.to_dhall(&T::get_annot(&self.annot))?;
+ Ok(val.to_string())
+ }
+}
+
+pub fn serialize<'a, T>(data: &'a T) -> Serializer<'a, T, NoAnnot>
+where
+ T: ToDhall,
+{
+ Serializer {
+ data,
+ annot: NoAnnot,
+ }
+}
diff --git a/serde_dhall/src/serialize.rs b/serde_dhall/src/serialize.rs
new file mode 100644
index 0000000..dd3e426
--- /dev/null
+++ b/serde_dhall/src/serialize.rs
@@ -0,0 +1,312 @@
+use serde::ser;
+use std::collections::BTreeMap;
+
+use dhall::syntax::NumKind;
+
+use crate::value::SimpleValue;
+use crate::{Error, ErrorKind, Result, SimpleType, Value};
+use SimpleValue::*;
+
+pub trait Sealed {}
+
+pub trait ToDhall: Sealed {
+ #[doc(hidden)]
+ fn to_dhall(&self, ty: &SimpleType) -> Result<Value>;
+}
+
+impl<T> Sealed for T where T: ser::Serialize {}
+
+impl<T> ToDhall for T
+where
+ T: ser::Serialize,
+{
+ fn to_dhall(&self, ty: &SimpleType) -> Result<Value> {
+ let sval: SimpleValue = self.serialize(Serializer)?;
+ sval.into_value(ty)
+ }
+}
+
+#[derive(Default, Clone, Copy)]
+struct Serializer;
+
+impl ser::Serializer for Serializer {
+ type Ok = SimpleValue;
+ type Error = Error;
+
+ type SerializeSeq = SeqSerializer;
+ type SerializeTuple = TupleSerializer;
+ type SerializeTupleStruct = ser::Impossible<Self::Ok, Self::Error>;
+ type SerializeTupleVariant = ser::Impossible<Self::Ok, Self::Error>;
+ type SerializeMap = MapSerializer;
+ type SerializeStruct = StructSerializer;
+ type SerializeStructVariant = ser::Impossible<Self::Ok, Self::Error>;
+
+ fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
+ Ok(Num(NumKind::Bool(v)))
+ }
+
+ fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
+ self.serialize_i64(i64::from(v))
+ }
+ fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
+ self.serialize_i64(i64::from(v))
+ }
+ fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
+ self.serialize_i64(i64::from(v))
+ }
+ fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
+ Ok(Num(NumKind::Integer(v)))
+ }
+
+ fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
+ self.serialize_u64(u64::from(v))
+ }
+ fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
+ self.serialize_u64(u64::from(v))
+ }
+ fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
+ self.serialize_u64(u64::from(v))
+ }
+ fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
+ Ok(Num(NumKind::Natural(v)))
+ }
+
+ fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
+ self.serialize_f64(f64::from(v))
+ }
+ fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
+ Ok(Num(NumKind::Double(v.into())))
+ }
+
+ fn serialize_char(self, v: char) -> Result<Self::Ok> {
+ self.serialize_str(&v.to_string())
+ }
+ fn serialize_str(self, v: &str) -> Result<Self::Ok> {
+ Ok(Text(v.to_owned()))
+ }
+
+ fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok> {
+ Err(ErrorKind::Serialize(
+ "Unsupported data for serialization: byte array".to_owned(),
+ )
+ .into())
+ }
+
+ fn serialize_none(self) -> Result<Self::Ok> {
+ Ok(Optional(None))
+ }
+ fn serialize_some<T>(self, v: &T) -> Result<Self::Ok>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ Ok(Optional(Some(Box::new(v.serialize(self)?))))
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok> {
+ Ok(Record(Default::default()))
+ }
+
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
+ self.serialize_unit()
+ }
+ fn serialize_newtype_struct<T>(
+ self,
+ _name: &'static str,
+ _value: &T,
+ ) -> Result<Self::Ok>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ Err(ErrorKind::Serialize(
+ "Unsupported data for serialization: newtype struct".to_owned(),
+ )
+ .into())
+ }
+ fn serialize_struct(
+ self,
+ _name: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeStruct> {
+ Ok(StructSerializer::default())
+ }
+
+ fn serialize_unit_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ ) -> Result<Self::Ok> {
+ Ok(Union(variant.to_owned(), None))
+ }
+ fn serialize_newtype_variant<T>(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ value: &T,
+ ) -> Result<Self::Ok>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ let value = value.serialize(self)?;
+ Ok(Union(variant.to_owned(), Some(Box::new(value))))
+ }
+ fn serialize_tuple_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeTupleVariant> {
+ Err(ErrorKind::Serialize(
+ "Unsupported data for serialization: tuple variant".to_owned(),
+ )
+ .into())
+ }
+ fn serialize_struct_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ _variant: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeStructVariant> {
+ Err(ErrorKind::Serialize(
+ "Unsupported data for serialization: struct variant".to_owned(),
+ )
+ .into())
+ }
+
+ fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
+ Ok(TupleSerializer::default())
+ }
+ fn serialize_tuple_struct(
+ self,
+ _name: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeTupleStruct> {
+ Err(ErrorKind::Serialize(
+ "Unsupported data for serialization: tuple struct".to_owned(),
+ )
+ .into())
+ }
+
+ fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
+ Ok(SeqSerializer::default())
+ }
+
+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
+ Ok(MapSerializer::default())
+ }
+}
+
+#[derive(Default)]
+struct SeqSerializer(Vec<SimpleValue>);
+
+impl ser::SerializeSeq for SeqSerializer {
+ type Ok = SimpleValue;
+ type Error = Error;
+
+ fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ self.0.push(value.serialize(Serializer)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ Ok(List(self.0))
+ }
+}
+
+#[derive(Default)]
+struct TupleSerializer(Vec<SimpleValue>);
+
+impl ser::SerializeTuple for TupleSerializer {
+ type Ok = SimpleValue;
+ type Error = Error;
+
+ fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ self.0.push(value.serialize(Serializer)?);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ Ok(Record(
+ self.0
+ .into_iter()
+ .enumerate()
+ .map(|(i, x)| (format!("_{}", i + 1), x))
+ .collect(),
+ ))
+ }
+}
+
+#[derive(Default)]
+struct MapSerializer {
+ map: BTreeMap<String, SimpleValue>,
+ key: Option<String>,
+ val: Option<SimpleValue>,
+}
+
+impl ser::SerializeMap for MapSerializer {
+ type Ok = SimpleValue;
+ type Error = Error;
+
+ fn serialize_key<T>(&mut self, key: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ let key = match key.serialize(Serializer)? {
+ Text(key) => key,
+ _ => return Err(<Error as ser::Error>::custom("not a string")),
+ };
+ if let Some(val) = self.val.take() {
+ self.map.insert(key, val);
+ } else {
+ self.key = Some(key);
+ }
+ Ok(())
+ }
+
+ fn serialize_value<T>(&mut self, val: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ let val: SimpleValue = val.serialize(Serializer)?;
+ if let Some(key) = self.key.take() {
+ self.map.insert(key, val);
+ } else {
+ self.val = Some(val);
+ }
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ Ok(Record(self.map))
+ }
+}
+
+#[derive(Default)]
+struct StructSerializer(BTreeMap<String, SimpleValue>);
+
+impl ser::SerializeStruct for StructSerializer {
+ type Ok = SimpleValue;
+ type Error = Error;
+
+ fn serialize_field<T>(&mut self, key: &'static str, val: &T) -> Result<()>
+ where
+ T: ?Sized + ser::Serialize,
+ {
+ let val: SimpleValue = val.serialize(Serializer)?;
+ self.0.insert(key.into(), val);
+ Ok(())
+ }
+
+ fn end(self) -> Result<Self::Ok> {
+ Ok(Record(self.0))
+ }
+}
diff --git a/serde_dhall/src/static_type.rs b/serde_dhall/src/static_type.rs
index 3c5da18..7e6c27c 100644
--- a/serde_dhall/src/static_type.rs
+++ b/serde_dhall/src/static_type.rs
@@ -103,6 +103,26 @@ derive_builtin!(i32, Integer);
derive_builtin!(f64, Double);
derive_builtin!(f32, Double);
derive_builtin!(String, Text);
+derive_builtin!(&str, Text);
+
+impl StaticType for () {
+ fn static_type() -> SimpleType {
+ SimpleType::Record(vec![].into_iter().collect())
+ }
+}
+
+impl<A> StaticType for (A,)
+where
+ A: StaticType,
+{
+ fn static_type() -> SimpleType {
+ SimpleType::Record(
+ vec![("_1".to_owned(), A::static_type())]
+ .into_iter()
+ .collect(),
+ )
+ }
+}
impl<A, B> StaticType for (A, B)
where
@@ -121,6 +141,46 @@ where
}
}
+impl<A, B, C> StaticType for (A, B, C)
+where
+ A: StaticType,
+ B: StaticType,
+ C: StaticType,
+{
+ fn static_type() -> SimpleType {
+ SimpleType::Record(
+ vec![
+ ("_1".to_owned(), A::static_type()),
+ ("_2".to_owned(), B::static_type()),
+ ("_3".to_owned(), C::static_type()),
+ ]
+ .into_iter()
+ .collect(),
+ )
+ }
+}
+
+impl<A, B, C, D> StaticType for (A, B, C, D)
+where
+ A: StaticType,
+ B: StaticType,
+ C: StaticType,
+ D: StaticType,
+{
+ fn static_type() -> SimpleType {
+ SimpleType::Record(
+ vec![
+ ("_1".to_owned(), A::static_type()),
+ ("_2".to_owned(), B::static_type()),
+ ("_3".to_owned(), C::static_type()),
+ ("_4".to_owned(), D::static_type()),
+ ]
+ .into_iter()
+ .collect(),
+ )
+ }
+}
+
impl<T, E> StaticType for std::result::Result<T, E>
where
T: StaticType,
diff --git a/serde_dhall/src/value.rs b/serde_dhall/src/value.rs
index d7116d9..ca05658 100644
--- a/serde_dhall/src/value.rs
+++ b/serde_dhall/src/value.rs
@@ -6,7 +6,7 @@ use dhall::semantics::{Hir, HirKind, Nir, NirKind};
pub use dhall::syntax::NumKind;
use dhall::syntax::{Expr, ExprKind, Span};
-use crate::{Error, ErrorKind, FromDhall, Result, Sealed};
+use crate::{Error, ErrorKind, FromDhall, Result, ToDhall};
#[doc(hidden)]
/// An arbitrary Dhall value.
@@ -292,6 +292,94 @@ impl SimpleValue {
_ => return None,
})
}
+
+ fn to_hir(&self, ty: &SimpleType) -> Result<Hir> {
+ use SimpleType as T;
+ use SimpleValue as V;
+ let hir = |k| Hir::new(HirKind::Expr(k), Span::Artificial);
+ let type_error = |msg| Error(ErrorKind::Serialize(msg));
+ let kind = match (self, ty) {
+ (V::Num(num @ NumKind::Bool(_)), T::Bool)
+ | (V::Num(num @ NumKind::Natural(_)), T::Natural)
+ | (V::Num(num @ NumKind::Integer(_)), T::Integer)
+ | (V::Num(num @ NumKind::Double(_)), T::Double) => {
+ ExprKind::Num(num.clone())
+ }
+ (V::Text(v), T::Text) => ExprKind::TextLit(v.clone().into()),
+ (V::Optional(None), T::Optional(t)) => ExprKind::Op(OpKind::App(
+ hir(ExprKind::Builtin(Builtin::OptionalNone)),
+ t.to_hir(),
+ )),
+ (V::Optional(Some(v)), T::Optional(t)) => {
+ ExprKind::SomeLit(v.to_hir(t)?)
+ }
+ (V::List(v), T::List(t)) if v.is_empty() => {
+ ExprKind::EmptyListLit(hir(ExprKind::Op(OpKind::App(
+ hir(ExprKind::Builtin(Builtin::List)),
+ t.to_hir(),
+ ))))
+ }
+ (V::List(v), T::List(t)) => ExprKind::NEListLit(
+ v.iter().map(|v| v.to_hir(t)).collect::<Result<_>>()?,
+ ),
+ (V::Record(v), T::Record(t)) => ExprKind::RecordLit(
+ v.iter()
+ .map(|(k, v)| match t.get(k) {
+ Some(t) => Ok((k.clone().into(), v.to_hir(t)?)),
+ None => Err(type_error(format!(
+ "expected a value of type {}, found {:?}",
+ ty.to_hir().to_expr(Default::default()),
+ self
+ ))),
+ })
+ .collect::<Result<_>>()?,
+ ),
+ (V::Union(variant, Some(v)), T::Union(t)) => match t.get(variant) {
+ Some(Some(variant_t)) => ExprKind::Op(OpKind::App(
+ hir(ExprKind::Op(OpKind::Field(
+ ty.to_hir(),
+ variant.clone().into(),
+ ))),
+ v.to_hir(variant_t)?,
+ )),
+ _ => {
+ return Err(type_error(format!(
+ "expected a value of type {}, found {:?}",
+ ty.to_hir().to_expr(Default::default()),
+ self
+ )))
+ }
+ },
+ (V::Union(variant, None), T::Union(t)) => match t.get(variant) {
+ Some(None) => ExprKind::Op(OpKind::Field(
+ ty.to_hir(),
+ variant.clone().into(),
+ )),
+ _ => {
+ return Err(type_error(format!(
+ "expected a value of type {}, found {:?}",
+ ty.to_hir().to_expr(Default::default()),
+ self
+ )))
+ }
+ },
+ _ => {
+ return Err(type_error(format!(
+ "expected a value of type {}, found {:?}",
+ ty.to_hir().to_expr(Default::default()),
+ self
+ )))
+ }
+ };
+ Ok(hir(kind))
+ }
+ pub(crate) fn into_value(self, ty: &SimpleType) -> Result<Value> {
+ Ok(Value {
+ hir: self.to_hir(ty)?,
+ as_simple_val: Some(self),
+ as_simple_ty: None,
+ })
+ }
}
impl SimpleType {
@@ -376,8 +464,10 @@ impl SimpleType {
}
}
-impl Sealed for Value {}
-impl Sealed for SimpleType {}
+impl crate::deserialize::Sealed for Value {}
+impl crate::deserialize::Sealed for SimpleType {}
+impl crate::serialize::Sealed for Value {}
+impl crate::serialize::Sealed for SimpleValue {}
impl FromDhall for Value {
fn from_dhall(v: &Value) -> Result<Self> {
@@ -394,6 +484,16 @@ impl FromDhall for SimpleType {
})
}
}
+impl ToDhall for Value {
+ fn to_dhall(&self, _ty: &SimpleType) -> Result<Value> {
+ Ok(self.clone())
+ }
+}
+impl ToDhall for SimpleValue {
+ fn to_dhall(&self, ty: &SimpleType) -> Result<Value> {
+ self.clone().into_value(ty)
+ }
+}
impl Eq for Value {}
impl PartialEq for Value {