ternary/
lib.rs

1//! Kleene logic within Rust's type system
2//!
3//! Values are `True`, `False` and `Unknown`. Operations are `Not`, `BitAnd`
4//! and `BitOr` from `std::ops`. There is also the `Ternary` enum which 
5//! represents the values at runtime and the `ToTernary` trait that adds the
6//! `to_ternary()` methods to our value types.
7//!
8//! Examples:
9//!
10//! `Same` and `Not`
11//!
12//! ```
13//!# use ternary::{True, False, Unknown, Same};
14//!# use std::ops::Not;
15//! type NotTrue = <<True as Not>::Output as Same<False>>::Output;
16//! type NotFalse = <<False as Not>::Output as Same<True>>::Output;
17//! type NotUnknown = <<Unknown as Not>::Output as Same<Unknown>>::Output;
18//! ```
19//! 
20//! Transforming Values to Runtime, `BitAnd` and `BitOr`
21//!
22//! ```
23//!# use ternary::{True, False, Unknown, Same, Ternary, ToTernary};
24//!# use std::ops::{BitAnd, BitOr};
25//! assert_eq!(Ternary::T, <True as BitOr<<Unknown as BitAnd<False>>::Output>>::Output::to_ternary());
26//! ```
27use std::ops::{Not, BitAnd, BitOr};
28
29/// Our True type value
30pub enum True {}
31
32/// Our False type value
33pub enum False {}
34
35/// Our Unknown type value
36pub enum Unknown {}
37
38/// runtime representation
39#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
40pub enum Ternary { 
41    /// A True-ish value
42    T,
43    /// An Unknown value
44    U,
45    /// A False-ish value
46    F,
47}
48
49/// conversion to runtime enum
50///
51/// examples:
52/// ```
53///# use ternary::{True, False, Unknown, Ternary, ToTernary};
54/// assert_eq!(True::to_ternary(), Ternary::T);
55/// assert_eq!(False::to_ternary(), Ternary::F);
56/// assert_eq!(Unknown::to_ternary(), Ternary::U);
57/// ```
58pub trait ToTernary {
59    fn to_ternary() -> Ternary;
60}
61
62impl ToTernary for True {
63    #[inline] fn to_ternary() -> Ternary { Ternary::T }
64}
65
66impl ToTernary for False {
67    #[inline] fn to_ternary() -> Ternary { Ternary::F }
68}
69
70impl ToTernary for Unknown {
71    #[inline] fn to_ternary() -> Ternary { Ternary::U }
72}
73
74/// Not
75
76/// !True == False
77impl Not for True {
78    type Output = False;
79    fn not(self) -> Self::Output { unreachable!() }
80}
81
82///!False == True
83impl Not for False {
84    type Output = True;
85    fn not(self) -> Self::Output { unreachable!() }
86}
87
88///!Unknown == Unknown
89impl Not for Unknown {
90    type Output = Unknown;
91    fn not(self) -> Self::Output { unreachable!() }
92}
93
94/// BitAnd
95
96/// True & X == X
97impl<X: ToTernary> BitAnd<X> for True {
98    type Output = X;
99    fn bitand(self, _: X) -> Self::Output { unreachable!() }
100}
101
102/// False & X == False
103impl<X: ToTernary> BitAnd<X> for False {
104    type Output = False;
105    fn bitand(self, _: X) -> Self::Output { unreachable!() }
106}
107
108/// Unknown & True == Unknown
109impl BitAnd<True> for Unknown {
110    type Output = Unknown;
111    fn bitand(self, _: True) -> Self::Output { unreachable!() }
112}
113
114/// Unknown & Unknown == Unknown
115impl BitAnd<Unknown> for Unknown {
116    type Output = Unknown;
117    fn bitand(self, _: Unknown) -> Self::Output { unreachable!() }
118}
119
120/// Unknown & False == False
121impl BitAnd<False> for Unknown {
122    type Output = False;
123    fn bitand(self, _: False) -> Self::Output { unreachable!() }
124}
125
126
127/// BitOr
128
129/// True | X == True
130impl<X: ToTernary> BitOr<X> for True {
131    type Output = True;
132    fn bitor(self, _: X) -> Self::Output { unreachable!() }
133}
134
135/// False | X == X
136impl<X: ToTernary> BitOr<X> for False {
137    type Output = X;
138    fn bitor(self, _: X) -> Self::Output { unreachable!() }
139}
140
141/// Unknown | True == True
142impl BitOr<True> for Unknown {
143    type Output = True;
144    fn bitor(self, _: True) -> Self::Output { unreachable!() }
145}
146
147/// Unknown | Unknown == Unknown
148impl BitOr<Unknown> for Unknown {
149    type Output = Unknown;
150    fn bitor(self, _: Unknown) -> Self::Output { unreachable!() }
151}
152
153/// Unknown | False == Unknown
154impl BitOr<False> for Unknown {
155    type Output = Unknown;
156    fn bitor(self, _: False) -> Self::Output { unreachable!() }
157}
158
159/// shamelessly copied from typenum
160pub trait Same<Rhs = Self> {
161    type Output;
162}
163
164impl<T> Same<T> for T {
165    type Output = T;
166}