typenum/
bit.rs

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(test)]
188mod bit_op_tests {
189    use core::ops::{BitAnd, BitOr, BitXor, Not};
190
191    use crate::{B0, B1};
192
193    // macro for testing operation results. Uses `Same` to ensure the types are equal and
194    // not just the values they evaluate to.
195    macro_rules! test_bit_op {
196        ($op:ident $Lhs:ident = $Answer:ident) => {{
197            type Test = <<$Lhs as $op>::Output as $crate::Same<$Answer>>::Output;
198            assert_eq!(
199                <$Answer as $crate::Bit>::to_u8(),
200                <Test as $crate::Bit>::to_u8()
201            );
202        }};
203        ($Lhs:ident $op:ident $Rhs:ident = $Answer:ident) => {{
204            type Test = <<$Lhs as $op<$Rhs>>::Output as $crate::Same<$Answer>>::Output;
205            assert_eq!(
206                <$Answer as $crate::Bit>::to_u8(),
207                <Test as $crate::Bit>::to_u8()
208            );
209        }};
210    }
211
212    #[test]
213    fn bit_operations() {
214        test_bit_op!(Not B0 = B1);
215        test_bit_op!(Not B1 = B0);
216
217        test_bit_op!(B0 BitAnd B0 = B0);
218        test_bit_op!(B0 BitAnd B1 = B0);
219        test_bit_op!(B1 BitAnd B0 = B0);
220        test_bit_op!(B1 BitAnd B1 = B1);
221
222        test_bit_op!(B0 BitOr B0 = B0);
223        test_bit_op!(B0 BitOr B1 = B1);
224        test_bit_op!(B1 BitOr B0 = B1);
225        test_bit_op!(B1 BitOr B1 = B1);
226
227        test_bit_op!(B0 BitXor B0 = B0);
228        test_bit_op!(B0 BitXor B1 = B1);
229        test_bit_op!(B1 BitXor B0 = B1);
230        test_bit_op!(B1 BitXor B1 = B0);
231    }
232}
233
234impl Cmp<B0> for B0 {
235    type Output = Equal;
236
237    #[inline]
238    fn compare<P: InternalMarker>(&self, _: &B0) -> Self::Output {
239        Equal
240    }
241}
242
243impl Cmp<B1> for B0 {
244    type Output = Less;
245
246    #[inline]
247    fn compare<P: InternalMarker>(&self, _: &B1) -> Self::Output {
248        Less
249    }
250}
251
252impl Cmp<B0> for B1 {
253    type Output = Greater;
254
255    #[inline]
256    fn compare<P: InternalMarker>(&self, _: &B0) -> Self::Output {
257        Greater
258    }
259}
260
261impl Cmp<B1> for B1 {
262    type Output = Equal;
263
264    #[inline]
265    fn compare<P: InternalMarker>(&self, _: &B1) -> Self::Output {
266        Equal
267    }
268}
269
270use crate::Min;
271impl Min<B0> for B0 {
272    type Output = B0;
273    #[inline]
274    fn min(self, _: B0) -> B0 {
275        self
276    }
277}
278impl Min<B1> for B0 {
279    type Output = B0;
280    #[inline]
281    fn min(self, _: B1) -> B0 {
282        self
283    }
284}
285impl Min<B0> for B1 {
286    type Output = B0;
287    #[inline]
288    fn min(self, rhs: B0) -> B0 {
289        rhs
290    }
291}
292impl Min<B1> for B1 {
293    type Output = B1;
294    #[inline]
295    fn min(self, _: B1) -> B1 {
296        self
297    }
298}
299
300use crate::Max;
301impl Max<B0> for B0 {
302    type Output = B0;
303    #[inline]
304    fn max(self, _: B0) -> B0 {
305        self
306    }
307}
308impl Max<B1> for B0 {
309    type Output = B1;
310    #[inline]
311    fn max(self, rhs: B1) -> B1 {
312        rhs
313    }
314}
315impl Max<B0> for B1 {
316    type Output = B1;
317    #[inline]
318    fn max(self, _: B0) -> B1 {
319        self
320    }
321}
322impl Max<B1> for B1 {
323    type Output = B1;
324    #[inline]
325    fn max(self, _: B1) -> B1 {
326        self
327    }
328}
329
330#[cfg(test)]
331mod bit_creation_tests {
332    #[test]
333    fn bit_creation() {
334        {
335            use crate::{B0, B1};
336            let _: B0 = B0::new();
337            let _: B1 = B1::new();
338        }
339
340        {
341            use crate::{Bit, B0, B1};
342
343            let _: B0 = <B0 as Bit>::new();
344            let _: B1 = <B1 as Bit>::new();
345        }
346    }
347}