1//! Type-level bits.
2//!
3//! These are rather simple and are used as the building blocks of the
4//! other number types in this crate.
5//!
6//!
7//! **Type operators** implemented:
8//!
9//! - From `core::ops`: `BitAnd`, `BitOr`, `BitXor`, and `Not`.
10//! - From `typenum`: `Same` and `Cmp`.
11
12use crate::{private::InternalMarker, Cmp, Equal, Greater, Less, NonZero, PowerOfTwo, Zero};
13use core::ops::{BitAnd, BitOr, BitXor, Not};
14
15pub use crate::marker_traits::Bit;
16
17/// The type-level bit 0.
18#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
19#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))]
20pub struct B0;
21
22impl B0 {
23 /// Instantiates a singleton representing this bit.
24 #[inline]
25 pub fn new() -> B0 {
26 B0
27 }
28}
29
30/// The type-level bit 1.
31#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
32#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))]
33pub struct B1;
34
35impl B1 {
36 /// Instantiates a singleton representing this bit.
37 #[inline]
38 pub fn new() -> B1 {
39 B1
40 }
41}
42
43impl Bit for B0 {
44 const U8: u8 = 0;
45 const BOOL: bool = false;
46
47 #[inline]
48 fn new() -> Self {
49 Self
50 }
51 #[inline]
52 fn to_u8() -> u8 {
53 0
54 }
55 #[inline]
56 fn to_bool() -> bool {
57 false
58 }
59}
60
61impl Bit for B1 {
62 const U8: u8 = 1;
63 const BOOL: bool = true;
64
65 #[inline]
66 fn new() -> Self {
67 Self
68 }
69 #[inline]
70 fn to_u8() -> u8 {
71 1
72 }
73 #[inline]
74 fn to_bool() -> bool {
75 true
76 }
77}
78
79impl Zero for B0 {}
80impl NonZero for B1 {}
81impl PowerOfTwo for B1 {}
82
83/// Not of 0 (!0 = 1)
84impl Not for B0 {
85 type Output = B1;
86 #[inline]
87 fn not(self) -> Self::Output {
88 B1
89 }
90}
91/// Not of 1 (!1 = 0)
92impl Not for B1 {
93 type Output = B0;
94 #[inline]
95 fn not(self) -> Self::Output {
96 B0
97 }
98}
99
100/// And with 0 ( 0 & B = 0)
101impl<Rhs: Bit> BitAnd<Rhs> for B0 {
102 type Output = B0;
103 #[inline]
104 fn bitand(self, _: Rhs) -> Self::Output {
105 B0
106 }
107}
108
109/// And with 1 ( 1 & 0 = 0)
110impl BitAnd<B0> for B1 {
111 type Output = B0;
112 #[inline]
113 fn bitand(self, _: B0) -> Self::Output {
114 B0
115 }
116}
117
118/// And with 1 ( 1 & 1 = 1)
119impl BitAnd<B1> for B1 {
120 type Output = B1;
121 #[inline]
122 fn bitand(self, _: B1) -> Self::Output {
123 B1
124 }
125}
126
127/// Or with 0 ( 0 | 0 = 0)
128impl BitOr<B0> for B0 {
129 type Output = B0;
130 #[inline]
131 fn bitor(self, _: B0) -> Self::Output {
132 B0
133 }
134}
135
136/// Or with 0 ( 0 | 1 = 1)
137impl BitOr<B1> for B0 {
138 type Output = B1;
139 #[inline]
140 fn bitor(self, _: B1) -> Self::Output {
141 B1
142 }
143}
144
145/// Or with 1 ( 1 | B = 1)
146impl<Rhs: Bit> BitOr<Rhs> for B1 {
147 type Output = B1;
148 #[inline]
149 fn bitor(self, _: Rhs) -> Self::Output {
150 B1
151 }
152}
153
154/// Xor between 0 and 0 ( 0 ^ 0 = 0)
155impl BitXor<B0> for B0 {
156 type Output = B0;
157 #[inline]
158 fn bitxor(self, _: B0) -> Self::Output {
159 B0
160 }
161}
162/// Xor between 1 and 0 ( 1 ^ 0 = 1)
163impl BitXor<B0> for B1 {
164 type Output = B1;
165 #[inline]
166 fn bitxor(self, _: B0) -> Self::Output {
167 B1
168 }
169}
170/// Xor between 0 and 1 ( 0 ^ 1 = 1)
171impl BitXor<B1> for B0 {
172 type Output = B1;
173 #[inline]
174 fn bitxor(self, _: B1) -> Self::Output {
175 B1
176 }
177}
178/// Xor between 1 and 1 ( 1 ^ 1 = 0)
179impl BitXor<B1> for B1 {
180 type Output = B0;
181 #[inline]
182 fn bitxor(self, _: B1) -> Self::Output {
183 B0
184 }
185}
186
187#[cfg(tests)]
188mod tests {
189 // macro for testing operation results. Uses `Same` to ensure the types are equal and
190 // not just the values they evaluate to.
191 macro_rules! test_bit_op {
192 ($op:ident $Lhs:ident = $Answer:ident) => {{
193 type Test = <<$Lhs as $op>::Output as ::Same<$Answer>>::Output;
194 assert_eq!(<$Answer as Bit>::to_u8(), <Test as Bit>::to_u8());
195 }};
196 ($Lhs:ident $op:ident $Rhs:ident = $Answer:ident) => {{
197 type Test = <<$Lhs as $op<$Rhs>>::Output as ::Same<$Answer>>::Output;
198 assert_eq!(<$Answer as Bit>::to_u8(), <Test as Bit>::to_u8());
199 }};
200 }
201
202 #[test]
203 fn bit_operations() {
204 test_bit_op!(Not B0 = B1);
205 test_bit_op!(Not B1 = B0);
206
207 test_bit_op!(B0 BitAnd B0 = B0);
208 test_bit_op!(B0 BitAnd B1 = B0);
209 test_bit_op!(B1 BitAnd B0 = B0);
210 test_bit_op!(B1 BitAnd B1 = B1);
211
212 test_bit_op!(B0 BitOr B0 = B0);
213 test_bit_op!(B0 BitOr B1 = B1);
214 test_bit_op!(B1 BitOr B0 = B1);
215 test_bit_op!(B1 BitOr B1 = B1);
216
217 test_bit_op!(B0 BitXor B0 = B0);
218 test_bit_op!(B0 BitXor B1 = B1);
219 test_bit_op!(B1 BitXor B0 = B1);
220 test_bit_op!(B1 BitXor B1 = B0);
221 }
222}
223
224impl Cmp<B0> for B0 {
225 type Output = Equal;
226
227 #[inline]
228 fn compare<P: InternalMarker>(&self, _: &B0) -> Self::Output {
229 Equal
230 }
231}
232
233impl Cmp<B1> for B0 {
234 type Output = Less;
235
236 #[inline]
237 fn compare<P: InternalMarker>(&self, _: &B1) -> Self::Output {
238 Less
239 }
240}
241
242impl Cmp<B0> for B1 {
243 type Output = Greater;
244
245 #[inline]
246 fn compare<P: InternalMarker>(&self, _: &B0) -> Self::Output {
247 Greater
248 }
249}
250
251impl Cmp<B1> for B1 {
252 type Output = Equal;
253
254 #[inline]
255 fn compare<P: InternalMarker>(&self, _: &B1) -> Self::Output {
256 Equal
257 }
258}
259
260use crate::Min;
261impl Min<B0> for B0 {
262 type Output = B0;
263 #[inline]
264 fn min(self, _: B0) -> B0 {
265 self
266 }
267}
268impl Min<B1> for B0 {
269 type Output = B0;
270 #[inline]
271 fn min(self, _: B1) -> B0 {
272 self
273 }
274}
275impl Min<B0> for B1 {
276 type Output = B0;
277 #[inline]
278 fn min(self, rhs: B0) -> B0 {
279 rhs
280 }
281}
282impl Min<B1> for B1 {
283 type Output = B1;
284 #[inline]
285 fn min(self, _: B1) -> B1 {
286 self
287 }
288}
289
290use crate::Max;
291impl Max<B0> for B0 {
292 type Output = B0;
293 #[inline]
294 fn max(self, _: B0) -> B0 {
295 self
296 }
297}
298impl Max<B1> for B0 {
299 type Output = B1;
300 #[inline]
301 fn max(self, rhs: B1) -> B1 {
302 rhs
303 }
304}
305impl Max<B0> for B1 {
306 type Output = B1;
307 #[inline]
308 fn max(self, _: B0) -> B1 {
309 self
310 }
311}
312impl Max<B1> for B1 {
313 type Output = B1;
314 #[inline]
315 fn max(self, _: B1) -> B1 {
316 self
317 }
318}
319
320#[cfg(test)]
321mod tests {
322 #[test]
323 fn bit_creation() {
324 {
325 use crate::{B0, B1};
326 let _: B0 = B0::new();
327 let _: B1 = B1::new();
328 }
329
330 {
331 use crate::{Bit, B0, B1};
332
333 let _: B0 = <B0 as Bit>::new();
334 let _: B1 = <B1 as Bit>::new();
335 }
336 }
337}
338