Skip to content

Commit 8fd5717

Browse files
committed
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 77b7ece commit 8fd5717

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
@@ -635,3 +635,86 @@ pub struct False;
635635

636636
// SAFETY: This is one of the only two implementations of `Bool`.
637637
unsafe impl Bool for False {}
638+
639+
/// Helper macro to declare a bitfield style type. The type will automatically
640+
/// gain boolean operator implementations, as well as the `as_raw()` and `contains()`
641+
/// methods, Debug, Copy, Clone, and PartialEq implementations.
642+
///
643+
/// Optionally, a default value can be specified with `= value` syntax, which
644+
/// will add a Default trait implementation.
645+
///
646+
/// # Examples
647+
///
648+
/// ```
649+
/// declare_flags_type! {
650+
/// /// Flags to be used for foo.
651+
/// pub struct FooFlags(u32);
652+
/// }
653+
///
654+
/// declare_flags_type! {
655+
/// /// Flags to be used for bar.
656+
/// pub struct BarFlags(u32) = 0;
657+
/// }
658+
/// ```
659+
macro_rules! declare_flags_type (
660+
(
661+
$(#[$outer:meta])*
662+
$v:vis struct $t:ident ( $base:ty );
663+
$($rest:tt)*
664+
) => {
665+
$(#[$outer])*
666+
#[derive(Debug, Clone, Copy, PartialEq)]
667+
$v struct $t($base);
668+
669+
impl $t {
670+
/// Get the raw representation of this flag.
671+
pub(crate) fn as_raw(self) -> $base {
672+
self.0
673+
}
674+
675+
/// Check whether `flags` is contained in `self`.
676+
pub fn contains(self, flags: Self) -> bool {
677+
(self & flags) == flags
678+
}
679+
}
680+
681+
impl core::ops::BitOr for $t {
682+
type Output = Self;
683+
fn bitor(self, rhs: Self) -> Self::Output {
684+
Self(self.0 | rhs.0)
685+
}
686+
}
687+
688+
impl core::ops::BitAnd for $t {
689+
type Output = Self;
690+
fn bitand(self, rhs: Self) -> Self::Output {
691+
Self(self.0 & rhs.0)
692+
}
693+
}
694+
695+
impl core::ops::Not for $t {
696+
type Output = Self;
697+
fn not(self) -> Self::Output {
698+
Self(!self.0)
699+
}
700+
}
701+
};
702+
(
703+
$(#[$outer:meta])*
704+
$v:vis struct $t:ident ( $base:ty ) = $default:expr;
705+
$($rest:tt)*
706+
) => {
707+
declare_flags_type! {
708+
$(#[$outer])*
709+
$v struct $t ($base);
710+
$($rest)*
711+
}
712+
impl Default for $t {
713+
fn default() -> Self {
714+
Self($default)
715+
}
716+
}
717+
};
718+
);
719+
720+
pub(crate) use declare_flags_type;

0 commit comments

Comments
 (0)