Loading page…
Rust walkthroughs
Loading page…
bitflags::Flags::all and how does it relate to the ! operator for flag manipulation?bitflags::Flags::all returns a flags value with all defined bits set, creating a mask that includes every flag in the definition. The ! operator (bitwise NOT) inverts all bits in a flags value, which when combined with all() allows you to express "all flags except these" in a clear and type-safe way. Together, all() and ! enable common flag manipulation patterns: !Flags::all() means "no flags," !flag means "all flags except this one," and all() - flag (or all() & !flag) means "remove this flag from the complete set."
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Permissions: u32 {
const READ = 0b0001;
const WRITE = 0b0010;
const EXECUTE = 0b0100;
const ADMIN = 0b1000;
}
}
fn main() {
// all() returns all defined flags set
let all_perms = Permissions::all();
println!("All permissions: {:?}", all_perms);
// All permissions: READ | WRITE | EXECUTE | ADMIN
println!("Bits: {:04b}", all_perms.bits());
// Bits: 1111
}all() returns a value with every defined flag combined.
! Operator for Bitwise NOTuse bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Flags: u8 {
const A = 0b0001;
const B = 0b0010;
const C = 0b0100;
const D = 0b1000;
}
}
fn main() {
// ! inverts all bits
let flags = Flags::A | Flags::B;
println!("Original: {:04b}", flags.bits()); // 0011
let inverted = !flags;
println!("Inverted: {:04b}", inverted.bits()); // 1100
// For a u8, ! inverts ALL 8 bits, including undefined ones
// bitflags handles this safely
// !all() gives "no flags"
let none = !Flags::all();
println!("No flags: {:?}", none); // empty
println!("Is empty: {}", none.is_empty());
}The ! operator inverts all bits, including undefined bits in the underlying type.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Permissions: u32 {
const READ = 0b0001;
const WRITE = 0b0010;
const EXECUTE = 0b0100;
}
}
fn main() {
// "All permissions except EXECUTE"
let without_execute = Permissions::all() & !Permissions::EXECUTE;
println!("Without execute: {:?}", without_execute);
// Without execute: READ | WRITE
// This is equivalent to:
let explicit = Permissions::READ | Permissions::WRITE;
assert_eq!(without_execute, explicit);
// "Remove READ from all permissions"
let all_perms = Permissions::all();
let no_read = all_perms & !Permissions::READ;
println!("No read: {:?}", no_read);
// No read: WRITE | EXECUTE
}all() & !flag removes specific flags from the complete set.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct FileFlags: u32 {
const READ = 0b0001;
const WRITE = 0b0010;
const HIDDEN = 0b0100;
const SYSTEM = 0b1000;
}
}
fn main() {
let flags = FileFlags::READ | FileFlags::WRITE;
// Check if specific flag is set
println!("Has READ: {}", flags.contains(FileFlags::READ)); // true
println!("Has HIDDEN: {}", flags.contains(FileFlags::HIDDEN)); // false
// Check if ANY flags are set
println!("Any set: {}", !flags.is_empty()); // true
// Check if NO flags are set
println!("Is empty: {}", flags.is_empty()); // false
// Check if ALL flags are set
println!("Has all: {}", flags.contains(FileFlags::all())); // false
println!("Has all: {}", flags.all().contains(FileFlags::all())); // false
// Check if ALL specified flags are set
let required = FileFlags::READ | FileFlags::WRITE;
println!("Has required: {}", flags.contains(required)); // true
}contains checks if specific flags are set; is_empty checks if no flags are set.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Status: u8 {
const ACTIVE = 0b0001;
const PENDING = 0b0010;
const ERROR = 0b0100;
}
}
fn main() {
// all() - all defined flags
let all_flags = Status::all();
println!("all(): {:?}", all_flags);
// all(): ACTIVE | PENDING | ERROR
// empty() - no flags (explicit method)
let no_flags = Status::empty();
println!("empty(): {:?}", no_flags);
// empty(): (empty)
// !all() - also no flags, but computed
let also_empty = !Status::all();
println!("!all(): {:?}", also_empty);
// !all(): (empty)
// They're equivalent for defined flags
assert_eq!(no_flags, also_empty);
// But the underlying bits differ!
// empty() has bits: 0
// !all() inverts all bits in the type (u8 = 8 bits)
// For u8, !all() would be 0b11111000 (undefined bits inverted too)
// bitflags handles this safely
}empty() and !all() represent "no flags set" but differ in undefined bits.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Access: u32 {
const READ = 0b0001;
const WRITE = 0b0010;
const DELETE = 0b0100;
const SHARE = 0b1000;
}
}
fn remove_flags(original: Access, to_remove: Access) -> Access {
// Remove flags using & and !
original & !to_remove
}
fn main() {
let full_access = Access::all();
// Remove DELETE permission
let safe_access = remove_flags(full_access, Access::DELETE);
println!("Safe access: {:?}", safe_access);
// Safe access: READ | WRITE | SHARE
// Remove multiple flags
let limited = remove_flags(full_access, Access::DELETE | Access::SHARE);
println!("Limited: {:?}", limited);
// Limited: READ | WRITE
// Equivalent to:
let explicit = Access::READ | Access::WRITE;
assert_eq!(limited, explicit);
}& !flags removes specific flags while keeping others.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Options: u8 {
const VERBOSE = 0b0001;
const DEBUG = 0b0010;
const QUIET = 0b0100;
const COLOR = 0b1000;
}
}
fn main() {
let mut opts = Options::empty();
// Add flags with |
opts |= Options::VERBOSE;
opts |= Options::DEBUG;
println!("After adding: {:?}", opts);
// After adding: VERBOSE | DEBUG
// Add multiple at once
opts |= Options::COLOR;
println!("With color: {:?}", opts);
// With color: VERBOSE | DEBUG | COLOR
// Toggle flags with ^
opts ^= Options::DEBUG; // Remove DEBUG (was set)
opts ^= Options::QUIET; // Add QUIET (was not set)
println!("After toggle: {:?}", opts);
// After toggle: VERBOSE | QUIET | COLOR
}|= adds flags; ^= toggles flags.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Config: u32 {
const ENABLED = 0b0001;
const DEBUG = 0b0010;
const LOGGING = 0b0100;
const TRACE = 0b1000;
}
}
fn main() {
// User provides arbitrary flags (maybe from external source)
let user_flags = Config::from_bits_retain(0b1111_1111);
println!("User flags: {:08b}", user_flags.bits());
// User flags: 11111111
// Keep only defined flags using all()
let valid_flags = user_flags & Config::all();
println!("Valid flags: {:?}", valid_flags);
// Valid flags: ENABLED | DEBUG | LOGGING | TRACE
// This filters out undefined bits
// Config::all() is: 0b0000_1111
// & operation: 0b1111_1111 & 0b0000_1111 = 0b0000_1111
// Useful for validating external input
fn sanitize_flags(input: u32) -> Config {
Config::from_bits_retain(input) & Config::all()
}
let sanitized = sanitize_flags(0b1111_0000_1111);
println!("Sanitized: {:?}", sanitize_flags(0b1111_0000_1111));
// Only defined bits remain: ENABLED | DEBUG | LOGGING | TRACE
}& all() filters to only defined flags, useful for sanitizing input.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Features: u32 {
const FEATURE_A = 0b0001;
const FEATURE_B = 0b0010;
const FEATURE_C = 0b0100;
const FEATURE_D = 0b1000;
}
}
fn main() {
let current = Features::FEATURE_A | Features::FEATURE_B | Features::FEATURE_C;
let requested = Features::FEATURE_B | Features::FEATURE_C | Features::FEATURE_D;
// XOR shows flags that differ
let diff = current ^ requested;
println!("Different flags: {:?}", diff);
// Different flags: FEATURE_A | FEATURE_D
// Flags in current but not in requested
let removed = current & !requested;
println!("Removed: {:?}", removed);
// Removed: FEATURE_A
// Flags in requested but not in current
let added = requested & !current;
println!("Added: {:?}", added);
// Added: FEATURE_D
// Flags that are the same
let same = current & requested;
println!("Unchanged: {:?}", same);
// Unchanged: FEATURE_B | FEATURE_C
}^ finds symmetric difference; & ! finds set differences.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Capability: u32 {
const READ = 0b0001;
const WRITE = 0b0010;
const EXECUTE = 0b0100;
const ADMIN = 0b1000;
}
}
fn check_permissions(user_caps: Capability, required: Capability) -> bool {
// User must have ALL required permissions
user_caps.contains(required)
}
fn main() {
let user_caps = Capability::READ | Capability::WRITE;
// Check if user can read and write
let can_read_write = check_permissions(user_caps, Capability::READ | Capability::WRITE);
println!("Can read/write: {}", can_read_write); // true
// Check if user has ALL permissions
let has_all = check_permissions(user_caps, Capability::all());
println!("Has all permissions: {}", has_all); // false
// Check if user has ANY permissions (at least one)
let has_any = user_caps.intersects(Capability::all());
println!("Has any permissions: {}", has_any); // true
// Check if user has NONE of the specified permissions
let has_none = !user_caps.intersects(Capability::ADMIN);
println!("Has no admin: {}", has_none); // true
}all() provides a convenient complete set for permission checks.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Mode: u8 {
const ENABLED = 0b0001;
const ACTIVE = 0b0010;
const RUNNING = 0b0100;
}
}
impl Default for Mode {
fn default() -> Self {
// Default: ENABLED and ACTIVE, not RUNNING
Mode::ENABLED | Mode::ACTIVE
}
}
fn main() {
// Start with default
let mut mode = Mode::default();
println!("Default: {:?}", mode);
// Default: ENABLED | ACTIVE
// "All except RUNNING"
let not_running = Mode::all() & !Mode::RUNNING;
println!("Not running: {:?}", not_running);
// Not running: ENABLED | ACTIVE
// This matches our default!
assert_eq!(mode, not_running);
// Enable RUNNING
mode |= Mode::RUNNING;
println!("Now running: {:?}", mode);
// Now running: ENABLED | ACTIVE | RUNNING
// "Invert to see what's missing"
let missing = !mode;
println!("Missing: {:?}", missing);
// Missing: (empty) - all bits are set
// Wait, that's not right for u8...
// ! inverts ALL bits in the type, including undefined
// bitflags only shows defined flags
// To see undefined bits:
println!("All bits: {:08b}", mode.bits());
println!("Inverted bits: {:08b}", (!mode).bits());
}! inverts all bits; bitflags only displays defined flags.
use bitflags::bitflags;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct FeatureFlags: u32 {
const AUTH = 0b0000_0001;
const CACHE = 0b0000_0010;
const METRICS = 0b0000_0100;
const LOGGING = 0b0000_1000;
const DEBUG = 0b0001_0000;
const TRACE = 0b0010_0000;
}
}
fn configure_features(enabled: FeatureFlags, disabled: FeatureFlags) -> FeatureFlags {
// Start with all features, remove disabled, then ensure enabled
FeatureFlags::all() & !disabled | enabled
}
fn main() {
// Enable specific features
let enabled = FeatureFlags::AUTH | FeatureFlags::CACHE | FeatureFlags::METRICS;
// Disable specific features
let disabled = FeatureFlags::DEBUG | FeatureFlags::TRACE;
// Compute effective flags
let effective = configure_features(enabled, disabled);
println!("Effective: {:?}", effective);
// Effective: AUTH | CACHE | METRICS | LOGGING
// Alternative: start empty, add enabled
let from_empty = FeatureFlags::empty() | enabled;
assert_eq!(enabled, from_empty);
// Remove specific flags from current set
let mut features = FeatureFlags::all();
features.set(FeatureFlags::DEBUG, false); // Remove DEBUG
features.set(FeatureFlags::TRACE, false); // Remove TRACE
println!("Production flags: {:?}", features);
// Production flags: AUTH | CACHE | METRICS | LOGGING
// Using &! syntax
let production = FeatureFlags::all() & !(FeatureFlags::DEBUG | FeatureFlags::TRACE);
assert_eq!(features, production);
}all() & !disabled removes unwanted flags from the complete set.
all() purpose:
The ! operator:
!all() gives "no flags" (conceptually)!flag gives "all bits except this flag's bits"Common patterns:
all(): All flags setempty(): No flags set!all(): Also no flags (computed)all() & !flag: All except this flagflags & !flag: Remove flag from setflags | flag: Add flag to setflags ^ flag: Toggle flagKey operations:
contains(flag): Check if flag is setintersects(flags): Check if ANY of the flags are setis_empty(): Check if NO flags are setset(flag, bool): Set or clear a flagUndefined bits:
! inverts ALL bits in the type (including undefined)all() only includes defined flags& all() filters to only defined bitsfrom_bits_retain to keep undefined bitsType safety:
Key insight: The combination of all() and ! enables expressive flag manipulation patterns that mirror set theory: all() & !flag is "set difference from the universal set," flags & !flag is "remove this flag from the set," and !all() represents the "empty set." The ! operator operates at the bit level (inverting all bits in the underlying type), while all() provides the type-safe complete set of defined flags. This distinction matters because !all() on a u8 type sets bits you didn't define, while empty() is guaranteed to have zero bits set. Use all() for operations on defined flags and empty() for explicitly representing "no flags."