enum_flag 3.0.0 copy "enum_flag: ^3.0.0" to clipboard
enum_flag: ^3.0.0 copied to clipboard

Portable enum bit flags for Dart with typed FlagSet values, stable bit positions, and int extensions.

enum_flag #

style: very good analysis License: MIT Tests Codecov

Portable, type-safe enum flags for Dart. Use the familiar int extensions or an immutable FlagSet<T> while keeping the same unsigned 32-bit representation on the Dart VM and JavaScript.

Features #

  • Portable masks from 0 through 0xFFFFFFFF.
  • Stable explicit bit positions for databases and APIs.
  • Convenient index-based flags for local, non-persisted state.
  • Typed immutable FlagSet<T> operations.
  • Backwards-compatible extensions on int, int?, and Iterable.
  • Preservation and reporting of unknown bits for forward compatibility.
  • Explicit conversion to and from signed 32-bit storage.

Installation #

dependencies:
  enum_flag: ^3.0.0

Defining flags #

Stable explicit positions #

Declare bitIndex explicitly when a mask is persisted or exchanged with another application. Members can then be reordered without changing their stored values.

import 'package:enum_flag/enum_flag.dart';

enum Permission with EnumFlag {
  read(0),
  write(1),
  execute(2),
  delete(3);

  const Permission(this.bitIndex);

  @override
  final int bitIndex;
}

Every position must be unique and between 0 and 31. Invalid positions throw a RangeError in every build mode, including JavaScript production builds.

Index-based positions #

For state that is never persisted, the mixin uses the declaration index by default:

enum LocalFeature with EnumFlag {
  compactMode, // bitIndex: 0, value: 1
  diagnostics, // bitIndex: 1, value: 2
}

If these values are persisted, never reorder existing members or insert new members before them. Only append new members, or migrate to explicit positions.

Typed FlagSet API #

Create an immutable, typed set from flags or from an unsigned mask:

final permissions = [Permission.read, Permission.execute].flagSet;
final restored = FlagSet<Permission>.fromBits(5);

print(permissions == restored); // true
print(permissions.bits); // 5
print(permissions.contains(Permission.read)); // true
print(permissions.activeFlags(Permission.values));
// [Permission.read, Permission.execute]

All updates return a new value:

final updated = permissions
    .add(Permission.write)
    .remove(Permission.execute)
    .toggle(Permission.delete);

print(updated.bits); // 11

Bulk operations are also available:

final updated = const FlagSet<Permission>.empty()
    .addAll([Permission.read, Permission.write])
    .toggleAll([Permission.write, Permission.execute])
    .removeAll([Permission.read]);

print(updated.bits); // 4

FlagSet<T> stores only the mask. Pass the enum's values list when an operation needs to interpret all known members.

int API #

The v2-style extensions remain first-class APIs:

var bits = noFlags;
bits = bits.addFlag(Permission.read);
bits = bits.addFlags([Permission.write, Permission.execute]);
bits = bits.removeFlag(Permission.execute);

print(bits.hasFlag(Permission.read)); // true
print(bits.hasAnyFlag([Permission.execute, Permission.write])); // true
print(bits.hasAllFlags([Permission.read, Permission.write])); // true
print(bits.getFlags(Permission.values));
// [Permission.read, Permission.write]

Combine iterables into either representation:

final bits = [Permission.read, Permission.write].flag; // 3
final allBits = Permission.values.all; // 15
final set = [Permission.read, Permission.write].flagSet;

Nullable masks retain the v2 helpers:

int? storedBits;

storedBits.hasFlagOrFalse(Permission.read); // false
storedBits.hasAnyFlagOrFalse(Permission.values); // false
storedBits.hasAllFlagsOrFalse(Permission.values); // false
storedBits.orNoFlags(); // 0

Unknown bits #

Masks from a newer producer may contain positions the current enum does not know. They are preserved through FlagSet operations and reported explicitly:

final permissions = FlagSet<Permission>.fromBits(0x13);

print(permissions.unknownBits(Permission.values)); // 16
print(permissions.describe(Permission.values));
// read | write | unknown(0x00000010)

The same behavior is available through int.getUnknownBits() and int.describeFlags().

Signed 32-bit storage #

The canonical representation is unsigned. Use explicit helpers for a database column or protocol that represents the same bits as a signed 32-bit integer:

final stored = FlagSet<Permission>.fromSigned32(-1);

print(stored.bits); // 4294967295 (0xFFFFFFFF)
print(stored.signedBits); // -1

Values outside the corresponding signed or unsigned 32-bit range throw a RangeError; they are never normalized silently.

Debug properties #

print(Permission.read.bitIndex); // 0
print(Permission.read.value); // 1
print(Permission.read.label); // read
print(Permission.read.binary); // 00000001

label always uses the enum declaration name, even if the enum overrides toString(). binary is padded to at least eight characters and grows up to 32 characters for higher positions.

Migrating from v2 #

Most calls continue to compile. Review these intentional changes:

  • Masks and receivers must be unsigned 32-bit values. Convert signed storage with FlagSet.fromSigned32.
  • A flag outside positions 0-31 now throws in release as well as debug builds.
  • label uses the declaration name instead of parsing toString().
  • describeFlags reports unknown bits instead of returning none for a non-zero unknown mask.
  • getFlags and describeFlags now accept any Iterable<T>.
  • Persisted index-based enums should override bitIndex before members are reordered or inserted.

Development and coverage #

Run the same coverage gate used by CI:

dart test --coverage=coverage
dart run coverage:format_coverage \
  --lcov \
  --in=coverage \
  --out=coverage/lcov.info \
  --report-on=lib
dart run tool/check_coverage.dart

The final command fails unless every executable line under lib is covered.

License #

MIT License - see LICENSE for details.

10
likes
160
points
1.53k
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Portable enum bit flags for Dart with typed FlagSet values, stable bit positions, and int extensions.

Repository (GitHub)
View/report issues

Topics

#enum #bitmask #flags

License

MIT (license)

Dependencies

meta

More

Packages that depend on enum_flag