xref: /linux/rust/kernel/impl_flags.rs (revision 37a93dd5c49b5fda807fd204edf2547c3493319c)
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