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