enum_flag

style: very good analysis License: MIT Tests Codecov

A Dart package to create enums for flags using bitmasks, with a mixin and extensions for easy flag manipulation.

Features

  • 🎯 Type-safe bitmask values via EnumFlag mixin
  • Flag manipulation: addFlag(), removeFlag(), toggleFlag()
  • 🔍 Flag checking: hasFlag(), hasAnyFlag(), hasAllFlags()
  • 📋 Flag retrieval: getFlags() with generic type support
  • 🛠️ Debugging utilities: label, binary, describeFlags()
  • 📦 Constants: noFlags for empty state, all for combined flags

Use Cases

Bitmask flags are ideal when you need to store multiple boolean options in a single integer value. Common scenarios include:

🔐 File/Resource Permissions

enum Permission with EnumFlag { read, write, execute, delete }

// Store user permissions in a single int (e.g., in a database)
final adminPermissions = Permission.values.all; // 15
final guestPermissions = [Permission.read].flag; // 1

// Check access
if (userPermissions.hasFlag(Permission.write)) {
  // Allow editing
}

👥 User Roles & Capabilities

enum Role with EnumFlag { viewer, editor, moderator, admin }

// Users can have multiple roles
final userRoles = [Role.editor, Role.moderator].flag;

if (userRoles.hasAnyFlag([Role.admin, Role.moderator])) {
  // Show moderation panel
}

🚀 Feature Flags

enum Feature with EnumFlag { darkMode, notifications, analytics, betaFeatures }

// Enable features per user or environment
var enabledFeatures = noFlags;
enabledFeatures = enabledFeatures.addFlag(Feature.darkMode);
enabledFeatures = enabledFeatures.addFlag(Feature.notifications);

// Check feature availability
if (enabledFeatures.hasFlag(Feature.betaFeatures)) {
  // Show experimental UI
}

🎮 Game States & Attributes

enum StatusEffect with EnumFlag { poisoned, burning, frozen, stunned, blessed }

// Apply multiple status effects to a character
var playerStatus = noFlags;
playerStatus = playerStatus.addFlag(StatusEffect.poisoned);
playerStatus = playerStatus.addFlag(StatusEffect.burning);

// Check and display active effects
print('Active: ${playerStatus.describeFlags(StatusEffect.values)}');
// Output: 'Active: poisoned | burning'

// Remove effect when healed
playerStatus = playerStatus.removeFlag(StatusEffect.poisoned);

📡 API Response Filtering

enum IncludeField with EnumFlag { metadata, timestamps, relations, stats }

// Client requests specific fields
final requestedFields = [IncludeField.metadata, IncludeField.stats].flag;

// Server checks what to include
if (requestedFields.hasFlag(IncludeField.relations)) {
  // Load and include related entities
}

Installation

dependencies:
  enum_flag: ^2.0.0

Usage

Basic Setup

import 'package:enum_flag/enum_flag.dart';

enum Permission with EnumFlag {
  read,    // value: 1 (binary: 00000001)
  write,   // value: 2 (binary: 00000010)
  execute, // value: 4 (binary: 00000100)
  delete,  // value: 8 (binary: 00001000)
}

Getting Bitmask Values

print(Permission.read.value);   // 1
print(Permission.write.value);  // 2
print(Permission.read.binary);  // '00000001'
print(Permission.read.label);   // 'read'

Combining Flags

// Using bitwise OR
final flags = Permission.read.value | Permission.write.value; // 3

// Using list extension
final flags = [Permission.read, Permission.write].flag; // 3

// Get all enum values combined
final allFlags = Permission.values.all; // 15

Checking Flags

final flags = 3; // read | write

flags.hasFlag(Permission.read);     // true
flags.hasFlag(Permission.execute);  // false

flags.hasAnyFlag([Permission.read, Permission.execute]); // true
flags.hasAllFlags([Permission.read, Permission.write]);  // true

Retrieving Active Flags

final flags = 3;
List<Permission> active = flags.getFlags(Permission.values);
print(active); // [Permission.read, Permission.write]

Manipulating Flags

var flags = noFlags; // Start with no flags (0)

flags = flags.addFlag(Permission.read);    // 1
flags = flags.addFlag(Permission.write);   // 3
flags = flags.removeFlag(Permission.read); // 2
flags = flags.toggleFlag(Permission.write); // 0

Bulk Operations

// Add multiple flags at once
var flags = noFlags.addFlags([Permission.read, Permission.write, Permission.execute]); // 7

// Remove multiple flags at once
flags = flags.removeFlags([Permission.read, Permission.execute]); // 2

// Toggle multiple flags at once
flags = flags.toggleFlags([Permission.write, Permission.delete]); // 8

Null-Safe Operations

int? userFlags = getUserFromDatabase()?.permissions; // May be null

// Safe flag checking (returns false if null)
if (userFlags.hasFlagOrFalse(Permission.read)) {
  // User has read permission
}

// Safe with multiple flags
userFlags.hasAnyFlagOrFalse([Permission.read, Permission.write]); // false if null
userFlags.hasAllFlagsOrFalse([Permission.read, Permission.write]); // false if null

// Get value or default to noFlags
final safeFlags = userFlags.orNoFlags(); // 0 if null

Debugging

print(3.describeFlags(Permission.values)); // 'read | write'
print(0.describeFlags(Permission.values)); // 'none'

API Reference

EnumFlag Mixin

Property Description
value Bitmask value (1 << index)
label Enum name without prefix
binary 8-character binary string

int Extensions

Method Description
hasFlag(flag) Check if single flag is active
hasAnyFlag(flags) Check if any flag is active
hasAllFlags(flags) Check if all flags are active
getFlags<T>(flags) Get list of active flags
addFlag(flag) Return value with flag added
removeFlag(flag) Return value with flag removed
toggleFlag(flag) Return value with flag toggled
addFlags(flags) Add multiple flags at once
removeFlags(flags) Remove multiple flags at once
toggleFlags(flags) Toggle multiple flags at once
describeFlags<T>(flags) Human-readable description

int? Extensions (Null-Safe)

Method Description
hasFlagOrFalse(flag) Check flag, returns false if null
hasAnyFlagOrFalse(flags) Check any flag, returns false if null
hasAllFlagsOrFalse(flags) Check all flags, returns false if null
orNoFlags() Returns value or 0 if null

Constants & Extensions

Name Description
noFlags Constant 0 for empty state
Iterable<EnumFlag>.flag Combined bitmask value
Iterable<EnumFlag>.all Alias for flag

Limitations

  • Maximum of 32 enum values (due to Dart's 32-bit integer operations in JavaScript)
  • An assertion will fail in debug mode if you exceed this limit

License

MIT License - see LICENSE for details.

Libraries

enum_flag