mck/value/
three_valued.rs

1use std::{
2    cmp::Ordering,
3    fmt::Display,
4    ops::{BitAnd, BitOr, BitXor, Not},
5};
6
7use serde::{Deserialize, Serialize};
8
9use crate::misc::Join;
10
11/// An extension of a Boolean to three-valued logic.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub enum ThreeValued {
14    // Known false.
15    False,
16    // Known true.
17    True,
18    // Either false or true, but it is unknown which one.
19    Unknown,
20}
21
22impl PartialOrd for ThreeValued {
23    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
24        Some(self.cmp(other))
25    }
26}
27
28impl Ord for ThreeValued {
29    fn cmp(&self, other: &Self) -> Ordering {
30        match (self, other) {
31            (ThreeValued::False, ThreeValued::False) => Ordering::Equal,
32            (ThreeValued::False, ThreeValued::Unknown) => Ordering::Less,
33            (ThreeValued::False, ThreeValued::True) => Ordering::Less,
34
35            (ThreeValued::Unknown, ThreeValued::False) => Ordering::Greater,
36            (ThreeValued::Unknown, ThreeValued::Unknown) => Ordering::Equal,
37            (ThreeValued::Unknown, ThreeValued::True) => Ordering::Less,
38
39            (ThreeValued::True, ThreeValued::False) => Ordering::Greater,
40            (ThreeValued::True, ThreeValued::Unknown) => Ordering::Greater,
41            (ThreeValued::True, ThreeValued::True) => Ordering::Equal,
42        }
43    }
44}
45
46impl ThreeValued {
47    /// Whether the value is unknown, i.e. neither false nor true.
48    pub fn is_unknown(&self) -> bool {
49        matches!(self, ThreeValued::Unknown)
50    }
51
52    /// Whether the value is known, i.e. false or true.
53    pub fn is_known(&self) -> bool {
54        !self.is_unknown()
55    }
56
57    /// Whether the value is definitely false.
58    pub fn is_false(&self) -> bool {
59        matches!(self, ThreeValued::False)
60    }
61
62    /// Whether the value is definitely true.
63    pub fn is_true(&self) -> bool {
64        matches!(self, ThreeValued::True)
65    }
66
67    pub fn from_bool(value: bool) -> ThreeValued {
68        if value {
69            ThreeValued::True
70        } else {
71            ThreeValued::False
72        }
73    }
74}
75
76impl Not for ThreeValued {
77    type Output = Self;
78
79    fn not(self) -> Self {
80        match self {
81            ThreeValued::False => ThreeValued::True,
82            ThreeValued::True => ThreeValued::False,
83            ThreeValued::Unknown => ThreeValued::Unknown,
84        }
85    }
86}
87
88impl BitAnd for ThreeValued {
89    type Output = Self;
90
91    fn bitand(self, rhs: Self) -> Self::Output {
92        match (self, rhs) {
93            (ThreeValued::False, _) => ThreeValued::False,
94            (_, ThreeValued::False) => ThreeValued::False,
95            (ThreeValued::Unknown, _) => ThreeValued::Unknown,
96            (_, ThreeValued::Unknown) => ThreeValued::Unknown,
97            (ThreeValued::True, ThreeValued::True) => ThreeValued::True,
98        }
99    }
100}
101
102impl BitOr for ThreeValued {
103    type Output = Self;
104
105    fn bitor(self, rhs: Self) -> Self::Output {
106        match (self, rhs) {
107            (ThreeValued::True, _) => ThreeValued::True,
108            (_, ThreeValued::True) => ThreeValued::True,
109            (ThreeValued::Unknown, _) => ThreeValued::Unknown,
110            (_, ThreeValued::Unknown) => ThreeValued::Unknown,
111            (ThreeValued::False, ThreeValued::False) => ThreeValued::False,
112        }
113    }
114}
115
116impl BitXor for ThreeValued {
117    type Output = Self;
118
119    fn bitxor(self, rhs: Self) -> Self::Output {
120        match (self, rhs) {
121            (ThreeValued::True, ThreeValued::True) | (ThreeValued::False, ThreeValued::False) => {
122                ThreeValued::False
123            }
124            (ThreeValued::True, ThreeValued::False) | (ThreeValued::False, ThreeValued::True) => {
125                ThreeValued::True
126            }
127            _ => ThreeValued::Unknown,
128        }
129    }
130}
131
132impl Join for ThreeValued {
133    fn join(self, rhs: &Self) -> Self {
134        match (self, rhs) {
135            (ThreeValued::False, ThreeValued::False) => ThreeValued::False,
136            (ThreeValued::True, ThreeValued::True) => ThreeValued::True,
137            (ThreeValued::False, ThreeValued::True) | (ThreeValued::True, ThreeValued::False) => {
138                ThreeValued::Unknown
139            }
140            (ThreeValued::Unknown, _) | (_, ThreeValued::Unknown) => ThreeValued::Unknown,
141        }
142    }
143}
144
145impl Display for ThreeValued {
146    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147        let str = match self {
148            ThreeValued::False => "false",
149            ThreeValued::True => "true",
150            ThreeValued::Unknown => "unknown",
151        };
152        write!(f, "{}", str)
153    }
154}