Skip to content

Commit e7a80b7

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 59f3ec0 commit e7a80b7

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

0 commit comments

Comments
 (0)