summaryrefslogtreecommitdiff
path: root/dhall
diff options
context:
space:
mode:
authorNadrieril2019-08-13 23:08:48 +0200
committerNadrieril2019-08-13 23:45:27 +0200
commitc600bae72198350b78fe19cf993b7f4c6f35225a (patch)
tree7986dc615d07a0a2d5b4ee5ff09a33164815ae5f /dhall
parent43094c8c52319aa82b03e73700ca1b5f65da13c6 (diff)
Implement Hash for ParsedSubExpr
Diffstat (limited to 'dhall')
-rw-r--r--dhall/src/phase/binary.rs41
-rw-r--r--dhall/src/phase/mod.rs16
2 files changed, 34 insertions, 23 deletions
diff --git a/dhall/src/phase/binary.rs b/dhall/src/phase/binary.rs
index b3a80aa..9ed823c 100644
--- a/dhall/src/phase/binary.rs
+++ b/dhall/src/phase/binary.rs
@@ -10,7 +10,7 @@ use dhall_syntax::{
};
use crate::error::{DecodeError, EncodeError};
-use crate::phase::{DecodedSubExpr, ParsedSubExpr};
+use crate::phase::DecodedSubExpr;
pub fn decode(data: &[u8]) -> Result<DecodedSubExpr, DecodeError> {
match serde_cbor::de::from_slice(data) {
@@ -19,7 +19,7 @@ pub fn decode(data: &[u8]) -> Result<DecodedSubExpr, DecodeError> {
}
}
-pub fn encode(expr: &ParsedSubExpr) -> Result<Vec<u8>, EncodeError> {
+pub fn encode<E>(expr: &SubExpr<E>) -> Result<Vec<u8>, EncodeError> {
serde_cbor::ser::to_vec(&Serialize::Expr(expr))
.map_err(|e| EncodeError::CBORError(e))
}
@@ -423,11 +423,11 @@ where
.collect::<Result<_, _>>()
}
-enum Serialize<'a> {
- Expr(&'a ParsedSubExpr),
+enum Serialize<'a, E> {
+ Expr(&'a SubExpr<E>),
CBOR(cbor::Value),
- RecordMap(&'a DupTreeMap<Label, ParsedSubExpr>),
- UnionMap(&'a DupTreeMap<Label, Option<ParsedSubExpr>>),
+ RecordMap(&'a DupTreeMap<Label, SubExpr<E>>),
+ UnionMap(&'a DupTreeMap<Label, Option<SubExpr<E>>>),
}
macro_rules! count {
@@ -447,7 +447,7 @@ macro_rules! ser_seq {
}};
}
-fn serialize_subexpr<S>(ser: S, e: &ParsedSubExpr) -> Result<S::Ok, S::Error>
+fn serialize_subexpr<S, E>(ser: S, e: &SubExpr<E>) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
@@ -457,21 +457,14 @@ where
use std::iter::once;
use self::Serialize::{RecordMap, UnionMap};
- fn expr(x: &ParsedSubExpr) -> self::Serialize<'_> {
+ fn expr<E>(x: &SubExpr<E>) -> self::Serialize<'_, E> {
self::Serialize::Expr(x)
}
- fn cbor<'a>(v: cbor::Value) -> self::Serialize<'a> {
- self::Serialize::CBOR(v)
- }
- fn tag<'a>(x: u64) -> self::Serialize<'a> {
- cbor(U64(x))
- }
- fn null<'a>() -> self::Serialize<'a> {
- cbor(cbor::Value::Null)
- }
- fn label<'a>(l: &Label) -> self::Serialize<'a> {
- cbor(cbor::Value::String(l.into()))
- }
+ let cbor =
+ |v: cbor::Value| -> self::Serialize<'_, E> { self::Serialize::CBOR(v) };
+ let tag = |x: u64| cbor(U64(x));
+ let null = || cbor(cbor::Value::Null);
+ let label = |l: &Label| cbor(cbor::Value::String(l.into()));
match e.as_ref() {
Const(c) => ser.serialize_str(&c.to_string()),
@@ -634,12 +627,14 @@ where
match &url.headers {
None => ser_seq.serialize_element(&Null)?,
Some(location_hashed) => {
- ser_seq.serialize_element(&self::Serialize::Expr(&rc(
+ let e = rc(
ExprF::Import(dhall_syntax::Import {
mode: ImportMode::Code,
location_hashed: location_hashed.as_ref().clone(),
}),
- )))?
+ );
+ let s: Serialize<'_, ()> = self::Serialize::Expr(&e);
+ ser_seq.serialize_element(&s)?
}
};
ser_seq.serialize_element(&url.authority)?;
@@ -665,7 +660,7 @@ where
ser_seq.end()
}
-impl<'a> serde::ser::Serialize for Serialize<'a> {
+impl<'a, E> serde::ser::Serialize for Serialize<'a, E> {
fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
diff --git a/dhall/src/phase/mod.rs b/dhall/src/phase/mod.rs
index a1e3f29..b73597c 100644
--- a/dhall/src/phase/mod.rs
+++ b/dhall/src/phase/mod.rs
@@ -157,6 +157,10 @@ impl Typed {
}
impl Normalized {
+ pub fn encode(&self) -> Result<Vec<u8>, EncodeError> {
+ crate::phase::binary::encode(&self.to_expr())
+ }
+
#[allow(dead_code)]
pub fn to_expr(&self) -> NormalizedSubExpr {
self.0.to_expr()
@@ -220,6 +224,18 @@ derive_traits_for_wrapper_struct!(Parsed);
derive_traits_for_wrapper_struct!(Resolved);
derive_traits_for_wrapper_struct!(Normalized);
+impl std::hash::Hash for Normalized {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: std::hash::Hasher,
+ {
+ match self.encode() {
+ Ok(vec) => vec.hash(state),
+ Err(_) => {}
+ }
+ }
+}
+
impl Eq for Typed {}
impl PartialEq for Typed {
fn eq(&self, other: &Self) -> bool {