Skip to content

Commit 35f51d6

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 48c1c8e commit 35f51d6

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
@@ -602,3 +602,86 @@ pub type NotThreadSafe = PhantomData<*mut ()>;
602602
/// [`NotThreadSafe`]: type@NotThreadSafe
603603
#[allow(non_upper_case_globals)]
604604
pub const NotThreadSafe: NotThreadSafe = PhantomData;
605+
606+
/// Helper macro to declare a bitfield style type. The type will automatically
607+
/// gain boolean operator implementations, as well as the `as_raw()` and `contains()`
608+
/// methods, Debug, Copy, Clone, and PartialEq implementations.
609+
///
610+
/// Optionally, a default value can be specified with `= value` syntax, which
611+
/// will add a Default trait implementation.
612+
///
613+
/// # Examples
614+
///
615+
/// ```
616+
/// declare_flags_type! {
617+
/// /// Flags to be used for foo.
618+
/// pub struct FooFlags(u32);
619+
/// }
620+
///
621+
/// declare_flags_type! {
622+
/// /// Flags to be used for bar.
623+
/// pub struct BarFlags(u32) = 0;
624+
/// }
625+
/// ```
626+
macro_rules! declare_flags_type (
627+
(
628+
$(#[$outer:meta])*
629+
$v:vis struct $t:ident ( $base:ty );
630+
$($rest:tt)*
631+
) => {
632+
$(#[$outer])*
633+
#[derive(Debug, Clone, Copy, PartialEq)]
634+
$v struct $t($base);
635+
636+
impl $t {
637+
/// Get the raw representation of this flag.
638+
pub(crate) fn as_raw(self) -> $base {
639+
self.0
640+
}
641+
642+
/// Check whether `flags` is contained in `self`.
643+
pub fn contains(self, flags: Self) -> bool {
644+
(self & flags) == flags
645+
}
646+
}
647+
648+
impl core::ops::BitOr for $t {
649+
type Output = Self;
650+
fn bitor(self, rhs: Self) -> Self::Output {
651+
Self(self.0 | rhs.0)
652+
}
653+
}
654+
655+
impl core::ops::BitAnd for $t {
656+
type Output = Self;
657+
fn bitand(self, rhs: Self) -> Self::Output {
658+
Self(self.0 & rhs.0)
659+
}
660+
}
661+
662+
impl core::ops::Not for $t {
663+
type Output = Self;
664+
fn not(self) -> Self::Output {
665+
Self(!self.0)
666+
}
667+
}
668+
};
669+
(
670+
$(#[$outer:meta])*
671+
$v:vis struct $t:ident ( $base:ty ) = $default:expr;
672+
$($rest:tt)*
673+
) => {
674+
declare_flags_type! {
675+
$(#[$outer])*
676+
$v struct $t ($base);
677+
$($rest)*
678+
}
679+
impl Default for $t {
680+
fn default() -> Self {
681+
Self($default)
682+
}
683+
}
684+
};
685+
);
686+
687+
pub(crate) use declare_flags_type;

0 commit comments

Comments
 (0)