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] test_not()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] test_and()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] test_or()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] test_xor()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