typefun/
bool.rs

1use crate::uninhabited::PhantomUninhabited;
2
3/// A boolean value.
4/// The only implementations are `False` or `True`.
5pub trait Bool: BoolT + private_bool::Sealed {
6    const VALUE: bool;
7}
8
9/// A type representing a boolean value.
10pub trait BoolT {
11    type Type: Bool;
12}
13
14/// Represent the boolean value `false`.
15pub enum False {}
16impl Bool for False {
17    const VALUE: bool = false;
18}
19impl BoolT for False {
20    type Type = Self;
21}
22
23/// Represent the boolean value `true`.
24pub enum True {}
25impl Bool for True {
26    const VALUE: bool = true;
27}
28impl BoolT for True {
29    type Type = Self;
30}
31
32mod private_bool {
33    use super::*;
34
35    pub trait Sealed {}
36    impl Sealed for False {}
37    impl Sealed for True {}
38}
39
40pub struct NandBase<A: Bool, B: Bool>(PhantomUninhabited<(A, B)>);
41impl BoolT for NandBase<False, False> {
42    type Type = True;
43}
44impl BoolT for NandBase<False, True> {
45    type Type = True;
46}
47impl BoolT for NandBase<True, False> {
48    type Type = True;
49}
50impl BoolT for NandBase<True, True> {
51    type Type = False;
52}
53
54/// Represents `A nand B`.
55pub struct Nand<A: BoolT, B: BoolT>(PhantomUninhabited<(A, B)>);
56impl<A: BoolT, B: BoolT> BoolT for Nand<A, B>
57where
58    NandBase<A::Type, B::Type>: BoolT,
59{
60    type Type = <NandBase<A::Type, B::Type> as BoolT>::Type;
61}
62
63/// Represents `not A`.
64pub struct Not<A: BoolT>(PhantomUninhabited<A>);
65impl<A: BoolT> BoolT for Not<A>
66where
67    Nand<A, A>: BoolT,
68{
69    type Type = <Nand<A, A> as BoolT>::Type;
70}
71
72/// Represents `A and B`.
73pub struct And<A: BoolT, B: BoolT>(PhantomUninhabited<(A, B)>);
74impl<A: BoolT, B: BoolT> BoolT for And<A, B>
75where
76    Nand<A, B>: BoolT,
77    Not<<Nand<A, B> as BoolT>::Type>: BoolT,
78{
79    type Type = <Not<<Nand<A, B> as BoolT>::Type> as BoolT>::Type;
80}
81
82/// Represents `A or B`.
83pub struct Or<A: BoolT, B: BoolT>(PhantomUninhabited<(A, B)>);
84impl<A: BoolT, B: BoolT> BoolT for Or<A, B>
85where
86    Not<A>: BoolT,
87    Not<B>: BoolT,
88    Nand<<Not<A> as BoolT>::Type, <Not<B> as BoolT>::Type>: BoolT,
89{
90    type Type = <Nand<<Not<A> as BoolT>::Type, <Not<B> as BoolT>::Type> as BoolT>::Type;
91}
92
93/// Represents `A nor B`.
94pub struct Nor<A: BoolT, B: BoolT>(PhantomUninhabited<(A, B)>);
95impl<A: BoolT, B: BoolT> BoolT for Nor<A, B>
96where
97    Or<A, B>: BoolT,
98    Not<<Or<A, B> as BoolT>::Type>: BoolT,
99{
100    type Type = <Not<<Or<A, B> as BoolT>::Type> as BoolT>::Type;
101}
102
103/// Represents `A xnor B`.
104pub struct Xnor<A: BoolT, B: BoolT>(PhantomUninhabited<(A, B)>);
105impl<A: BoolT, B: BoolT> BoolT for Xnor<A, B>
106where
107    Nand<A, B>: BoolT,
108    And<A, B>: BoolT,
109    Or<<Nand<A, B> as BoolT>::Type, <And<A, B> as BoolT>::Type>: BoolT,
110{
111    type Type = <Or<<Nand<A, B> as BoolT>::Type, <And<A, B> as BoolT>::Type> as BoolT>::Type;
112}
113
114/// Represents `A xor B`.
115pub struct Xor<A: BoolT, B: BoolT>(PhantomUninhabited<(A, B)>);
116impl<A: BoolT, B: BoolT> BoolT for Xor<A, B>
117where
118    Xnor<A, B>: BoolT,
119    Not<<Xnor<A, B> as BoolT>::Type>: BoolT,
120{
121    type Type = <Not<<Xnor<A, B> as BoolT>::Type> as BoolT>::Type;
122}
123
124pub type BoolEq<A, B> = Xnor<A, B>;
125
126pub const fn assert_false<T: BoolT<Type = False>>() {}
127pub const fn assert_true<T: BoolT<Type = True>>() {}
128
129/// Only implemented for two types `A: BoolT` and `B: BoolT` where `A` and `B` represents the same
130/// boolean value.
131pub trait BoolIsEq: private_eq::BoolIsEqSealed {}
132impl<T: private_eq::BoolIsEqSealed> BoolIsEq for T {}
133
134/// Only implemented for two types `A: BoolT` and `B: BoolT` where `A` and `B` represents different
135/// boolean values.
136pub trait BoolNotEq: private_eq::BoolNotEqSealed {}
137impl<T: private_eq::BoolNotEqSealed> BoolNotEq for T {}
138
139mod private_eq {
140    use super::*;
141    pub trait BoolIsEqSealed {}
142    impl<V: Bool, A: BoolT<Type = V>, B: BoolT<Type = V>> BoolIsEqSealed for (A, B) {}
143
144    pub trait BoolNotEqSealed {}
145    impl<A, B> BoolNotEqSealed for (A, B)
146    where
147        A: BoolT,
148        B: BoolT,
149        (A, Not<B>): BoolIsEq,
150    {
151    }
152}
153
154pub const fn assert_bool_eq<T1: BoolT, T2: BoolT>()
155where
156    (T1, T2): BoolIsEq,
157{
158}
159
160mod test {
161    use super::*;
162
163    const _: () = assert_false::<False>();
164    const _: () = assert_true::<True>();
165
166    const _: () = assert_true::<Not<False>>();
167    const _: () = assert_false::<Not<True>>();
168
169    const _: () = assert_false::<And<False, False>>();
170    const _: () = assert_false::<And<False, True>>();
171    const _: () = assert_false::<And<True, False>>();
172    const _: () = assert_true::<And<True, True>>();
173
174    const _: () = assert_true::<Nand<False, False>>();
175    const _: () = assert_true::<Nand<False, True>>();
176    const _: () = assert_false::<Nand<True, True>>();
177    const _: () = assert_true::<Nand<True, False>>();
178
179    const _: () = assert_false::<Or<False, False>>();
180    const _: () = assert_true::<Or<False, True>>();
181    const _: () = assert_true::<Or<True, False>>();
182    const _: () = assert_true::<Or<True, True>>();
183
184    const _: () = assert_true::<Nor<False, False>>();
185    const _: () = assert_false::<Nor<False, True>>();
186    const _: () = assert_false::<Nor<True, False>>();
187    const _: () = assert_false::<Nor<True, True>>();
188}