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 | |
12 | use crate::{private::InternalMarker, Cmp, Equal, Greater, Less, NonZero, PowerOfTwo, Zero}; |
13 | use core::ops::{BitAnd, BitOr, BitXor, Not}; |
14 | |
15 | pub 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))] |
20 | pub struct B0; |
21 | |
22 | impl 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))] |
33 | pub struct B1; |
34 | |
35 | impl B1 { |
36 | /// Instantiates a singleton representing this bit. |
37 | #[inline ] |
38 | pub fn new() -> B1 { |
39 | B1 |
40 | } |
41 | } |
42 | |
43 | impl 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 | |
61 | impl 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 | |
79 | impl Zero for B0 {} |
80 | impl NonZero for B1 {} |
81 | impl PowerOfTwo for B1 {} |
82 | |
83 | /// Not of 0 (!0 = 1) |
84 | impl 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) |
92 | impl 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) |
101 | impl<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) |
110 | impl 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) |
119 | impl 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) |
128 | impl 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) |
137 | impl 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) |
146 | impl<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) |
155 | impl 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) |
163 | impl 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) |
171 | impl 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) |
179 | impl 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)] |
188 | mod 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 | |
224 | impl 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 | |
233 | impl 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 | |
242 | impl 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 | |
251 | impl 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 | |
260 | use crate::Min; |
261 | impl Min<B0> for B0 { |
262 | type Output = B0; |
263 | #[inline ] |
264 | fn min(self, _: B0) -> B0 { |
265 | self |
266 | } |
267 | } |
268 | impl Min<B1> for B0 { |
269 | type Output = B0; |
270 | #[inline ] |
271 | fn min(self, _: B1) -> B0 { |
272 | self |
273 | } |
274 | } |
275 | impl Min<B0> for B1 { |
276 | type Output = B0; |
277 | #[inline ] |
278 | fn min(self, rhs: B0) -> B0 { |
279 | rhs |
280 | } |
281 | } |
282 | impl Min<B1> for B1 { |
283 | type Output = B1; |
284 | #[inline ] |
285 | fn min(self, _: B1) -> B1 { |
286 | self |
287 | } |
288 | } |
289 | |
290 | use crate::Max; |
291 | impl Max<B0> for B0 { |
292 | type Output = B0; |
293 | #[inline ] |
294 | fn max(self, _: B0) -> B0 { |
295 | self |
296 | } |
297 | } |
298 | impl Max<B1> for B0 { |
299 | type Output = B1; |
300 | #[inline ] |
301 | fn max(self, rhs: B1) -> B1 { |
302 | rhs |
303 | } |
304 | } |
305 | impl Max<B0> for B1 { |
306 | type Output = B1; |
307 | #[inline ] |
308 | fn max(self, _: B0) -> B1 { |
309 | self |
310 | } |
311 | } |
312 | impl Max<B1> for B1 { |
313 | type Output = B1; |
314 | #[inline ] |
315 | fn max(self, _: B1) -> B1 { |
316 | self |
317 | } |
318 | } |
319 | |
320 | #[cfg (test)] |
321 | mod 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 | |