diff --git a/CHANGELOG.md b/CHANGELOG.md index 369b33a57..15aa894d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ UNRELEASED =================== * see https://github.com/kube-rs/kube-rs/compare/0.63.0...master + * `kube::runtime::wait::Condition` added boolean combinators (`not`/`and`/`or`) - #678 0.63.0 / 2021-10-26 =================== diff --git a/kube-runtime/src/wait.rs b/kube-runtime/src/wait.rs index 20fca6b93..24826b99e 100644 --- a/kube-runtime/src/wait.rs +++ b/kube-runtime/src/wait.rs @@ -87,6 +87,63 @@ where /// ``` pub trait Condition { fn matches_object(&self, obj: Option<&K>) -> bool; + + /// Returns a `Condition` that holds if `self` does not + /// + /// # Usage + /// + /// ```rust + /// # use kube_runtime::wait::Condition; + /// let condition: fn(Option<&()>) -> bool = |_| true; + /// assert!(condition.matches_object(None)); + /// assert!(!condition.not().matches_object(None)); + /// ``` + fn not(self) -> conditions::Not + where + Self: Sized, + { + conditions::Not(self) + } + + /// Returns a `Condition` that holds if `self` and `other` both do + /// + /// # Usage + /// + /// ```rust + /// # use kube_runtime::wait::Condition; + /// let cond_false: fn(Option<&()>) -> bool = |_| false; + /// let cond_true: fn(Option<&()>) -> bool = |_| true; + /// assert!(!cond_false.and(cond_false).matches_object(None)); + /// assert!(!cond_false.and(cond_true).matches_object(None)); + /// assert!(!cond_true.and(cond_false).matches_object(None)); + /// assert!(cond_true.and(cond_true).matches_object(None)); + /// ``` + fn and>(self, other: Other) -> conditions::And + where + Self: Sized, + { + conditions::And(self, other) + } + + /// Returns a `Condition` that holds if either `self` or `other` does + /// + /// # Usage + /// + /// ```rust + /// # use kube_runtime::wait::Condition; + /// let cond_false: fn(Option<&()>) -> bool = |_| false; + /// let cond_true: fn(Option<&()>) -> bool = |_| true; + /// assert!(!cond_false.or(cond_false).matches_object(None)); + /// assert!(cond_false.or(cond_true).matches_object(None)); + /// assert!(cond_true.or(cond_false).matches_object(None)); + /// assert!(cond_true.or(cond_true).matches_object(None)); + /// ``` + fn or>(self, other: Other) -> conditions::Or + where + Self: Sized, + { + conditions::Or(self, other) + } } impl) -> bool> Condition for F { @@ -134,6 +191,41 @@ pub mod conditions { false } } + + /// See [`Condition::not`] + #[derive(Copy, Clone, Debug, PartialEq, Eq)] + pub struct Not(pub(super) A); + impl, K> Condition for Not { + fn matches_object(&self, obj: Option<&K>) -> bool { + !self.0.matches_object(obj) + } + } + + /// See [`Condition::and`] + #[derive(Copy, Clone, Debug, PartialEq, Eq)] + pub struct And(pub(super) A, pub(super) B); + impl Condition for And + where + A: Condition, + B: Condition, + { + fn matches_object(&self, obj: Option<&K>) -> bool { + self.0.matches_object(obj) && self.1.matches_object(obj) + } + } + + /// See [`Condition::or`] + #[derive(Copy, Clone, Debug, PartialEq, Eq)] + pub struct Or(pub(super) A, pub(super) B); + impl Condition for Or + where + A: Condition, + B: Condition, + { + fn matches_object(&self, obj: Option<&K>) -> bool { + self.0.matches_object(obj) || self.1.matches_object(obj) + } + } } /// Utilities for deleting objects