xref: /qemu/rust/bits/src/lib.rs (revision f8a113701dd2d28f3bedb216e59125ddcb77fd05)
1 // SPDX-License-Identifier: MIT or Apache-2.0 or GPL-2.0-or-later
2 
3 /// # Definition entry point
4 ///
5 /// Define a struct with a single field of type $type.  Include public constants
6 /// for each element listed in braces.
7 ///
8 /// The unnamed element at the end, if present, can be used to enlarge the set
9 /// of valid bits.  Bits that are valid but not listed are treated normally for
10 /// the purpose of arithmetic operations, and are printed with their hexadecimal
11 /// value.
12 ///
13 /// The struct implements the following traits: [`BitAnd`](std::ops::BitAnd),
14 /// [`BitOr`](std::ops::BitOr), [`BitXor`](std::ops::BitXor),
15 /// [`Not`](std::ops::Not), [`Sub`](std::ops::Sub); [`Debug`](std::fmt::Debug),
16 /// [`Display`](std::fmt::Display), [`Binary`](std::fmt::Binary),
17 /// [`Octal`](std::fmt::Octal), [`LowerHex`](std::fmt::LowerHex),
18 /// [`UpperHex`](std::fmt::UpperHex); [`From`]`<type>`/[`Into`]`<type>` where
19 /// type is the type specified in the definition.
20 ///
21 /// ## Example
22 ///
23 /// ```
24 /// # use bits::bits;
25 /// bits! {
26 ///     pub struct Colors(u8) {
27 ///         BLACK = 0,
28 ///         RED = 1,
29 ///         GREEN = 1 << 1,
30 ///         BLUE = 1 << 2,
31 ///         WHITE = (1 << 0) | (1 << 1) | (1 << 2),
32 ///     }
33 /// }
34 /// ```
35 ///
36 /// ```
37 /// # use bits::bits;
38 /// # bits! { pub struct Colors(u8) { BLACK = 0, RED = 1, GREEN = 1 << 1, BLUE = 1 << 2, } }
39 ///
40 /// bits! {
41 ///     pub struct Colors8(u8) {
42 ///         BLACK = 0,
43 ///         RED = 1,
44 ///         GREEN = 1 << 1,
45 ///         BLUE = 1 << 2,
46 ///         WHITE = (1 << 0) | (1 << 1) | (1 << 2),
47 ///
48 ///         _ = 255,
49 ///     }
50 /// }
51 ///
52 /// // The previously defined struct ignores bits not explicitly defined.
53 /// assert_eq!(
54 ///     Colors::from(255).into_bits(),
55 ///     (Colors::RED | Colors::GREEN | Colors::BLUE).into_bits()
56 /// );
57 ///
58 /// // Adding "_ = 255" makes it retain other bits as well.
59 /// assert_eq!(Colors8::from(255).into_bits(), 255);
60 ///
61 /// // all() does not include the additional bits, valid_bits() does
62 /// assert_eq!(Colors8::all().into_bits(), Colors::all().into_bits());
63 /// assert_eq!(Colors8::valid_bits().into_bits(), 255);
64 /// ```
65 ///
66 /// # Evaluation entry point
67 ///
68 /// Return a constant corresponding to the boolean expression `$expr`.
69 /// Identifiers in the expression correspond to values defined for the
70 /// type `$type`.  Supported operators are `!` (unary), `-`, `&`, `^`, `|`.
71 ///
72 /// ## Examples
73 ///
74 /// ```
75 /// # use bits::bits;
76 /// bits! {
77 ///     pub struct Colors(u8) {
78 ///         BLACK = 0,
79 ///         RED = 1,
80 ///         GREEN = 1 << 1,
81 ///         BLUE = 1 << 2,
82 ///         // same as "WHITE = 7",
83 ///         WHITE = bits!(Self as u8: RED | GREEN | BLUE),
84 ///     }
85 /// }
86 ///
87 /// let rgb = bits! { Colors: RED | GREEN | BLUE };
88 /// assert_eq!(rgb, Colors::WHITE);
89 /// ```
90 #[macro_export]
91 macro_rules! bits {
92     {
93         $(#[$struct_meta:meta])*
94         $struct_vis:vis struct $struct_name:ident($field_vis:vis $type:ty) {
95             $($(#[$const_meta:meta])* $const:ident = $val:expr),+
96             $(,_ = $mask:expr)?
97             $(,)?
98         }
99     } => {
100         $(#[$struct_meta])*
101         #[derive(Clone, Copy, PartialEq, Eq)]
102         #[repr(transparent)]
103         $struct_vis struct $struct_name($field_vis $type);
104 
105         impl $struct_name {
106             $( #[allow(dead_code)] $(#[$const_meta])*
107                 pub const $const: $struct_name = $struct_name($val); )+
108 
109             #[doc(hidden)]
110             const VALID__: $type = $( Self::$const.0 )|+ $(|$mask)?;
111 
112             #[allow(dead_code)]
113             #[inline(always)]
114             pub const fn empty() -> Self {
115                 Self(0)
116             }
117 
118             #[allow(dead_code)]
119             #[inline(always)]
120             pub const fn all() -> Self {
121                 Self($( Self::$const.0 )|+)
122             }
123 
124             #[allow(dead_code)]
125             #[inline(always)]
126             pub const fn valid_bits() -> Self {
127                 Self(Self::VALID__)
128             }
129 
130             #[allow(dead_code)]
131             #[inline(always)]
132             pub const fn valid(val: $type) -> bool {
133                 (val & !Self::VALID__) == 0
134             }
135 
136             #[allow(dead_code)]
137             #[inline(always)]
138             pub const fn any_set(self, mask: Self) -> bool {
139                 (self.0 & mask.0) != 0
140             }
141 
142             #[allow(dead_code)]
143             #[inline(always)]
144             pub const fn all_set(self, mask: Self) -> bool {
145                 (self.0 & mask.0) == mask.0
146             }
147 
148             #[allow(dead_code)]
149             #[inline(always)]
150             pub const fn none_set(self, mask: Self) -> bool {
151                 (self.0 & mask.0) == 0
152             }
153 
154             #[allow(dead_code)]
155             #[inline(always)]
156             pub const fn from_bits(value: $type) -> Self {
157                 $struct_name(value)
158             }
159 
160             #[allow(dead_code)]
161             #[inline(always)]
162             pub const fn into_bits(self) -> $type {
163                 self.0
164             }
165 
166             #[allow(dead_code)]
167             #[inline(always)]
168             pub fn set(&mut self, rhs: Self) {
169                 self.0 |= rhs.0;
170             }
171 
172             #[allow(dead_code)]
173             #[inline(always)]
174             pub fn clear(&mut self, rhs: Self) {
175                 self.0 &= !rhs.0;
176             }
177 
178             #[allow(dead_code)]
179             #[inline(always)]
180             pub fn toggle(&mut self, rhs: Self) {
181                 self.0 ^= rhs.0;
182             }
183 
184             #[allow(dead_code)]
185             #[inline(always)]
186             pub const fn intersection(self, rhs: Self) -> Self {
187                 $struct_name(self.0 & rhs.0)
188             }
189 
190             #[allow(dead_code)]
191             #[inline(always)]
192             pub const fn difference(self, rhs: Self) -> Self {
193                 $struct_name(self.0 & !rhs.0)
194             }
195 
196             #[allow(dead_code)]
197             #[inline(always)]
198             pub const fn symmetric_difference(self, rhs: Self) -> Self {
199                 $struct_name(self.0 ^ rhs.0)
200             }
201 
202             #[allow(dead_code)]
203             #[inline(always)]
204             pub const fn union(self, rhs: Self) -> Self {
205                 $struct_name(self.0 | rhs.0)
206             }
207 
208             #[allow(dead_code)]
209             #[inline(always)]
210             pub const fn invert(self) -> Self {
211                 $struct_name(self.0 ^ Self::VALID__)
212             }
213         }
214 
215         impl ::std::fmt::Binary for $struct_name {
216             fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
217                 // If no width, use the highest valid bit
218                 let width = f.width().unwrap_or((Self::VALID__.ilog2() + 1) as usize);
219                 write!(f, "{:0>width$.precision$b}", self.0,
220                        width = width,
221                        precision = f.precision().unwrap_or(width))
222             }
223         }
224 
225         impl ::std::fmt::LowerHex for $struct_name {
226             fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
227                 <$type as ::std::fmt::LowerHex>::fmt(&self.0, f)
228             }
229         }
230 
231         impl ::std::fmt::Octal for $struct_name {
232             fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
233                 <$type as ::std::fmt::Octal>::fmt(&self.0, f)
234             }
235         }
236 
237         impl ::std::fmt::UpperHex for $struct_name {
238             fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
239                 <$type as ::std::fmt::UpperHex>::fmt(&self.0, f)
240             }
241         }
242 
243         impl ::std::fmt::Debug for $struct_name {
244             fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
245                 write!(f, "{}({})", stringify!($struct_name), self)
246             }
247         }
248 
249         impl ::std::fmt::Display for $struct_name {
250             fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
251                 use ::std::fmt::Display;
252                 let mut first = true;
253                 let mut left = self.0;
254                 $(if Self::$const.0.is_power_of_two() && (self & Self::$const).0 != 0 {
255                     if first { first = false } else { Display::fmt(&'|', f)?; }
256                     Display::fmt(stringify!($const), f)?;
257                     left -= Self::$const.0;
258                 })+
259                 if first {
260                     Display::fmt(&'0', f)
261                 } else if left != 0 {
262                     write!(f, "|{left:#x}")
263                 } else {
264                     Ok(())
265                 }
266             }
267         }
268 
269         impl ::std::cmp::PartialEq<$type> for $struct_name {
270             fn eq(&self, rhs: &$type) -> bool {
271                 self.0 == *rhs
272             }
273         }
274 
275         impl ::std::ops::BitAnd<$struct_name> for &$struct_name {
276             type Output = $struct_name;
277             fn bitand(self, rhs: $struct_name) -> Self::Output {
278                 $struct_name(self.0 & rhs.0)
279             }
280         }
281 
282         impl ::std::ops::BitAndAssign<$struct_name> for $struct_name {
283             fn bitand_assign(&mut self, rhs: $struct_name) {
284                 self.0 = self.0 & rhs.0
285             }
286         }
287 
288         impl ::std::ops::BitXor<$struct_name> for &$struct_name {
289             type Output = $struct_name;
290             fn bitxor(self, rhs: $struct_name) -> Self::Output {
291                 $struct_name(self.0 ^ rhs.0)
292             }
293         }
294 
295         impl ::std::ops::BitXorAssign<$struct_name> for $struct_name {
296             fn bitxor_assign(&mut self, rhs: $struct_name) {
297                 self.0 = self.0 ^ rhs.0
298             }
299         }
300 
301         impl ::std::ops::BitOr<$struct_name> for &$struct_name {
302             type Output = $struct_name;
303             fn bitor(self, rhs: $struct_name) -> Self::Output {
304                 $struct_name(self.0 | rhs.0)
305             }
306         }
307 
308         impl ::std::ops::BitOrAssign<$struct_name> for $struct_name {
309             fn bitor_assign(&mut self, rhs: $struct_name) {
310                 self.0 = self.0 | rhs.0
311             }
312         }
313 
314         impl ::std::ops::Sub<$struct_name> for &$struct_name {
315             type Output = $struct_name;
316             fn sub(self, rhs: $struct_name) -> Self::Output {
317                 $struct_name(self.0 & !rhs.0)
318             }
319         }
320 
321         impl ::std::ops::SubAssign<$struct_name> for $struct_name {
322             fn sub_assign(&mut self, rhs: $struct_name) {
323                 self.0 = self.0 - rhs.0
324             }
325         }
326 
327         impl ::std::ops::Not for &$struct_name {
328             type Output = $struct_name;
329             fn not(self) -> Self::Output {
330                 $struct_name(self.0 ^ $struct_name::VALID__)
331             }
332         }
333 
334         impl ::std::ops::BitAnd<$struct_name> for $struct_name {
335             type Output = Self;
336             fn bitand(self, rhs: Self) -> Self::Output {
337                 $struct_name(self.0 & rhs.0)
338             }
339         }
340 
341         impl ::std::ops::BitXor<$struct_name> for $struct_name {
342             type Output = Self;
343             fn bitxor(self, rhs: Self) -> Self::Output {
344                 $struct_name(self.0 ^ rhs.0)
345             }
346         }
347 
348         impl ::std::ops::BitOr<$struct_name> for $struct_name {
349             type Output = Self;
350             fn bitor(self, rhs: Self) -> Self::Output {
351                 $struct_name(self.0 | rhs.0)
352             }
353         }
354 
355         impl ::std::ops::Sub<$struct_name> for $struct_name {
356             type Output = Self;
357             fn sub(self, rhs: Self) -> Self::Output {
358                 $struct_name(self.0 & !rhs.0)
359             }
360         }
361 
362         impl ::std::ops::Not for $struct_name {
363             type Output = Self;
364             fn not(self) -> Self::Output {
365                 $struct_name(self.0 ^ Self::VALID__)
366             }
367         }
368 
369         impl From<$struct_name> for $type {
370             fn from(x: $struct_name) -> $type {
371                 x.0
372             }
373         }
374 
375         impl From<$type> for $struct_name {
376             fn from(x: $type) -> Self {
377                 $struct_name(x & Self::VALID__)
378             }
379         }
380     };
381 
382     { $type:ty: $expr:expr } => {
383         ::qemu_api_macros::bits_const_internal! { $type @ ($expr) }
384     };
385 
386     { $type:ty as $int_type:ty: $expr:expr } => {
387         (::qemu_api_macros::bits_const_internal! { $type @ ($expr) }.into_bits()) as $int_type
388     };
389 }
390 
391 #[cfg(test)]
392 mod test {
393     bits! {
394         pub struct InterruptMask(u32) {
395             OE = 1 << 10,
396             BE = 1 << 9,
397             PE = 1 << 8,
398             FE = 1 << 7,
399             RT = 1 << 6,
400             TX = 1 << 5,
401             RX = 1 << 4,
402             DSR = 1 << 3,
403             DCD = 1 << 2,
404             CTS = 1 << 1,
405             RI = 1 << 0,
406 
407             E = bits!(Self as u32: OE | BE | PE | FE),
408             MS = bits!(Self as u32: RI | DSR | DCD | CTS),
409         }
410     }
411 
412     #[test]
test_not()413     pub fn test_not() {
414         assert_eq!(
415             !InterruptMask::from(InterruptMask::RT.0),
416             InterruptMask::E | InterruptMask::MS | InterruptMask::TX | InterruptMask::RX
417         );
418     }
419 
420     #[test]
test_and()421     pub fn test_and() {
422         assert_eq!(
423             InterruptMask::from(0),
424             InterruptMask::MS & InterruptMask::OE
425         )
426     }
427 
428     #[test]
test_or()429     pub fn test_or() {
430         assert_eq!(
431             InterruptMask::E,
432             InterruptMask::OE | InterruptMask::BE | InterruptMask::PE | InterruptMask::FE
433         );
434     }
435 
436     #[test]
test_xor()437     pub fn test_xor() {
438         assert_eq!(
439             InterruptMask::E ^ InterruptMask::BE,
440             InterruptMask::OE | InterruptMask::PE | InterruptMask::FE
441         );
442     }
443 }
444