macro_rules! impl_flags {
(
$(#[$outer_flags:meta])*
$vis_flags:vis struct $flags:ident($ty:ty);
$(#[$outer_flag:meta])*
$vis_flag:vis enum $flag:ident {
$(
$(#[$inner_flag:meta])*
$name:ident = $value:expr
),+ $( , )?
}
) => { ... };
}Expand description
Common helper for declaring bitflag and bitmask types.
This macro takes as input:
- A struct declaration representing a bitmask type
(e.g.,
pub struct Permissions(u32)). - An enumeration declaration representing individual bit flags
(e.g.,
pub enum Permission { ... }).
And generates:
- The struct and enum types with appropriate
#[repr]attributes. - Implementations of common bitflag operators
(
::core::ops::BitOr,::core::ops::BitAnd, etc.). - Utility methods such as
.contains()to check flags.
ยงExamples
use kernel::impl_flags;
impl_flags!(
/// Represents multiple permissions.
#[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
pub struct Permissions(u32);
/// Represents a single permission.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Permission {
/// Read permission.
Read = 1 << 0,
/// Write permission.
Write = 1 << 1,
/// Execute permission.
Execute = 1 << 2,
}
);
// Combine multiple permissions using the bitwise OR (`|`) operator.
let mut read_write: Permissions = Permission::Read | Permission::Write;
assert!(read_write.contains(Permission::Read));
assert!(read_write.contains(Permission::Write));
assert!(!read_write.contains(Permission::Execute));
assert!(read_write.contains_any(Permission::Read | Permission::Execute));
assert!(read_write.contains_all(Permission::Read | Permission::Write));
// Using the bitwise OR assignment (`|=`) operator.
read_write |= Permission::Execute;
assert!(read_write.contains(Permission::Execute));
// Masking a permission with the bitwise AND (`&`) operator.
let read_only: Permissions = read_write & Permission::Read;
assert!(read_only.contains(Permission::Read));
assert!(!read_only.contains(Permission::Write));
// Toggling permissions with the bitwise XOR (`^`) operator.
let toggled: Permissions = read_only ^ Permission::Read;
assert!(!toggled.contains(Permission::Read));
// Inverting permissions with the bitwise NOT (`!`) operator.
let negated = !read_only;
assert!(negated.contains(Permission::Write));
assert!(!negated.contains(Permission::Read));