Skip to main content

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 { Self::True } else { Self::False }
21    }
22}
23
24impl KleeneValue {
25    /// Turns this Kleene value to a bool, taking the unknown value as an
26    /// argument.
27    pub fn to_bool(self, unknown: bool) -> bool {
28        match self {
29            Self::True => true,
30            Self::False => false,
31            Self::Unknown => unknown,
32        }
33    }
34
35    /// Return true if any result of f() is definitely true.
36    /// Otherwise, return the `or` of all values.
37    /// Returns false if empty, like that of `Iterator`.
38    #[inline(always)]
39    pub fn any<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) -> Self) -> Self {
40        Self::any_value(iter, Self::True, Self::False, |a, b| a | b, f)
41    }
42
43    /// Return false if any results of f() is definitely false.
44    /// Otherwise, return the `and` of all values.
45    /// Returns true if empty, opposite of `Iterator`.
46    #[inline(always)]
47    pub fn any_false<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) -> Self) -> Self {
48        Self::any_value(iter, Self::False, Self::True, |a, b| a & b, f)
49    }
50
51    #[inline(always)]
52    fn any_value<T>(
53        iter: impl Iterator<Item = T>,
54        value: Self,
55        on_empty: Self,
56        op: impl Fn(Self, Self) -> Self,
57        mut f: impl FnMut(T) -> Self,
58    ) -> Self {
59        let mut result = None;
60        for item in iter {
61            let r = f(item);
62            if r == value {
63                return r;
64            }
65            if let Some(v) = result.as_mut() {
66                *v = op(*v, r);
67            } else {
68                result = Some(r);
69            }
70        }
71        result.unwrap_or(on_empty)
72    }
73}
74
75impl std::ops::Not for KleeneValue {
76    type Output = Self;
77
78    fn not(self) -> Self {
79        match self {
80            Self::True => Self::False,
81            Self::False => Self::True,
82            Self::Unknown => Self::Unknown,
83        }
84    }
85}
86
87// Implements the logical and operation.
88impl std::ops::BitAnd for KleeneValue {
89    type Output = Self;
90
91    fn bitand(self, other: Self) -> Self {
92        if self == Self::False || other == Self::False {
93            return Self::False;
94        }
95        if self == Self::Unknown || other == Self::Unknown {
96            return Self::Unknown;
97        }
98        Self::True
99    }
100}
101
102// Implements the logical or operation.
103impl std::ops::BitOr for KleeneValue {
104    type Output = Self;
105
106    fn bitor(self, other: Self) -> Self {
107        if self == Self::True || other == Self::True {
108            return Self::True;
109        }
110        if self == Self::Unknown || other == Self::Unknown {
111            return Self::Unknown;
112        }
113        Self::False
114    }
115}
116
117impl std::ops::BitOrAssign for KleeneValue {
118    fn bitor_assign(&mut self, other: Self) {
119        *self = *self | other;
120    }
121}
122
123impl std::ops::BitAndAssign for KleeneValue {
124    fn bitand_assign(&mut self, other: Self) {
125        *self = *self & other;
126    }
127}