Skip to main content

step_p21/primitive/
logical.rs

1use serde::{Deserialize, Serialize};
2use std::ops::*;
3
4/// `LOGICAL` type
5///
6/// ```
7/// use step_p21::primitive::Logical;
8///
9/// // Default
10/// assert_eq!(Logical::default(), Logical::Unknown);
11///
12/// // From<bool>
13/// assert_eq!(Logical::True, true.into());
14/// assert_eq!(Logical::False, false.into());
15///
16/// // From<Option<bool>>
17/// assert_eq!(Logical::True, Some(true).into());
18/// assert_eq!(Logical::False, Some(false).into());
19/// assert_eq!(Logical::Unknown, None.into());
20///
21/// // Not
22/// assert_eq!(Logical::True, !Logical::False);
23/// assert_eq!(Logical::False, !Logical::True);
24/// assert_eq!(Logical::Unknown, !Logical::Unknown);
25///
26/// // BitAnd
27/// assert_eq!(Logical::True & Logical::True, Logical::True);
28/// assert_eq!(Logical::True & Logical::Unknown, Logical::Unknown);
29/// assert_eq!(Logical::True & Logical::False, Logical::False);
30/// assert_eq!(Logical::False & Logical::True, Logical::False);
31/// assert_eq!(Logical::False & Logical::Unknown, Logical::False);
32/// assert_eq!(Logical::False & Logical::False, Logical::False);
33/// assert_eq!(Logical::Unknown & Logical::True, Logical::Unknown);
34/// assert_eq!(Logical::Unknown & Logical::Unknown, Logical::Unknown);
35/// assert_eq!(Logical::Unknown & Logical::False, Logical::False);
36///
37/// // BitOr
38/// assert_eq!(Logical::True | Logical::True, Logical::True);
39/// assert_eq!(Logical::True | Logical::Unknown, Logical::True);
40/// assert_eq!(Logical::True | Logical::False, Logical::True);
41/// assert_eq!(Logical::False | Logical::True, Logical::True);
42/// assert_eq!(Logical::False | Logical::Unknown, Logical::Unknown);
43/// assert_eq!(Logical::False | Logical::False, Logical::False);
44/// assert_eq!(Logical::Unknown | Logical::True, Logical::True);
45/// assert_eq!(Logical::Unknown | Logical::Unknown, Logical::Unknown);
46/// assert_eq!(Logical::Unknown | Logical::False, Logical::Unknown);
47///
48/// // BitXor
49/// assert_eq!(Logical::True ^ Logical::True, Logical::False);
50/// assert_eq!(Logical::True ^ Logical::Unknown, Logical::Unknown);
51/// assert_eq!(Logical::True ^ Logical::False, Logical::True);
52/// assert_eq!(Logical::False ^ Logical::True, Logical::True);
53/// assert_eq!(Logical::False ^ Logical::Unknown, Logical::Unknown);
54/// assert_eq!(Logical::False ^ Logical::False, Logical::False);
55/// assert_eq!(Logical::Unknown ^ Logical::True, Logical::Unknown);
56/// assert_eq!(Logical::Unknown ^ Logical::Unknown, Logical::Unknown);
57/// assert_eq!(Logical::Unknown ^ Logical::False, Logical::Unknown);
58/// ```
59#[derive(
60    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Default,
61)]
62pub enum Logical {
63    False,
64    /// Three-valued logic's third value, and the default: an unset `LOGICAL`
65    /// carries no information, which is not the same as being false.
66    #[default]
67    Unknown,
68    True,
69}
70
71impl std::fmt::Display for Logical {
72    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
73        match self {
74            Logical::True => f.pad("true"),
75            Logical::Unknown => f.pad("unknown"),
76            Logical::False => f.pad("false"),
77        }
78    }
79}
80
81impl From<bool> for Logical {
82    fn from(b: bool) -> Logical {
83        match b {
84            true => Logical::True,
85            false => Logical::False,
86        }
87    }
88}
89
90impl From<Option<bool>> for Logical {
91    fn from(option: Option<bool>) -> Logical {
92        match option {
93            Some(b) => b.into(),
94            None => Logical::Unknown,
95        }
96    }
97}
98
99impl From<Logical> for Option<bool> {
100    fn from(l: Logical) -> Option<bool> {
101        match l {
102            Logical::Unknown => None,
103            _ => Some(l == Logical::True),
104        }
105    }
106}
107
108impl BitAnd for Logical {
109    type Output = Self;
110
111    fn bitand(self, other: Self) -> Self {
112        match (self, other) {
113            (Logical::False, _) => Logical::False,
114            (_, Logical::False) => Logical::False,
115            (Logical::Unknown, _) => Logical::Unknown,
116            (_, Logical::Unknown) => Logical::Unknown,
117            (Logical::True, Logical::True) => Logical::True,
118        }
119    }
120}
121
122impl BitOr for Logical {
123    type Output = Self;
124
125    fn bitor(self, other: Self) -> Self {
126        match (self, other) {
127            (Logical::True, _) => Logical::True,
128            (_, Logical::True) => Logical::True,
129            (Logical::Unknown, _) => Logical::Unknown,
130            (_, Logical::Unknown) => Logical::Unknown,
131            (Logical::False, Logical::False) => Logical::False,
132        }
133    }
134}
135
136impl BitXor for Logical {
137    type Output = Logical;
138
139    fn bitxor(self, other: Self) -> Logical {
140        match (self, other) {
141            (Logical::Unknown, _) => Logical::Unknown,
142            (_, Logical::Unknown) => Logical::Unknown,
143            (_, _) => (self != other).into(),
144        }
145    }
146}
147
148impl Not for Logical {
149    type Output = Logical;
150
151    fn not(self) -> Logical {
152        match self {
153            Logical::True => Logical::False,
154            Logical::Unknown => Logical::Unknown,
155            Logical::False => Logical::True,
156        }
157    }
158}
159
160enum SubLogical {
161    T,
162    True,
163    F,
164    False,
165    U,
166    Unknown,
167}
168
169struct SubVisitor;
170
171const VARIANTS: &[&str] = &["T", "True", "F", "False", "U", "Unknown"];
172
173impl<'de> serde::de::Visitor<'de> for SubVisitor {
174    type Value = SubLogical;
175
176    fn expecting(
177        &self,
178        formatter: &mut std::fmt::Formatter,
179    ) -> std::fmt::Result {
180        write!(formatter, "Logical")
181    }
182
183    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
184    where
185        E: serde::de::Error,
186    {
187        match v {
188            "T" => Ok(SubLogical::T),
189            "True" => Ok(SubLogical::True),
190            "F" => Ok(SubLogical::F),
191            "False" => Ok(SubLogical::False),
192            "U" => Ok(SubLogical::U),
193            "Unknown" => Ok(SubLogical::Unknown),
194            _ => Err(E::unknown_field(v, VARIANTS)),
195        }
196    }
197
198    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
199    where
200        E: serde::de::Error,
201    {
202        match v {
203            b"T" => Ok(SubLogical::T),
204            b"True" => Ok(SubLogical::True),
205            b"F" => Ok(SubLogical::F),
206            b"False" => Ok(SubLogical::False),
207            b"U" => Ok(SubLogical::U),
208            b"Unknown" => Ok(SubLogical::Unknown),
209            _ => Err(E::unknown_field(&String::from_utf8_lossy(v), VARIANTS)),
210        }
211    }
212}
213
214impl From<SubLogical> for Logical {
215    fn from(value: SubLogical) -> Self {
216        match value {
217            SubLogical::T => Self::True,
218            SubLogical::True => Self::True,
219            SubLogical::F => Self::False,
220            SubLogical::False => Self::False,
221            SubLogical::U => Self::Unknown,
222            SubLogical::Unknown => Self::Unknown,
223        }
224    }
225}
226
227impl<'de> Deserialize<'de> for SubLogical {
228    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
229    where
230        D: serde::Deserializer<'de>,
231    {
232        deserializer.deserialize_identifier(SubVisitor)
233    }
234}
235
236#[derive(Clone, Debug)]
237struct Visitor;
238
239impl<'de> serde::de::Visitor<'de> for Visitor {
240    type Value = Logical;
241
242    fn expecting(
243        &self,
244        formatter: &mut std::fmt::Formatter,
245    ) -> std::fmt::Result {
246        write!(formatter, "enum Logical")
247    }
248
249    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
250    where
251        A: serde::de::EnumAccess<'de>,
252    {
253        data.variant::<SubLogical>().map(|(x, _)| x.into())
254    }
255}
256
257impl<'de> Deserialize<'de> for Logical {
258    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
259    where
260        D: serde::Deserializer<'de>,
261    {
262        deserializer.deserialize_enum("SubLogical", VARIANTS, Visitor)
263    }
264}