diff options
-rw-r--r-- | serde_dhall/src/options/de.rs | 37 | ||||
-rw-r--r-- | serde_dhall/tests/serde.rs | 70 |
2 files changed, 98 insertions, 9 deletions
diff --git a/serde_dhall/src/options/de.rs b/serde_dhall/src/options/de.rs index dcc6bac..4f7c346 100644 --- a/serde_dhall/src/options/de.rs +++ b/serde_dhall/src/options/de.rs @@ -1,5 +1,5 @@ -use std::path::{Path, PathBuf}; use std::collections::HashMap; +use std::path::{Path, PathBuf}; use dhall::{Ctxt, Parsed}; @@ -228,7 +228,7 @@ impl<'a, A> Deserializer<'a, A> { // self // } - /// Sets a Collection of names which should be substituted with + /// injects a collection of names which should be substituted with /// the given types, i.e. effectively adds built-in type variables /// which do not need to be imported within dhall. /// @@ -258,20 +258,43 @@ impl<'a, A> Deserializer<'a, A> { /// let data = "Newtype.Bar"; /// /// let deserialized = serde_dhall::from_str(data) - /// .substitute_names(substs) + /// .inject_types(substs) /// .parse::<Newtype>() /// .unwrap(); /// /// assert_eq!(deserialized, Newtype::Bar); /// /// ``` - pub fn substitute_names(self, substs: HashMap<String, SimpleType>) -> Self { + pub fn inject_types( + self, + tys: impl IntoIterator<Item = (String, SimpleType)>, + ) -> Self { Deserializer { - substitutions: substs - .iter() + substitutions: tys + .into_iter() .map(|(s, ty)| { - (dhall::syntax::Label::from_str(s), ty.to_expr()) + (dhall::syntax::Label::from_str(&s), ty.to_expr()) }) + .chain( + self.substitutions + .iter() + .map(|(n,t)| (n.clone(), t.clone())), + ) + .collect(), + ..self + } + } + + pub fn inject_single_type(self, name: String, ty: SimpleType) -> Self { + Deserializer { + substitutions: self + .substitutions + .iter() + .map(|(n,t)| (n.clone(),t.clone())) + .chain(std::iter::once(( + dhall::syntax::Label::from_str(&name), + ty.to_expr(), + ))) .collect(), ..self } diff --git a/serde_dhall/tests/serde.rs b/serde_dhall/tests/serde.rs index 99e4b8b..abf78e3 100644 --- a/serde_dhall/tests/serde.rs +++ b/serde_dhall/tests/serde.rs @@ -151,7 +151,73 @@ mod serde { } #[test] - fn substitutions() { + fn inject_single_type() { + #[derive(Debug, Clone, Deserialize, Serialize, StaticType, Eq, PartialEq)] + enum Foo { + X(u64), + Y(i64), + } + + assert_eq!(from_str("Foo.X 1") + .inject_single_type("Foo".to_string(), Foo::static_type()) + .static_type_annotation() + .parse::<Foo>() + .unwrap(), + Foo::X(1) + ) + } + + #[test] + fn chain_inject_type() { + #[derive(Debug, Clone, Deserialize, Serialize, StaticType, Eq, PartialEq)] + enum Bar { + A,B + } + #[derive(Debug, Clone, Deserialize, Serialize, StaticType, Eq, PartialEq)] + enum Foo { + X(Bar), + Y(i64), + } + + assert_eq!(from_str("Foo.X Bar.A") + .inject_single_type("Bar".to_string(), Bar::static_type()) + .inject_single_type("Foo".to_string(), Foo::static_type()) + .static_type_annotation() + .parse::<Foo>() + .unwrap(), + Foo::X(Bar::A) + ); + + let mut substs = collections::HashMap::new(); + substs.insert("Foo".to_string(), Foo::static_type()); + + assert_eq!(from_str("Foo.X Bar.A") + .inject_types(substs.clone()) + .inject_single_type("Bar".to_string(), Bar::static_type()) + .static_type_annotation() + .parse::<Foo>() + .unwrap(), + Foo::X(Bar::A) + ); + + + // check that in chained injects, later injects override earlier ones + substs.insert("Bar".to_string(), Foo::static_type()); + + assert_eq!(from_str("Foo.X Bar.A") + .inject_types(substs) + .inject_single_type("Bar".to_string(), Bar::static_type()) + .static_type_annotation() + .parse::<Foo>() + .unwrap(), + Foo::X(Bar::A) + ); + + + + } + #[test] + fn inject_types() { #[derive(Debug, Clone, Deserialize, Serialize, StaticType, Eq, PartialEq)] enum Foo { X(u64), @@ -162,7 +228,7 @@ mod serde { substs.insert("Foo".to_string(), Foo::static_type()); assert_eq!(from_str("Foo.X 1") - .substitute_names(substs) + .inject_types(substs) .static_type_annotation() .parse::<Foo>() .unwrap(), |