1use crate::uninhabited::PhantomUninhabited;
2
3pub trait Bool: BoolT + private_bool::Sealed {
6 const VALUE: bool;
7}
8
9pub trait BoolT {
11 type Type: Bool;
12}
13
14pub enum False {}
16impl Bool for False {
17 const VALUE: bool = false;
18}
19impl BoolT for False {
20 type Type = Self;
21}
22
23pub 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
54pub 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
63pub 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
72pub 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
82pub 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
93pub 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
103pub 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
114pub 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
129pub trait BoolIsEq: private_eq::BoolIsEqSealed {}
132impl<T: private_eq::BoolIsEqSealed> BoolIsEq for T {}
133
134pub 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}