Skip to content

Commit 245d78a

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 69c5b7d commit 245d78a

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
@@ -573,3 +573,86 @@ pub type NotThreadSafe = PhantomData<*mut ()>;
573573
/// [`NotThreadSafe`]: type@NotThreadSafe
574574
#[allow(non_upper_case_globals)]
575575
pub const NotThreadSafe: NotThreadSafe = PhantomData;
576+
577+
/// Helper macro to declare a bitfield style type. The type will automatically
578+
/// gain boolean operator implementations, as well as the `as_raw()` and `contains()`
579+
/// methods, Debug, Copy, Clone, and PartialEq implementations.
580+
///
581+
/// Optionally, a default value can be specified with `= value` syntax, which
582+
/// will add a Default trait implementation.
583+
///
584+
/// # Examples
585+
///
586+
/// ```
587+
/// declare_flags_type! {
588+
/// /// Flags to be used for foo.
589+
/// pub struct FooFlags(u32);
590+
/// }
591+
///
592+
/// declare_flags_type! {
593+
/// /// Flags to be used for bar.
594+
/// pub struct BarFlags(u32) = 0;
595+
/// }
596+
/// ```
597+
macro_rules! declare_flags_type (
598+
(
599+
$(#[$outer:meta])*
600+
$v:vis struct $t:ident ( $base:ty );
601+
$($rest:tt)*
602+
) => {
603+
$(#[$outer])*
604+
#[derive(Debug, Clone, Copy, PartialEq)]
605+
$v struct $t($base);
606+
607+
impl $t {
608+
/// Get the raw representation of this flag.
609+
pub(crate) fn as_raw(self) -> $base {
610+
self.0
611+
}
612+
613+
/// Check whether `flags` is contained in `self`.
614+
pub fn contains(self, flags: Self) -> bool {
615+
(self & flags) == flags
616+
}
617+
}
618+
619+
impl core::ops::BitOr for $t {
620+
type Output = Self;
621+
fn bitor(self, rhs: Self) -> Self::Output {
622+
Self(self.0 | rhs.0)
623+
}
624+
}
625+
626+
impl core::ops::BitAnd for $t {
627+
type Output = Self;
628+
fn bitand(self, rhs: Self) -> Self::Output {
629+
Self(self.0 & rhs.0)
630+
}
631+
}
632+
633+
impl core::ops::Not for $t {
634+
type Output = Self;
635+
fn not(self) -> Self::Output {
636+
Self(!self.0)
637+
}
638+
}
639+
};
640+
(
641+
$(#[$outer:meta])*
642+
$v:vis struct $t:ident ( $base:ty ) = $default:expr;
643+
$($rest:tt)*
644+
) => {
645+
declare_flags_type! {
646+
$(#[$outer])*
647+
$v struct $t ($base);
648+
$($rest)*
649+
}
650+
impl Default for $t {
651+
fn default() -> Self {
652+
Self($default)
653+
}
654+
}
655+
};
656+
);
657+
658+
pub(crate) use declare_flags_type;

0 commit comments

Comments
 (0)