1#[cfg(feature = "serde")]
13mod serde;
14
15use std::fmt::{Display, Formatter, Result as FmtResult};
16use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
17use std::str::FromStr;
18
19#[derive(Debug, Clone, Copy, Hash)]
21pub enum Tribool {
22 True,
24 False,
26 Indeterminate,
28}
29
30pub use Tribool::{False, Indeterminate, True};
31
32impl Default for Tribool {
33 #[inline]
34 fn default() -> Tribool {
35 False
36 }
37}
38
39impl FromStr for Tribool {
40 type Err = ();
41
42 #[inline]
43 fn from_str(s: &str) -> Result<Tribool, ()> {
44 Ok(match bool::from_str(s) {
45 Ok(value) => Tribool::boolean(value),
46 _ => Indeterminate,
47 })
48 }
49}
50
51impl Tribool {
52 #[inline]
54 pub const fn boolean(value: bool) -> Tribool {
55 match value {
56 true => True,
57 false => False,
58 }
59 }
60
61 #[inline]
71 pub const fn is_true(self) -> bool {
72 match self {
73 True => true,
74 _ => false,
75 }
76 }
77
78 #[inline]
88 pub const fn is_false(self) -> bool {
89 match self {
90 False => true,
91 _ => false,
92 }
93 }
94
95 #[inline]
105 pub const fn is_indeterminate(self) -> bool {
106 match self {
107 Indeterminate => true,
108 _ => false,
109 }
110 }
111
112 #[inline]
125 pub const fn equals(self, rhs: Tribool) -> Tribool {
126 match (self, rhs) {
127 (False, False) | (True, True) => True,
128 (False, True) | (True, False) => False,
129 _ => Indeterminate,
130 }
131 }
132
133 #[inline]
146 pub const fn not_equals(self, rhs: Tribool) -> Tribool {
147 match (self, rhs) {
148 (False, False) | (True, True) => False,
149 (False, True) | (True, False) => True,
150 _ => Indeterminate,
151 }
152 }
153
154 #[inline]
158 pub const fn kleene_implication(self, b: Tribool) -> Tribool {
159 self.negate().or(b) }
161
162 #[inline]
169 pub fn lukasiewicz_implication(self, b: Tribool) -> Tribool {
170 match (self, b) {
171 (True, Indeterminate) | (Indeterminate, False) => Indeterminate,
172 (True, False) => False,
173 (False, False) => True,
174 (_, True) | (_, Indeterminate) => True,
175 }
176 }
177
178 #[inline]
180 pub const fn and(self, rhs: Tribool) -> Tribool {
181 match (self, rhs) {
182 (True, True) => True,
183 (False, _) | (_, False) => False,
184 _ => Indeterminate,
185 }
186 }
187
188 #[inline]
190 pub const fn or(self, rhs: Tribool) -> Tribool {
191 match (self, rhs) {
192 (False, False) => False,
193 (True, _) | (_, True) => True,
194 _ => Indeterminate,
195 }
196 }
197
198 #[inline]
200 pub const fn xor(self, rhs: Tribool) -> Tribool {
201 self.or(rhs).and(self.and(rhs).negate())
203 }
204
205 #[inline]
207 pub const fn negate(self) -> Tribool {
208 match self {
209 True => False,
210 False => True,
211 _ => Indeterminate,
212 }
213 }
214
215 #[inline]
219 pub const fn compare(self, rhs: Tribool) -> Option<Ordering> {
220 match (self, rhs) {
221 (Indeterminate, _) | (_, Indeterminate) => None,
222 (True, False) => Some(Ordering::Greater),
223 (False, True) => Some(Ordering::Less),
224 (True, True) | (False, False) => Some(Ordering::Equal),
225 }
226 }
227}
228
229impl Display for Tribool {
230 #[inline]
231 fn fmt(&self, f: &mut Formatter) -> FmtResult {
232 f.write_str(match self {
233 True => "True",
234 False => "False",
235 Indeterminate => "Indeterminate",
236 })
237 }
238}
239
240impl<B: Into<Tribool> + Copy> PartialEq<B> for Tribool {
241 #[inline]
242 fn eq(&self, rhs: &B) -> bool {
243 self.equals((*rhs).into()).is_true()
244 }
245
246 #[inline]
247 fn ne(&self, rhs: &B) -> bool {
248 self.not_equals((*rhs).into()).is_true()
249 }
250}
251
252impl PartialEq<Tribool> for bool {
253 #[inline]
254 fn eq(&self, rhs: &Tribool) -> bool {
255 *rhs == *self
256 }
257
258 #[inline]
259 fn ne(&self, rhs: &Tribool) -> bool {
260 *rhs != *self
261 }
262}
263
264use std::cmp::Ordering;
265
266impl<B: Into<Tribool> + Copy> PartialOrd<B> for Tribool {
267 #[inline]
268 fn partial_cmp(&self, rhs: &B) -> Option<Ordering> {
269 self.compare((*rhs).into())
270 }
271
272 #[inline]
273 fn lt(&self, rhs: &B) -> bool {
274 match (*self, (*rhs).into()) {
275 (False, True) => true,
276 _ => false,
277 }
278 }
279
280 #[inline]
281 fn le(&self, rhs: &B) -> bool {
282 match (*self, (*rhs).into()) {
283 (True, True) | (False, False) | (False, True) => true,
284 _ => false,
285 }
286 }
287
288 #[inline]
289 fn gt(&self, rhs: &B) -> bool {
290 match (*self, (*rhs).into()) {
291 (True, False) => true,
292 _ => false,
293 }
294 }
295
296 #[inline]
297 fn ge(&self, rhs: &B) -> bool {
298 match (*self, (*rhs).into()) {
299 (True, True) | (False, False) | (True, False) => true,
300 _ => false,
301 }
302 }
303}
304
305impl Not for Tribool {
306 type Output = Tribool;
307
308 #[inline]
309 fn not(self) -> Tribool {
310 self.negate()
311 }
312}
313
314impl<B: Into<Tribool>> BitAnd<B> for Tribool {
315 type Output = Tribool;
316
317 #[inline]
318 fn bitand(self, rhs: B) -> Tribool {
319 self.and(rhs.into())
320 }
321}
322
323impl<B: Into<Tribool>> BitOr<B> for Tribool {
324 type Output = Tribool;
325
326 #[inline]
327 fn bitor(self, rhs: B) -> Tribool {
328 self.or(rhs.into())
329 }
330}
331
332impl<B: Into<Tribool>> BitXor<B> for Tribool {
333 type Output = Tribool;
334
335 #[inline]
336 fn bitxor(self, rhs: B) -> Tribool {
337 self.xor(rhs.into())
338 }
339}
340
341macro_rules! impl_binary_op {
342 ($op:ident => $f:ident, $assign_op:ident => $af:ident) => {
343 impl $op<Tribool> for bool {
344 type Output = Tribool;
345
346 #[inline]
347 fn $f(self, rhs: Tribool) -> Tribool {
348 rhs.$f(self)
349 }
350 }
351
352 impl<B: Into<Tribool>> $assign_op<B> for Tribool {
353 #[inline]
354 fn $af(&mut self, rhs: B) {
355 *self = self.$f(rhs.into());
356 }
357 }
358
359 impl $assign_op<Tribool> for bool {
360 #[inline]
361 fn $af(&mut self, rhs: Tribool) {
362 *self = rhs.$f(*self).is_true()
363 }
364 }
365 };
366}
367
368impl_binary_op!(BitAnd => bitand, BitAndAssign => bitand_assign);
369impl_binary_op!(BitOr => bitor, BitOrAssign => bitor_assign);
370impl_binary_op!(BitXor => bitxor, BitXorAssign => bitxor_assign);
371
372impl From<bool> for Tribool {
373 #[inline]
374 fn from(value: bool) -> Tribool {
375 Tribool::boolean(value)
376 }
377}
378
379#[derive(Debug, Clone, Copy)]
381pub struct IndeterminateError;
382
383impl TryFrom<Tribool> for bool {
384 type Error = IndeterminateError;
385
386 #[inline]
387 fn try_from(value: Tribool) -> Result<Self, Self::Error> {
388 match value {
389 True => Ok(true),
390 False => Ok(false),
391 Indeterminate => Err(IndeterminateError),
392 }
393 }
394}
395
396impl From<Result<Tribool, IndeterminateError>> for Tribool {
397 #[inline]
398 fn from(value: Result<Tribool, IndeterminateError>) -> Self {
399 match value {
400 Ok(t) => t,
401 Err(_) => Indeterminate,
402 }
403 }
404}
405
406macro_rules! forward_ref_unop {
409 (impl $imp:ident, $method:ident for $t:ty) => {
410 impl<'a> $imp for &'a $t {
411 type Output = <$t as $imp>::Output;
412
413 #[inline]
414 fn $method(self) -> <$t as $imp>::Output {
415 $imp::$method(*self)
416 }
417 }
418 };
419}
420
421macro_rules! forward_ref_binop {
424 (impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
425 impl<'a> $imp<$u> for &'a $t {
426 type Output = <$t as $imp<$u>>::Output;
427
428 #[inline]
429 fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
430 $imp::$method(*self, other)
431 }
432 }
433
434 impl<'a> $imp<&'a $u> for $t {
435 type Output = <$t as $imp<$u>>::Output;
436
437 #[inline]
438 fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
439 $imp::$method(self, *other)
440 }
441 }
442
443 impl<'a, 'b> $imp<&'a $u> for &'b $t {
444 type Output = <$t as $imp<$u>>::Output;
445
446 #[inline]
447 fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
448 $imp::$method(*self, *other)
449 }
450 }
451 };
452}
453
454forward_ref_unop!(impl Not, not for Tribool);
455
456forward_ref_binop!(impl BitAnd, bitand for Tribool, Tribool);
457forward_ref_binop!(impl BitOr, bitor for Tribool, Tribool);
458forward_ref_binop!(impl BitXor, bitxor for Tribool, Tribool);
459
460forward_ref_binop!(impl BitAnd, bitand for Tribool, bool);
461forward_ref_binop!(impl BitOr, bitor for Tribool, bool);
462forward_ref_binop!(impl BitXor, bitxor for Tribool, bool);
463
464forward_ref_binop!(impl BitAnd, bitand for bool, Tribool);
465forward_ref_binop!(impl BitOr, bitor for bool, Tribool);
466forward_ref_binop!(impl BitXor, bitxor for bool, Tribool);
467
468#[cfg(test)]
469mod test {
470 use super::*;
471
472 #[test]
473 fn equality() {
474 assert_eq!(True, True);
475 assert_ne!(True, False);
476 assert_ne!(False, True);
477 assert_eq!(False, False);
478
479 assert!(!(Indeterminate == True));
480 assert!(!(Indeterminate == False));
481 assert!(!(Indeterminate == Indeterminate));
482 assert!(!(Indeterminate != True));
483 assert!(!(Indeterminate != False));
484 assert!(!(Indeterminate != Indeterminate));
485 }
486
487 #[test]
488 fn bool_equality() {
489 assert_eq!(True, true);
490 assert_eq!(False, false);
491 assert_ne!(True, false);
492 assert_ne!(False, true);
493 assert!(!(Indeterminate != true));
494 assert!(!(Indeterminate != false));
495 }
496
497 #[test]
498 fn ordering() {
499 assert!(True > False);
500 assert!(True >= False);
501 assert!(False < True);
502 assert!(False <= True);
503 assert!(False <= False);
504 assert!(False >= False);
505 assert!(True <= True);
506 assert!(True >= True);
507
508 assert!(!(True > True));
509 assert!(!(False > True));
510 assert!(!(False > False));
511
512 assert!(!(Indeterminate < True));
513 assert!(!(Indeterminate < False));
514 assert!(!(Indeterminate <= True));
515 assert!(!(Indeterminate <= False));
516 assert!(!(Indeterminate > True));
517 assert!(!(Indeterminate > False));
518 assert!(!(Indeterminate >= True));
519 assert!(!(Indeterminate >= False));
520 }
521
522 #[test]
523 fn bool_ordering() {
524 assert!(True > false);
525 assert!(True >= false);
526 assert!(False < true);
527 assert!(False <= true);
528 assert!(False <= false);
529 assert!(False >= false);
530 assert!(True <= true);
531 assert!(True >= true);
532
533 assert!(!(True > true));
534 assert!(!(False > true));
535 assert!(!(False > false));
536
537 assert!(!(Indeterminate < true));
538 assert!(!(Indeterminate < false));
539 assert!(!(Indeterminate <= true));
540 assert!(!(Indeterminate <= false));
541 assert!(!(Indeterminate > true));
542 assert!(!(Indeterminate > false));
543 assert!(!(Indeterminate >= true));
544 assert!(!(Indeterminate >= false));
545 }
546
547 #[test]
548 fn and() {
549 assert!((False & False).is_false());
550 assert!((False & Indeterminate).is_false());
551 assert!((False & True).is_false());
552
553 assert!((Indeterminate & False).is_false());
554 assert!((Indeterminate & Indeterminate).is_indeterminate());
555 assert!((Indeterminate & True).is_indeterminate());
556
557 assert!((True & False).is_false());
558 assert!((True & Indeterminate).is_indeterminate());
559 assert!((True & True).is_true());
560 }
561
562 #[test]
563 fn or() {
564 assert!((False | False).is_false());
565 assert!((False | Indeterminate).is_indeterminate());
566 assert!((False | True).is_true());
567
568 assert!((Indeterminate | False).is_indeterminate());
569 assert!((Indeterminate | Indeterminate).is_indeterminate());
570 assert!((Indeterminate | True).is_true());
571
572 assert!((True | False).is_true());
573 assert!((True | Indeterminate).is_true());
574 assert!((True | True).is_true());
575 }
576
577 #[test]
578 fn xor() {
579 assert!((False ^ False).is_false());
580 assert!((False ^ True).is_true());
581 assert!((False ^ Indeterminate).is_indeterminate());
582
583 assert!((Indeterminate ^ False).is_indeterminate());
584 assert!((Indeterminate ^ Indeterminate).is_indeterminate());
585 assert!((Indeterminate ^ True).is_indeterminate());
586
587 assert!((True ^ False).is_true());
588 assert!((True ^ Indeterminate).is_indeterminate());
589 assert!((True ^ True).is_false());
590 }
591
592 #[test]
593 fn kleene() {
594 assert!(True.kleene_implication(True).is_true());
595 assert!(Indeterminate.kleene_implication(True).is_true());
596 assert!(False.kleene_implication(True).is_true());
597
598 assert!(True.kleene_implication(Indeterminate).is_indeterminate());
599 assert!(Indeterminate
600 .kleene_implication(Indeterminate)
601 .is_indeterminate());
602 assert!(False.kleene_implication(Indeterminate).is_true());
603
604 assert!(True.kleene_implication(False).is_false());
605 assert!(Indeterminate.kleene_implication(False).is_indeterminate());
606 assert!(False.kleene_implication(False).is_true());
607 }
608
609 #[test]
610 fn lukasiewicz() {
611 assert!(True.lukasiewicz_implication(True).is_true());
612 assert!(Indeterminate.lukasiewicz_implication(True).is_true());
613 assert!(False.lukasiewicz_implication(True).is_true());
614
615 assert!(True
616 .lukasiewicz_implication(Indeterminate)
617 .is_indeterminate());
618 assert!(Indeterminate
619 .lukasiewicz_implication(Indeterminate)
620 .is_true());
621 assert!(False.lukasiewicz_implication(Indeterminate).is_true());
622
623 assert!(True.lukasiewicz_implication(False).is_false());
624 assert!(Indeterminate
625 .lukasiewicz_implication(False)
626 .is_indeterminate());
627 assert!(False.lukasiewicz_implication(False).is_true());
628 }
629
630 #[cfg(feature = "serde")]
631 #[test]
632 fn serde() {
633 let res_false = serde_json::to_string_pretty(&Tribool::False)
634 .expect("serde Serialize impl for False failed");
635 let res_true = serde_json::to_string_pretty(&Tribool::True)
636 .expect("serde Serialize impl for True failed");
637 let res_none = serde_json::to_string_pretty(&Tribool::Indeterminate)
638 .expect("serde Serialize impl for Indeterminate failed");
639
640 assert!(serde_json::from_str::<Tribool>(&res_false)
641 .expect("serde Deserialize impl for False failed")
642 .is_false());
643 assert!(serde_json::from_str::<Tribool>(&res_true)
644 .expect("serde Deserialize impl for True failed")
645 .is_true());
646 assert!(serde_json::from_str::<Tribool>(&res_none)
647 .expect("serde Deserialize impl for Indeterminate failed")
648 .is_indeterminate())
649 }
650}