What is the purpose of 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."

Basic bitflags Definition

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.

The ! Operator for Bitwise NOT

use 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.

Combining all() and ! for Set Operations

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.

Checking Flag Combinations

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.

all() vs Empty vs None

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.

Removing Flags with !

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.

Adding Flags with |

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.

Filtering with all()

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.

Symmetric Difference with ^

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.

all() for Permission Checks

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.

Default Values and Complement

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.

Practical Example: Feature 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.

Synthesis

all() purpose:

  • Returns a flags value with ALL defined bits set
  • Provides a complete set for set operations
  • Useful for "everything except" patterns

The ! operator:

  • Inverts ALL bits in the underlying type (not just defined flags)
  • !all() gives "no flags" (conceptually)
  • !flag gives "all bits except this flag's bits"

Common patterns:

  • all(): All flags set
  • empty(): No flags set
  • !all(): Also no flags (computed)
  • all() & !flag: All except this flag
  • flags & !flag: Remove flag from set
  • flags | flag: Add flag to set
  • flags ^ flag: Toggle flag

Key operations:

  • contains(flag): Check if flag is set
  • intersects(flags): Check if ANY of the flags are set
  • is_empty(): Check if NO flags are set
  • set(flag, bool): Set or clear a flag

Undefined bits:

  • ! inverts ALL bits in the type (including undefined)
  • all() only includes defined flags
  • & all() filters to only defined bits
  • Use from_bits_retain to keep undefined bits

Type safety:

  • bitflags ensures type safety for flag operations
  • Invalid bits are tracked but not displayed
  • Operations work correctly even with undefined bits

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."