summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <matthias.beyer@atos.net>2021-06-25 17:23:31 +0200
committerMatthias Beyer <matthias.beyer@atos.net>2021-09-16 12:31:45 +0200
commit2c0ad8a6c457a72e952f630c8993efb54c4d50cc (patch)
treea82f769bc98e0cfbb3f01919fe02c2980d2c2e2c
parent288b7860b2d216f5aefce252b3fe51928325ff33 (diff)
Add conditional dependency variant
This patch adds a conditional dependency variant to the build/runtime dependency deserialization type(s). Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
-rw-r--r--src/package/dependency/build.rs9
-rw-r--r--src/package/dependency/condition.rs67
-rw-r--r--src/package/dependency/mod.rs2
-rw-r--r--src/package/dependency/runtime.rs9
4 files changed, 79 insertions, 8 deletions
diff --git a/src/package/dependency/build.rs b/src/package/dependency/build.rs
index 78d3fad..42c0763 100644
--- a/src/package/dependency/build.rs
+++ b/src/package/dependency/build.rs
@@ -12,22 +12,25 @@ use anyhow::Result;
use serde::Deserialize;
use serde::Serialize;
-use crate::package::dependency::ParseDependency;
-use crate::package::dependency::StringEqual;
use crate::package::PackageName;
use crate::package::PackageVersionConstraint;
+use crate::package::dependency::ParseDependency;
+use crate::package::dependency::StringEqual;
+use crate::package::dependency::condition::Condition;
/// A dependency that is packaged and is only required during build time
#[derive(Serialize, Deserialize, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(untagged)]
pub enum BuildDependency {
Simple(String),
+ Conditional(String, Condition),
}
impl AsRef<str> for BuildDependency {
fn as_ref(&self) -> &str {
match self {
BuildDependency::Simple(name) => name,
+ BuildDependency::Conditional(name, _) => name,
}
}
}
@@ -36,6 +39,7 @@ impl StringEqual for BuildDependency {
fn str_equal(&self, s: &str) -> bool {
match self {
BuildDependency::Simple(name) => name == s,
+ BuildDependency::Conditional(name, _) => name == s,
}
}
}
@@ -61,6 +65,7 @@ mod tests {
let s: TestSetting = toml::from_str(r#"setting = "foo""#).expect("Parsing TestSetting failed");
match s.setting {
BuildDependency::Simple(name) => assert_eq!(name, "foo", "Expected 'foo', got {}", name),
+ other => panic!("Unexpected deserialization to other variant: {:?}", other),
}
}
}
diff --git a/src/package/dependency/condition.rs b/src/package/dependency/condition.rs
index df65a5c..9de498e 100644
--- a/src/package/dependency/condition.rs
+++ b/src/package/dependency/condition.rs
@@ -11,6 +11,7 @@
use std::collections::HashMap;
use serde::Deserialize;
+use serde::Serialize;
use crate::util::EnvironmentVariableName;
@@ -23,7 +24,7 @@ use crate::util::EnvironmentVariableName;
/// build image is used.
/// All these settings are optional, of course.
///
-#[derive(Deserialize, Clone, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
pub struct Condition {
#[serde(rename = "has_env", skip_serializing_if = "Option::is_none")]
has_env: Option<OneOrMore<EnvironmentVariableName>>,
@@ -35,11 +36,71 @@ pub struct Condition {
in_image: Option<OneOrMore<String>>,
}
+/// Manual implementation of PartialOrd for Condition
+///
+/// Because HashMap does not implement PartialOrd
+impl PartialOrd for Condition {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ use std::cmp::Ordering as O;
+
+ let cmp_has_env = match (self.has_env.as_ref(), other.has_env.as_ref()) {
+ (Some(a), Some(b)) => a.partial_cmp(b),
+ (Some(_), None) => Some(O::Greater),
+ (None, Some(_)) => Some(O::Less),
+ (None, None) => Some(O::Equal),
+ };
+
+ if cmp_has_env.as_ref().map(|o| *o != O::Equal).unwrap_or(false) {
+ return cmp_has_env
+ }
+
+ let cmp_env_eq = match (self.env_eq.as_ref(), other.env_eq.as_ref()) {
+ // TODO: Is this safe? We ignore the HashMaps here and just say they are equal. They are most certainly not.
+ (Some(_), Some(_)) => Some(O::Equal),
+ (Some(_), None) => Some(O::Greater),
+ (None, Some(_)) => Some(O::Less),
+ (None, None) => Some(O::Equal),
+ };
+
+ if cmp_env_eq.as_ref().map(|o| *o != O::Equal).unwrap_or(false) {
+ return cmp_env_eq
+ }
+
+ match (self.in_image.as_ref(), other.in_image.as_ref()) {
+ (Some(a), Some(b)) => a.partial_cmp(b),
+ (Some(_), None) => Some(O::Greater),
+ (None, Some(_)) => Some(O::Less),
+ (None, None) => Some(O::Equal),
+ }
+ }
+}
+
+/// Manual implementation of Ord for Condition
+///
+/// Because HashMap does not implement Ord
+impl Ord for Condition {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ self.partial_cmp(other).unwrap_or(std::cmp::Ordering::Equal)
+ }
+}
+
+/// Manual implementation of Hash for Condition
+///
+/// Because HashMap does not implement Hash
+impl std::hash::Hash for Condition {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.has_env.hash(state);
+ if let Some(hm) = self.env_eq.as_ref() {
+ hm.iter().for_each(|(k, v)| (k, v).hash(state));
+ };
+ self.in_image.hash(state);
+ }
+}
+
/// Helper type for supporting Vec<T> and T in value
/// position of Condition
-#[cfg_attr(test, derive(Eq, PartialEq))]
-#[derive(Deserialize, Clone, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(untagged)]
pub enum OneOrMore<T: Sized> {
One(T),
diff --git a/src/package/dependency/mod.rs b/src/package/dependency/mod.rs
index 8195dd1..e55dfc2 100644
--- a/src/package/dependency/mod.rs
+++ b/src/package/dependency/mod.rs
@@ -24,7 +24,7 @@ pub use build::*;
mod runtime;
pub use runtime::*;
-mod condition;
+pub(self) mod condition;
pub trait StringEqual {
fn str_equal(&self, s: &str) -> bool;
diff --git a/src/package/dependency/runtime.rs b/src/package/dependency/runtime.rs
index 3916b22..26679e2 100644
--- a/src/package/dependency/runtime.rs
+++ b/src/package/dependency/runtime.rs
@@ -12,22 +12,25 @@ use anyhow::Result;
use serde::Deserialize;
use serde::Serialize;
-use crate::package::dependency::ParseDependency;
-use crate::package::dependency::StringEqual;
use crate::package::PackageName;
use crate::package::PackageVersionConstraint;
+use crate::package::dependency::ParseDependency;
+use crate::package::dependency::StringEqual;
+use crate::package::dependency::condition::Condition;
/// A dependency that is packaged and is required during runtime
#[derive(Serialize, Deserialize, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[serde(untagged)]
pub enum Dependency {
Simple(String),
+ Conditional(String, Condition),
}
impl AsRef<str> for Dependency {
fn as_ref(&self) -> &str {
match self {
Dependency::Simple(name) => name,
+ Dependency::Conditional(name, _) => name,
}
}
}
@@ -36,6 +39,7 @@ impl StringEqual for Dependency {
fn str_equal(&self, s: &str) -> bool {
match self {
Dependency::Simple(name) => name == s,
+ Dependency::Conditional(name, _) => name == s,
}
}
}
@@ -68,6 +72,7 @@ mod tests {
match s.setting {
Dependency::Simple(name) => assert_eq!(name, "foo", "Expected 'foo', got {}", name),
+ other => panic!("Unexpected deserialization to other variant: {:?}", other),
}
}
}