1*0e62e4f3SFilipe Xavier // SPDX-License-Identifier: GPL-2.0 2*0e62e4f3SFilipe Xavier 3*0e62e4f3SFilipe Xavier //! Bitflag type generator. 4*0e62e4f3SFilipe Xavier 5*0e62e4f3SFilipe Xavier /// Common helper for declaring bitflag and bitmask types. 6*0e62e4f3SFilipe Xavier /// 7*0e62e4f3SFilipe Xavier /// This macro takes as input: 8*0e62e4f3SFilipe Xavier /// - A struct declaration representing a bitmask type 9*0e62e4f3SFilipe Xavier /// (e.g., `pub struct Permissions(u32)`). 10*0e62e4f3SFilipe Xavier /// - An enumeration declaration representing individual bit flags 11*0e62e4f3SFilipe Xavier /// (e.g., `pub enum Permission { ... }`). 12*0e62e4f3SFilipe Xavier /// 13*0e62e4f3SFilipe Xavier /// And generates: 14*0e62e4f3SFilipe Xavier /// - The struct and enum types with appropriate `#[repr]` attributes. 15*0e62e4f3SFilipe Xavier /// - Implementations of common bitflag operators 16*0e62e4f3SFilipe Xavier /// ([`::core::ops::BitOr`], [`::core::ops::BitAnd`], etc.). 17*0e62e4f3SFilipe Xavier /// - Utility methods such as `.contains()` to check flags. 18*0e62e4f3SFilipe Xavier /// 19*0e62e4f3SFilipe Xavier /// # Examples 20*0e62e4f3SFilipe Xavier /// 21*0e62e4f3SFilipe Xavier /// ``` 22*0e62e4f3SFilipe Xavier /// use kernel::impl_flags; 23*0e62e4f3SFilipe Xavier /// 24*0e62e4f3SFilipe Xavier /// impl_flags!( 25*0e62e4f3SFilipe Xavier /// /// Represents multiple permissions. 26*0e62e4f3SFilipe Xavier /// #[derive(Debug, Clone, Default, Copy, PartialEq, Eq)] 27*0e62e4f3SFilipe Xavier /// pub struct Permissions(u32); 28*0e62e4f3SFilipe Xavier /// 29*0e62e4f3SFilipe Xavier /// /// Represents a single permission. 30*0e62e4f3SFilipe Xavier /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] 31*0e62e4f3SFilipe Xavier /// pub enum Permission { 32*0e62e4f3SFilipe Xavier /// /// Read permission. 33*0e62e4f3SFilipe Xavier /// Read = 1 << 0, 34*0e62e4f3SFilipe Xavier /// 35*0e62e4f3SFilipe Xavier /// /// Write permission. 36*0e62e4f3SFilipe Xavier /// Write = 1 << 1, 37*0e62e4f3SFilipe Xavier /// 38*0e62e4f3SFilipe Xavier /// /// Execute permission. 39*0e62e4f3SFilipe Xavier /// Execute = 1 << 2, 40*0e62e4f3SFilipe Xavier /// } 41*0e62e4f3SFilipe Xavier /// ); 42*0e62e4f3SFilipe Xavier /// 43*0e62e4f3SFilipe Xavier /// // Combine multiple permissions using the bitwise OR (`|`) operator. 44*0e62e4f3SFilipe Xavier /// let mut read_write: Permissions = Permission::Read | Permission::Write; 45*0e62e4f3SFilipe Xavier /// assert!(read_write.contains(Permission::Read)); 46*0e62e4f3SFilipe Xavier /// assert!(read_write.contains(Permission::Write)); 47*0e62e4f3SFilipe Xavier /// assert!(!read_write.contains(Permission::Execute)); 48*0e62e4f3SFilipe Xavier /// assert!(read_write.contains_any(Permission::Read | Permission::Execute)); 49*0e62e4f3SFilipe Xavier /// assert!(read_write.contains_all(Permission::Read | Permission::Write)); 50*0e62e4f3SFilipe Xavier /// 51*0e62e4f3SFilipe Xavier /// // Using the bitwise OR assignment (`|=`) operator. 52*0e62e4f3SFilipe Xavier /// read_write |= Permission::Execute; 53*0e62e4f3SFilipe Xavier /// assert!(read_write.contains(Permission::Execute)); 54*0e62e4f3SFilipe Xavier /// 55*0e62e4f3SFilipe Xavier /// // Masking a permission with the bitwise AND (`&`) operator. 56*0e62e4f3SFilipe Xavier /// let read_only: Permissions = read_write & Permission::Read; 57*0e62e4f3SFilipe Xavier /// assert!(read_only.contains(Permission::Read)); 58*0e62e4f3SFilipe Xavier /// assert!(!read_only.contains(Permission::Write)); 59*0e62e4f3SFilipe Xavier /// 60*0e62e4f3SFilipe Xavier /// // Toggling permissions with the bitwise XOR (`^`) operator. 61*0e62e4f3SFilipe Xavier /// let toggled: Permissions = read_only ^ Permission::Read; 62*0e62e4f3SFilipe Xavier /// assert!(!toggled.contains(Permission::Read)); 63*0e62e4f3SFilipe Xavier /// 64*0e62e4f3SFilipe Xavier /// // Inverting permissions with the bitwise NOT (`!`) operator. 65*0e62e4f3SFilipe Xavier /// let negated = !read_only; 66*0e62e4f3SFilipe Xavier /// assert!(negated.contains(Permission::Write)); 67*0e62e4f3SFilipe Xavier /// assert!(!negated.contains(Permission::Read)); 68*0e62e4f3SFilipe Xavier /// ``` 69*0e62e4f3SFilipe Xavier #[macro_export] 70*0e62e4f3SFilipe Xavier macro_rules! impl_flags { 71*0e62e4f3SFilipe Xavier ( 72*0e62e4f3SFilipe Xavier $(#[$outer_flags:meta])* 73*0e62e4f3SFilipe Xavier $vis_flags:vis struct $flags:ident($ty:ty); 74*0e62e4f3SFilipe Xavier 75*0e62e4f3SFilipe Xavier $(#[$outer_flag:meta])* 76*0e62e4f3SFilipe Xavier $vis_flag:vis enum $flag:ident { 77*0e62e4f3SFilipe Xavier $( 78*0e62e4f3SFilipe Xavier $(#[$inner_flag:meta])* 79*0e62e4f3SFilipe Xavier $name:ident = $value:expr 80*0e62e4f3SFilipe Xavier ),+ $( , )? 81*0e62e4f3SFilipe Xavier } 82*0e62e4f3SFilipe Xavier ) => { 83*0e62e4f3SFilipe Xavier $(#[$outer_flags])* 84*0e62e4f3SFilipe Xavier #[repr(transparent)] 85*0e62e4f3SFilipe Xavier $vis_flags struct $flags($ty); 86*0e62e4f3SFilipe Xavier 87*0e62e4f3SFilipe Xavier $(#[$outer_flag])* 88*0e62e4f3SFilipe Xavier #[repr($ty)] 89*0e62e4f3SFilipe Xavier $vis_flag enum $flag { 90*0e62e4f3SFilipe Xavier $( 91*0e62e4f3SFilipe Xavier $(#[$inner_flag])* 92*0e62e4f3SFilipe Xavier $name = $value 93*0e62e4f3SFilipe Xavier ),+ 94*0e62e4f3SFilipe Xavier } 95*0e62e4f3SFilipe Xavier 96*0e62e4f3SFilipe Xavier impl ::core::convert::From<$flag> for $flags { 97*0e62e4f3SFilipe Xavier #[inline] 98*0e62e4f3SFilipe Xavier fn from(value: $flag) -> Self { 99*0e62e4f3SFilipe Xavier Self(value as $ty) 100*0e62e4f3SFilipe Xavier } 101*0e62e4f3SFilipe Xavier } 102*0e62e4f3SFilipe Xavier 103*0e62e4f3SFilipe Xavier impl ::core::convert::From<$flags> for $ty { 104*0e62e4f3SFilipe Xavier #[inline] 105*0e62e4f3SFilipe Xavier fn from(value: $flags) -> Self { 106*0e62e4f3SFilipe Xavier value.0 107*0e62e4f3SFilipe Xavier } 108*0e62e4f3SFilipe Xavier } 109*0e62e4f3SFilipe Xavier 110*0e62e4f3SFilipe Xavier impl ::core::ops::BitOr for $flags { 111*0e62e4f3SFilipe Xavier type Output = Self; 112*0e62e4f3SFilipe Xavier #[inline] 113*0e62e4f3SFilipe Xavier fn bitor(self, rhs: Self) -> Self::Output { 114*0e62e4f3SFilipe Xavier Self(self.0 | rhs.0) 115*0e62e4f3SFilipe Xavier } 116*0e62e4f3SFilipe Xavier } 117*0e62e4f3SFilipe Xavier 118*0e62e4f3SFilipe Xavier impl ::core::ops::BitOrAssign for $flags { 119*0e62e4f3SFilipe Xavier #[inline] 120*0e62e4f3SFilipe Xavier fn bitor_assign(&mut self, rhs: Self) { 121*0e62e4f3SFilipe Xavier *self = *self | rhs; 122*0e62e4f3SFilipe Xavier } 123*0e62e4f3SFilipe Xavier } 124*0e62e4f3SFilipe Xavier 125*0e62e4f3SFilipe Xavier impl ::core::ops::BitOr<$flag> for $flags { 126*0e62e4f3SFilipe Xavier type Output = Self; 127*0e62e4f3SFilipe Xavier #[inline] 128*0e62e4f3SFilipe Xavier fn bitor(self, rhs: $flag) -> Self::Output { 129*0e62e4f3SFilipe Xavier self | Self::from(rhs) 130*0e62e4f3SFilipe Xavier } 131*0e62e4f3SFilipe Xavier } 132*0e62e4f3SFilipe Xavier 133*0e62e4f3SFilipe Xavier impl ::core::ops::BitOrAssign<$flag> for $flags { 134*0e62e4f3SFilipe Xavier #[inline] 135*0e62e4f3SFilipe Xavier fn bitor_assign(&mut self, rhs: $flag) { 136*0e62e4f3SFilipe Xavier *self = *self | rhs; 137*0e62e4f3SFilipe Xavier } 138*0e62e4f3SFilipe Xavier } 139*0e62e4f3SFilipe Xavier 140*0e62e4f3SFilipe Xavier impl ::core::ops::BitAnd for $flags { 141*0e62e4f3SFilipe Xavier type Output = Self; 142*0e62e4f3SFilipe Xavier #[inline] 143*0e62e4f3SFilipe Xavier fn bitand(self, rhs: Self) -> Self::Output { 144*0e62e4f3SFilipe Xavier Self(self.0 & rhs.0) 145*0e62e4f3SFilipe Xavier } 146*0e62e4f3SFilipe Xavier } 147*0e62e4f3SFilipe Xavier 148*0e62e4f3SFilipe Xavier impl ::core::ops::BitAndAssign for $flags { 149*0e62e4f3SFilipe Xavier #[inline] 150*0e62e4f3SFilipe Xavier fn bitand_assign(&mut self, rhs: Self) { 151*0e62e4f3SFilipe Xavier *self = *self & rhs; 152*0e62e4f3SFilipe Xavier } 153*0e62e4f3SFilipe Xavier } 154*0e62e4f3SFilipe Xavier 155*0e62e4f3SFilipe Xavier impl ::core::ops::BitAnd<$flag> for $flags { 156*0e62e4f3SFilipe Xavier type Output = Self; 157*0e62e4f3SFilipe Xavier #[inline] 158*0e62e4f3SFilipe Xavier fn bitand(self, rhs: $flag) -> Self::Output { 159*0e62e4f3SFilipe Xavier self & Self::from(rhs) 160*0e62e4f3SFilipe Xavier } 161*0e62e4f3SFilipe Xavier } 162*0e62e4f3SFilipe Xavier 163*0e62e4f3SFilipe Xavier impl ::core::ops::BitAndAssign<$flag> for $flags { 164*0e62e4f3SFilipe Xavier #[inline] 165*0e62e4f3SFilipe Xavier fn bitand_assign(&mut self, rhs: $flag) { 166*0e62e4f3SFilipe Xavier *self = *self & rhs; 167*0e62e4f3SFilipe Xavier } 168*0e62e4f3SFilipe Xavier } 169*0e62e4f3SFilipe Xavier 170*0e62e4f3SFilipe Xavier impl ::core::ops::BitXor for $flags { 171*0e62e4f3SFilipe Xavier type Output = Self; 172*0e62e4f3SFilipe Xavier #[inline] 173*0e62e4f3SFilipe Xavier fn bitxor(self, rhs: Self) -> Self::Output { 174*0e62e4f3SFilipe Xavier Self((self.0 ^ rhs.0) & Self::all_bits()) 175*0e62e4f3SFilipe Xavier } 176*0e62e4f3SFilipe Xavier } 177*0e62e4f3SFilipe Xavier 178*0e62e4f3SFilipe Xavier impl ::core::ops::BitXorAssign for $flags { 179*0e62e4f3SFilipe Xavier #[inline] 180*0e62e4f3SFilipe Xavier fn bitxor_assign(&mut self, rhs: Self) { 181*0e62e4f3SFilipe Xavier *self = *self ^ rhs; 182*0e62e4f3SFilipe Xavier } 183*0e62e4f3SFilipe Xavier } 184*0e62e4f3SFilipe Xavier 185*0e62e4f3SFilipe Xavier impl ::core::ops::BitXor<$flag> for $flags { 186*0e62e4f3SFilipe Xavier type Output = Self; 187*0e62e4f3SFilipe Xavier #[inline] 188*0e62e4f3SFilipe Xavier fn bitxor(self, rhs: $flag) -> Self::Output { 189*0e62e4f3SFilipe Xavier self ^ Self::from(rhs) 190*0e62e4f3SFilipe Xavier } 191*0e62e4f3SFilipe Xavier } 192*0e62e4f3SFilipe Xavier 193*0e62e4f3SFilipe Xavier impl ::core::ops::BitXorAssign<$flag> for $flags { 194*0e62e4f3SFilipe Xavier #[inline] 195*0e62e4f3SFilipe Xavier fn bitxor_assign(&mut self, rhs: $flag) { 196*0e62e4f3SFilipe Xavier *self = *self ^ rhs; 197*0e62e4f3SFilipe Xavier } 198*0e62e4f3SFilipe Xavier } 199*0e62e4f3SFilipe Xavier 200*0e62e4f3SFilipe Xavier impl ::core::ops::Not for $flags { 201*0e62e4f3SFilipe Xavier type Output = Self; 202*0e62e4f3SFilipe Xavier #[inline] 203*0e62e4f3SFilipe Xavier fn not(self) -> Self::Output { 204*0e62e4f3SFilipe Xavier Self((!self.0) & Self::all_bits()) 205*0e62e4f3SFilipe Xavier } 206*0e62e4f3SFilipe Xavier } 207*0e62e4f3SFilipe Xavier 208*0e62e4f3SFilipe Xavier impl ::core::ops::BitOr for $flag { 209*0e62e4f3SFilipe Xavier type Output = $flags; 210*0e62e4f3SFilipe Xavier #[inline] 211*0e62e4f3SFilipe Xavier fn bitor(self, rhs: Self) -> Self::Output { 212*0e62e4f3SFilipe Xavier $flags(self as $ty | rhs as $ty) 213*0e62e4f3SFilipe Xavier } 214*0e62e4f3SFilipe Xavier } 215*0e62e4f3SFilipe Xavier 216*0e62e4f3SFilipe Xavier impl ::core::ops::BitAnd for $flag { 217*0e62e4f3SFilipe Xavier type Output = $flags; 218*0e62e4f3SFilipe Xavier #[inline] 219*0e62e4f3SFilipe Xavier fn bitand(self, rhs: Self) -> Self::Output { 220*0e62e4f3SFilipe Xavier $flags(self as $ty & rhs as $ty) 221*0e62e4f3SFilipe Xavier } 222*0e62e4f3SFilipe Xavier } 223*0e62e4f3SFilipe Xavier 224*0e62e4f3SFilipe Xavier impl ::core::ops::BitXor for $flag { 225*0e62e4f3SFilipe Xavier type Output = $flags; 226*0e62e4f3SFilipe Xavier #[inline] 227*0e62e4f3SFilipe Xavier fn bitxor(self, rhs: Self) -> Self::Output { 228*0e62e4f3SFilipe Xavier $flags((self as $ty ^ rhs as $ty) & $flags::all_bits()) 229*0e62e4f3SFilipe Xavier } 230*0e62e4f3SFilipe Xavier } 231*0e62e4f3SFilipe Xavier 232*0e62e4f3SFilipe Xavier impl ::core::ops::Not for $flag { 233*0e62e4f3SFilipe Xavier type Output = $flags; 234*0e62e4f3SFilipe Xavier #[inline] 235*0e62e4f3SFilipe Xavier fn not(self) -> Self::Output { 236*0e62e4f3SFilipe Xavier $flags((!(self as $ty)) & $flags::all_bits()) 237*0e62e4f3SFilipe Xavier } 238*0e62e4f3SFilipe Xavier } 239*0e62e4f3SFilipe Xavier 240*0e62e4f3SFilipe Xavier impl $flags { 241*0e62e4f3SFilipe Xavier /// Returns an empty instance where no flags are set. 242*0e62e4f3SFilipe Xavier #[inline] 243*0e62e4f3SFilipe Xavier pub const fn empty() -> Self { 244*0e62e4f3SFilipe Xavier Self(0) 245*0e62e4f3SFilipe Xavier } 246*0e62e4f3SFilipe Xavier 247*0e62e4f3SFilipe Xavier /// Returns a mask containing all valid flag bits. 248*0e62e4f3SFilipe Xavier #[inline] 249*0e62e4f3SFilipe Xavier pub const fn all_bits() -> $ty { 250*0e62e4f3SFilipe Xavier 0 $( | $value )+ 251*0e62e4f3SFilipe Xavier } 252*0e62e4f3SFilipe Xavier 253*0e62e4f3SFilipe Xavier /// Checks if a specific flag is set. 254*0e62e4f3SFilipe Xavier #[inline] 255*0e62e4f3SFilipe Xavier pub fn contains(self, flag: $flag) -> bool { 256*0e62e4f3SFilipe Xavier (self.0 & flag as $ty) == flag as $ty 257*0e62e4f3SFilipe Xavier } 258*0e62e4f3SFilipe Xavier 259*0e62e4f3SFilipe Xavier /// Checks if at least one of the provided flags is set. 260*0e62e4f3SFilipe Xavier #[inline] 261*0e62e4f3SFilipe Xavier pub fn contains_any(self, flags: $flags) -> bool { 262*0e62e4f3SFilipe Xavier (self.0 & flags.0) != 0 263*0e62e4f3SFilipe Xavier } 264*0e62e4f3SFilipe Xavier 265*0e62e4f3SFilipe Xavier /// Checks if all of the provided flags are set. 266*0e62e4f3SFilipe Xavier #[inline] 267*0e62e4f3SFilipe Xavier pub fn contains_all(self, flags: $flags) -> bool { 268*0e62e4f3SFilipe Xavier (self.0 & flags.0) == flags.0 269*0e62e4f3SFilipe Xavier } 270*0e62e4f3SFilipe Xavier } 271*0e62e4f3SFilipe Xavier }; 272*0e62e4f3SFilipe Xavier } 273