What is the purpose of bitflags::Flags::contains_all for comprehensive flag checking?
contains_all checks whether a flags value has all specified bits set, returning true only if every flag in the argument is also present in the value being checked. This is the strictest membership check in bitflags, requiring complete containment rather than partial overlap, and is essential for validating that a value satisfies all requirements from a set of flags.
Basic contains_all Usage
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy, Debug)]
struct Permissions: u32 {
const READ = 0b0001;
const WRITE = 0b0010;
const EXECUTE = 0b0100;
const ADMIN = 0b1000;
}
}
fn basic_usage() {
let read_write = Permissions::READ | Permissions::WRITE;
let all_perms = Permissions::READ | Permissions::WRITE | Permissions::EXECUTE | Permissions::ADMIN;
// contains_all: Does the value have ALL specified flags?
assert!(read_write.contains_all(Permissions::READ));
assert!(read_write.contains_all(Permissions::WRITE));
assert!(read_write.contains_all(Permissions::READ | Permissions::WRITE));
// Does NOT contain all - missing EXECUTE
assert!(!read_write.contains_all(Permissions::READ | Permissions::EXECUTE));
// Does NOT contain all - missing ADMIN
assert!(!read_write.contains_all(Permissions::all()));
// All permissions contains everything
assert!(all_perms.contains_all(Permissions::all()));
}contains_all requires every specified bit to be set in the value.
contains_all vs contains
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Flags: u8 {
const A = 0b0001;
const B = 0b0010;
const C = 0b0100;
const D = 0b1000;
}
}
fn contains_vs_contains_all() {
let value = Flags::A | Flags::B | Flags::C; // 0b0111
// contains: Does value have this ONE flag?
assert!(value.contains(Flags::A)); // Yes, A is set
assert!(value.contains(Flags::B)); // Yes, B is set
assert!(!value.contains(Flags::D)); // No, D is not set
// contains_all: Does value have ALL specified flags?
assert!(value.contains_all(Flags::A)); // Single flag, same as contains
assert!(value.contains_all(Flags::A | Flags::B)); // Both A and B are set
assert!(value.contains_all(Flags::A | Flags::B | Flags::C)); // All three are set
assert!(!value.contains_all(Flags::A | Flags::D)); // D is not set
// Key difference: contains checks one flag, contains_all checks multiple
// contains(Flags::A | Flags::B) is NOT valid - takes only one flag
// contains_all(Flags::A | Flags::B) is valid - checks all flags
}contains is for single flags; contains_all is for multiple flags.
contains_all vs intersects
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Status: u8 {
const ACTIVE = 0b0001;
const PENDING = 0b0010;
const VERIFIED = 0b0100;
const SUSPENDED = 0b1000;
}
}
fn contains_all_vs_intersects() {
let status = Status::ACTIVE | Status::VERIFIED; // 0b0101
// intersects: Is there ANY overlap? (partial)
assert!(status.intersects(Status::ACTIVE | Status::PENDING));
// ACTIVE is set, so intersects returns true even though PENDING is not
assert!(status.intersects(Status::VERIFIED | Status::SUSPENDED));
// VERIFIED is set, so intersects returns true
// contains_all: Are ALL flags set? (complete)
assert!(status.contains_all(Status::ACTIVE | Status::VERIFIED));
// Both ACTIVE and VERIFIED are set
assert!(!status.contains_all(Status::ACTIVE | Status::PENDING));
// ACTIVE is set but PENDING is not
assert!(!status.contains_all(Status::VERIFIED | Status::SUSPENDED));
// VERIFIED is set but SUSPENDED is not
// Summary:
// intersects: "Is ANY of these flags set?" (OR logic)
// contains_all: "Are ALL of these flags set?" (AND logic)
}intersects checks for any overlap; contains_all checks for complete containment.
Permission Checking Pattern
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct FilePermissions: u32 {
const READ = 0b0001;
const WRITE = 0b0010;
const EXECUTE = 0b0100;
const ADMIN = 0b1000;
}
}
struct File {
name: String,
permissions: FilePermissions,
}
fn check_access(file: &File, required: FilePermissions) -> bool {
// Check if user has ALL required permissions
file.permissions.contains_all(required)
}
fn permission_example() {
let readable_file = File {
name: "data.txt".to_string(),
permissions: FilePermissions::READ,
};
let writable_file = File {
name: "output.txt".to_string(),
permissions: FilePermissions::READ | FilePermissions::WRITE,
};
// Check single permission
assert!(check_access(&readable_file, FilePermissions::READ));
assert!(!check_access(&readable_file, FilePermissions::WRITE));
// Check multiple permissions
let read_write = FilePermissions::READ | FilePermissions::WRITE;
assert!(!check_access(&readable_file, read_write)); // Missing WRITE
assert!(check_access(&writable_file, read_write)); // Has both
// Admin can do anything (if checking ADMIN specifically)
let admin_file = File {
name: "system.cfg".to_string(),
permissions: FilePermissions::ADMIN,
};
// Note: ADMIN doesn't automatically imply other permissions
// Application logic must decide how ADMIN interacts with other checks
}Use contains_all to verify that all required permissions are present.
Capability Requirements Pattern
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Capabilities: u32 {
const CAN_READ = 0b0001;
const CAN_WRITE = 0b0010;
const CAN_DELETE = 0b0100;
const CAN_SHARE = 0b1000;
}
}
struct User {
name: String,
capabilities: Capabilities,
}
fn perform_operation(user: &User, operation: &str) -> Result<(), &'static str> {
let required = match operation {
"read" => Capabilities::CAN_READ,
"write" => Capabilities::CAN_WRITE | Capabilities::CAN_READ,
"delete" => Capabilities::CAN_DELETE | Capabilities::CAN_READ,
"share" => Capabilities::CAN_SHARE | Capabilities::CAN_READ,
_ => return Err("Unknown operation"),
};
if user.capabilities.contains_all(required) {
Ok(())
} else {
Err("Insufficient capabilities")
}
}
fn capability_example() {
let reader = User {
name: "reader".to_string(),
capabilities: Capabilities::CAN_READ,
};
let writer = User {
name: "writer".to_string(),
capabilities: Capabilities::CAN_READ | Capabilities::CAN_WRITE,
};
let admin = User {
name: "admin".to_string(),
capabilities: Capabilities::all(),
};
// Read requires only CAN_READ
assert!(perform_operation(&reader, "read").is_ok());
// Write requires CAN_READ and CAN_WRITE
assert!(perform_operation(&reader, "write").is_err()); // Missing CAN_WRITE
assert!(perform_operation(&writer, "write").is_ok()); // Has both
// Delete requires CAN_DELETE and CAN_READ
assert!(perform_operation(&writer, "delete").is_err()); // Missing CAN_DELETE
assert!(perform_operation(&admin, "delete").is_ok()); // Has all
// Admin has everything
assert!(perform_operation(&admin, "share").is_ok());
}Combine multiple capabilities with | and check with contains_all.
Feature Flag Pattern
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Features: u32 {
const FEATURE_A = 0b0001;
const FEATURE_B = 0b0010;
const FEATURE_C = 0b0100;
const PREMIUM = 0b1000;
}
}
struct Config {
features: Features,
}
fn is_feature_enabled(config: &Config, feature: Features) -> bool {
config.features.contains_all(feature)
}
fn require_features(config: &Config, features: Features) -> Result<(), String> {
let missing = features & !config.features;
if missing.is_empty() {
Ok(())
} else {
Err(format!("Missing features: {:?}", missing))
}
}
fn feature_example() {
let basic_config = Config {
features: Features::FEATURE_A | Features::FEATURE_B,
};
let premium_config = Config {
features: Features::all(),
};
// Check single feature
assert!(is_feature_enabled(&basic_config, Features::FEATURE_A));
assert!(!is_feature_enabled(&basic_config, Features::FEATURE_C));
// Check multiple features
assert!(is_feature_enabled(&basic_config, Features::FEATURE_A | Features::FEATURE_B));
assert!(!is_feature_enabled(&basic_config, Features::FEATURE_A | Features::FEATURE_C));
// Require multiple features
assert!(require_features(&basic_config, Features::FEATURE_A | Features::FEATURE_B).is_ok());
assert!(require_features(&basic_config, Features::FEATURE_A | Features::FEATURE_C).is_err());
// Premium has all features
assert!(require_features(&premium_config, Features::all()).is_ok());
}Use contains_all to check if all required features are enabled.
Empty Set Behavior
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Flags: u8 {
const A = 0b0001;
const B = 0b0010;
}
}
fn empty_set_behavior() {
let value = Flags::A | Flags::B;
// contains_all with empty set always returns true
// (All zero flags are set in any value)
assert!(value.contains_all(Flags::empty()));
// This is mathematically consistent:
// "Does value contain all flags in empty set?"
// Yes, vacuously true - there are no flags to check
let empty_value = Flags::empty();
// Even empty value contains all flags from empty set
assert!(empty_value.contains_all(Flags::empty()));
// But empty value does NOT contain any actual flags
assert!(!empty_value.contains_all(Flags::A));
assert!(!empty_value.contains_all(Flags::B));
assert!(!empty_value.contains_all(Flags::A | Flags::B));
}contains_all(Flags::empty()) is always true—empty sets are trivially contained.
All Flags Behavior
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Flags: u8 {
const A = 0b0001;
const B = 0b0010;
const C = 0b0100;
}
}
fn all_flags_behavior() {
// contains_all(Flags::all()) checks if all defined flags are set
let partial = Flags::A | Flags::B;
let complete = Flags::A | Flags::B | Flags::C; // Same as Flags::all()
// partial doesn't contain all flags
assert!(!partial.contains_all(Flags::all()));
assert!(!partial.contains_all(Flags::A | Flags::B | Flags::C)); // Same check
// complete contains all flags
assert!(complete.contains_all(Flags::all()));
assert!(complete.contains_all(Flags::A | Flags::B | Flags::C));
// This is useful for validation: "Is every flag set?"
fn is_complete(flags: Flags) -> bool {
flags.contains_all(Flags::all())
}
assert!(!is_complete(partial));
assert!(is_complete(complete));
}contains_all(Flags::all()) checks if every defined flag is present.
Combining with Other Operations
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Flags: u32 {
const A = 0b0001;
const B = 0b0010;
const C = 0b0100;
const D = 0b1000;
}
}
fn combined_operations() {
let value = Flags::A | Flags::B | Flags::C;
// Check with union
let check = Flags::A | Flags::B;
assert!(value.contains_all(check));
// Check with intersection
let intersection = value & Flags::A;
assert!(intersection.contains_all(Flags::A));
assert!(!intersection.contains_all(Flags::A | Flags::B));
// Check with difference
let difference = value - Flags::A; // B | C
assert!(difference.contains_all(Flags::B | Flags::C));
assert!(!difference.contains_all(Flags::A));
// Toggle and check
let toggled = value ^ Flags::D; // A | B | C | D
assert!(toggled.contains_all(Flags::A | Flags::B | Flags::C | Flags::D));
// Check complement
let complement = !Flags::A;
// complement has B, C, D set (and possibly more bits)
assert!(complement.contains_all(Flags::B | Flags::C | Flags::D));
}contains_all works naturally with bitwise operations.
Finding Missing Flags
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy, Debug)]
struct Permissions: u32 {
const READ = 0b0001;
const WRITE = 0b0010;
const EXECUTE = 0b0100;
}
}
fn find_missing() {
let required = Permissions::READ | Permissions::WRITE | Permissions::EXECUTE;
let available = Permissions::READ | Permissions::WRITE;
if !available.contains_all(required) {
// Find which flags are missing
let missing = required & !available;
println!("Missing permissions: {:?}", missing);
// Missing permissions: EXECUTE
}
// This pattern is useful for reporting errors
fn explain_missing(available: Permissions, required: Permissions) -> Option<String> {
if available.contains_all(required) {
return None;
}
let missing = required & !available;
Some(format!("Missing permissions: {:?}", missing))
}
assert_eq!(
explain_missing(available, required),
Some("Missing permissions: Permissions(0b100)".to_string())
);
assert_eq!(
explain_missing(Permissions::all(), required),
None
);
}Use required & !available to find which flags are missing.
Validation and Error Messages
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy, Debug)]
struct Config: u32 {
const ENABLED = 0b0001;
const VERBOSE = 0b0010;
const DEBUG = 0b0100;
const SECURE = 0b1000;
}
}
#[derive(Debug)]
struct ConfigError {
missing: Config,
}
fn validate_config(config: Config) -> Result<(), ConfigError> {
// Required configuration
let required = Config::ENABLED | Config::SECURE;
if config.contains_all(required) {
Ok(())
} else {
Err(ConfigError {
missing: required & !config,
})
}
}
fn validation_example() {
let valid_config = Config::ENABLED | Config::SECURE | Config::VERBOSE;
let invalid_config = Config::ENABLED | Config::VERBOSE;
assert!(validate_config(valid_config).is_ok());
match validate_config(invalid_config) {
Ok(()) => unreachable!(),
Err(e) => {
println!("Configuration error: missing {:?}", e.missing);
// Configuration error: missing SECURE
}
}
}Provide detailed error messages showing which flags are missing.
Performance Characteristics
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Flags: u64 {
const A = 0b0001;
const B = 0b0010;
// ... potentially 64 different flags
}
}
fn performance() {
let value = Flags::A | Flags::B;
let check = Flags::A;
// contains_all is O(1) - single bitwise operation
// (value.bits & check.bits) == check.bits
// One AND operation and one comparison
// This is extremely fast regardless of number of flags
for _ in 0..1_000_000 {
let _ = value.contains_all(check);
}
// Compare to loop-based checking (O(n) where n is number of flags):
// Slower because it needs to iterate and check each flag
}contains_all is a constant-time bitwise operation.
Type Safety with bitflags
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Status: u32 {
const RUNNING = 0b0001;
const PAUSED = 0b0010;
const STOPPED = 0b0100;
const ERROR = 0b1000;
}
}
bitflags! {
#[derive(Clone, Copy)]
struct Permissions: u32 {
const READ = 0b0001;
const WRITE = 0b0010;
}
}
fn type_safety() {
let status = Status::RUNNING | Status::PAUSED;
let perms = Permissions::READ | Permissions::WRITE;
// Compile error: mismatched types
// status.contains_all(perms); // Won't compile
// Each bitflags type is separate
// Can't mix Status and Permissions
// This prevents accidentally checking wrong flags
}bitflags generates distinct types, preventing accidental mixing of different flag types.
Synthesis
Quick reference:
| Method | Question Answered | Returns True If |
|---|---|---|
contains(Flag) |
Is this one flag set? | That specific bit is 1 |
contains_all(Flags) |
Are ALL these flags set? | All specified bits are 1 |
intersects(Flags) |
Is ANY of these flags set? | Any specified bit is 1 |
is_empty() |
Is no flag set? | All bits are 0 |
Common patterns:
use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy)]
struct Flags: u32 {
const A = 0b0001;
const B = 0b0010;
const C = 0b0100;
}
}
fn patterns() {
let value = Flags::A | Flags::B;
// Single flag check
if value.contains(Flags::A) {
// A is set
}
// Multiple flags check (all required)
if value.contains_all(Flags::A | Flags::B) {
// Both A and B are set
}
// Multiple flags check (any allowed)
if value.intersects(Flags::A | Flags::C) {
// Either A or C is set (A is)
}
// Validate complete set
if value.contains_all(Flags::all()) {
// Every defined flag is set
}
// Find missing flags
let required = Flags::A | Flags::B | Flags::C;
if !value.contains_all(required) {
let missing = required & !value;
// missing contains C
}
}Key insight: contains_all implements the subset operation for flags—it asks "is the argument a subset of the value?" by checking whether all bits set in the argument are also set in the value. This is the strictest containment check, requiring complete overlap rather than any intersection. The implementation is a single bitwise AND followed by an equality comparison: (value.bits & check.bits) == check.bits. This constant-time operation makes it efficient for permission checks, capability validation, and feature flag verification. Use contains_all when you need to ensure that a value satisfies all requirements from a set of flags, as opposed to intersects which checks for any overlap or contains which checks a single flag. The method is particularly useful for validating user capabilities before operations, checking that all required features are enabled, or ensuring that configuration flags are complete.
