machine_check_common/value/
three_valued.rs

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