summaryrefslogtreecommitdiffstats
path: root/servo/components/selectors/kleene_value.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--servo/components/selectors/kleene_value.rs131
1 files changed, 131 insertions, 0 deletions
diff --git a/servo/components/selectors/kleene_value.rs b/servo/components/selectors/kleene_value.rs
new file mode 100644
index 0000000000..58141c1156
--- /dev/null
+++ b/servo/components/selectors/kleene_value.rs
@@ -0,0 +1,131 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+//! Kleen logic: https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics
+
+/// A "trilean" value based on Kleen logic.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum KleeneValue {
+ /// False
+ False = 0,
+ /// True
+ True = 1,
+ /// Either true or false, but we’re not sure which yet.
+ Unknown,
+}
+
+impl From<bool> for KleeneValue {
+ fn from(b: bool) -> Self {
+ if b {
+ Self::True
+ } else {
+ Self::False
+ }
+ }
+}
+
+impl KleeneValue {
+ /// Turns this Kleene value to a bool, taking the unknown value as an
+ /// argument.
+ pub fn to_bool(self, unknown: bool) -> bool {
+ match self {
+ Self::True => true,
+ Self::False => false,
+ Self::Unknown => unknown,
+ }
+ }
+
+ /// Return true if any result of f() is true. Otherwise, return the strongest value seen.
+ /// Returns false if empty, like that of `Iterator`.
+ pub fn any<T>(
+ iter: impl Iterator<Item = T>,
+ f: impl FnMut(T) -> Self,
+ ) -> Self {
+ Self::any_value(iter, Self::True, Self::False, f)
+ }
+
+ /// Return false if any results of f() is false. Otherwise, return the strongest value seen.
+ /// Returns true if empty, opposite of `Iterator`.
+ pub fn any_false<T>(
+ iter: impl Iterator<Item = T>,
+ f: impl FnMut(T) -> Self,
+ ) -> Self {
+ Self::any_value(iter, Self::False, Self::True, f)
+ }
+
+ fn any_value<T>(
+ iter: impl Iterator<Item = T>,
+ value: Self,
+ on_empty: Self,
+ mut f: impl FnMut(T) -> Self,
+ ) -> Self {
+ let mut result = None;
+ for item in iter {
+ let r = f(item);
+ if r == value {
+ return r;
+ }
+ if let Some(v) = result.as_mut() {
+ *v = *v & r;
+ } else {
+ result = Some(r);
+ }
+ }
+ result.unwrap_or(on_empty)
+ }
+}
+
+impl std::ops::Not for KleeneValue {
+ type Output = Self;
+
+ fn not(self) -> Self {
+ match self {
+ Self::True => Self::False,
+ Self::False => Self::True,
+ Self::Unknown => Self::Unknown,
+ }
+ }
+}
+
+// Implements the logical and operation.
+impl std::ops::BitAnd for KleeneValue {
+ type Output = Self;
+
+ fn bitand(self, other: Self) -> Self {
+ if self == Self::False || other == Self::False {
+ return Self::False;
+ }
+ if self == Self::Unknown || other == Self::Unknown {
+ return Self::Unknown;
+ }
+ Self::True
+ }
+}
+
+// Implements the logical or operation.
+impl std::ops::BitOr for KleeneValue {
+ type Output = Self;
+
+ fn bitor(self, other: Self) -> Self {
+ if self == Self::True || other == Self::True {
+ return Self::True;
+ }
+ if self == Self::Unknown || other == Self::Unknown {
+ return Self::Unknown;
+ }
+ Self::False
+ }
+}
+
+impl std::ops::BitOrAssign for KleeneValue {
+ fn bitor_assign(&mut self, other: Self) {
+ *self = *self | other;
+ }
+}
+
+impl std::ops::BitAndAssign for KleeneValue {
+ fn bitand_assign(&mut self, other: Self) {
+ *self = *self & other;
+ }
+}