summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstuebinm2021-05-02 00:33:31 +0200
committerstuebinm2021-05-02 00:36:45 +0200
commite65c53a8e22e2edf209a31ad28ba67ac5d78bed7 (patch)
tree3d6e17c5e121682e4b409b79dc2eba58494fc570
parenta0776173fabe05ed82e0283b55d85a2fffc511bf (diff)
substitute_names -> inject_types
This does three things: 1. rename the substitute_names function into inject_types, and makes it accept anything that implements IntoIterator instead of just HashMaps 2. adds an extra function to inject just a single type 3. makes these functions chainable; before, each call to substitute_names would discard previous invocations. However, this currently comes at the cost of a lot of ugly copying. also, more tests!
-rw-r--r--serde_dhall/src/options/de.rs37
-rw-r--r--serde_dhall/tests/serde.rs70
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(),