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