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