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