Skip to content

Commit 564d64f

Browse files
hoshinolinajannau
authored andcommitted
rust: types: Add declare_flags_type()
Add a helper macro that can be used to declare bitfield style types. Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 7da0b18 commit 564d64f

1 file changed

Lines changed: 83 additions & 0 deletions

File tree

rust/kernel/types.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,3 +443,86 @@ pub type NotThreadSafe = PhantomData<*mut ()>;
443443
/// [`NotThreadSafe`]: type@NotThreadSafe
444444
#[allow(non_upper_case_globals)]
445445
pub const NotThreadSafe: NotThreadSafe = PhantomData;
446+
447+
/// Helper macro to declare a bitfield style type. The type will automatically
448+
/// gain boolean operator implementations, as well as the `as_raw()` and `contains()`
449+
/// methods, Debug, Copy, Clone, and PartialEq implementations.
450+
///
451+
/// Optionally, a default value can be specified with `= value` syntax, which
452+
/// will add a Default trait implementation.
453+
///
454+
/// # Examples
455+
///
456+
/// ```
457+
/// declare_flags_type! {
458+
/// /// Flags to be used for foo.
459+
/// pub struct FooFlags(u32);
460+
/// }
461+
///
462+
/// declare_flags_type! {
463+
/// /// Flags to be used for bar.
464+
/// pub struct BarFlags(u32) = 0;
465+
/// }
466+
/// ```
467+
macro_rules! declare_flags_type (
468+
(
469+
$(#[$outer:meta])*
470+
$v:vis struct $t:ident ( $base:ty );
471+
$($rest:tt)*
472+
) => {
473+
$(#[$outer])*
474+
#[derive(Debug, Clone, Copy, PartialEq)]
475+
$v struct $t($base);
476+
477+
impl $t {
478+
/// Get the raw representation of this flag.
479+
pub(crate) fn as_raw(self) -> $base {
480+
self.0
481+
}
482+
483+
/// Check whether `flags` is contained in `self`.
484+
pub fn contains(self, flags: Self) -> bool {
485+
(self & flags) == flags
486+
}
487+
}
488+
489+
impl core::ops::BitOr for $t {
490+
type Output = Self;
491+
fn bitor(self, rhs: Self) -> Self::Output {
492+
Self(self.0 | rhs.0)
493+
}
494+
}
495+
496+
impl core::ops::BitAnd for $t {
497+
type Output = Self;
498+
fn bitand(self, rhs: Self) -> Self::Output {
499+
Self(self.0 & rhs.0)
500+
}
501+
}
502+
503+
impl core::ops::Not for $t {
504+
type Output = Self;
505+
fn not(self) -> Self::Output {
506+
Self(!self.0)
507+
}
508+
}
509+
};
510+
(
511+
$(#[$outer:meta])*
512+
$v:vis struct $t:ident ( $base:ty ) = $default:expr;
513+
$($rest:tt)*
514+
) => {
515+
declare_flags_type! {
516+
$(#[$outer])*
517+
$v struct $t ($base);
518+
$($rest)*
519+
}
520+
impl Default for $t {
521+
fn default() -> Self {
522+
Self($default)
523+
}
524+
}
525+
};
526+
);
527+
528+
pub(crate) use declare_flags_type;

0 commit comments

Comments
 (0)