selectors/
kleene_value.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Kleen logic: https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics
6
7/// A "trilean" value based on Kleen logic.
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub enum KleeneValue {
10    /// False
11    False = 0,
12    /// True
13    True = 1,
14    /// Either true or false, but we’re not sure which yet.
15    Unknown,
16}
17
18impl From<bool> for KleeneValue {
19    fn from(b: bool) -> Self {
20        if b {
21            Self::True
22        } else {
23            Self::False
24        }
25    }
26}
27
28impl KleeneValue {
29    /// Turns this Kleene value to a bool, taking the unknown value as an
30    /// argument.
31    pub fn to_bool(self, unknown: bool) -> bool {
32        match self {
33            Self::True => true,
34            Self::False => false,
35            Self::Unknown => unknown,
36        }
37    }
38
39    /// Return true if any result of f() is definitely true.
40    /// Otherwise, return the `or` of all values.
41    /// Returns false if empty, like that of `Iterator`.
42    #[inline(always)]
43    pub fn any<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) -> Self) -> Self {
44        Self::any_value(iter, Self::True, Self::False, |a, b| a | b, f)
45    }
46
47    /// Return false if any results of f() is definitely false.
48    /// Otherwise, return the `and` of all values.
49    /// Returns true if empty, opposite of `Iterator`.
50    #[inline(always)]
51    pub fn any_false<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) -> Self) -> Self {
52        Self::any_value(iter, Self::False, Self::True, |a, b| a & b, f)
53    }
54
55    #[inline(always)]
56    fn any_value<T>(
57        iter: impl Iterator<Item = T>,
58        value: Self,
59        on_empty: Self,
60        op: impl Fn(Self, Self) -> Self,
61        mut f: impl FnMut(T) -> Self,
62    ) -> Self {
63        let mut result = None;
64        for item in iter {
65            let r = f(item);
66            if r == value {
67                return r;
68            }
69            if let Some(v) = result.as_mut() {
70                *v = op(*v, r);
71            } else {
72                result = Some(r);
73            }
74        }
75        result.unwrap_or(on_empty)
76    }
77}
78
79impl std::ops::Not for KleeneValue {
80    type Output = Self;
81
82    fn not(self) -> Self {
83        match self {
84            Self::True => Self::False,
85            Self::False => Self::True,
86            Self::Unknown => Self::Unknown,
87        }
88    }
89}
90
91// Implements the logical and operation.
92impl std::ops::BitAnd for KleeneValue {
93    type Output = Self;
94
95    fn bitand(self, other: Self) -> Self {
96        if self == Self::False || other == Self::False {
97            return Self::False;
98        }
99        if self == Self::Unknown || other == Self::Unknown {
100            return Self::Unknown;
101        }
102        Self::True
103    }
104}
105
106// Implements the logical or operation.
107impl std::ops::BitOr for KleeneValue {
108    type Output = Self;
109
110    fn bitor(self, other: Self) -> Self {
111        if self == Self::True || other == Self::True {
112            return Self::True;
113        }
114        if self == Self::Unknown || other == Self::Unknown {
115            return Self::Unknown;
116        }
117        Self::False
118    }
119}
120
121impl std::ops::BitOrAssign for KleeneValue {
122    fn bitor_assign(&mut self, other: Self) {
123        *self = *self | other;
124    }
125}
126
127impl std::ops::BitAndAssign for KleeneValue {
128    fn bitand_assign(&mut self, other: Self) {
129        *self = *self & other;
130    }
131}