yaroslavche/bitmask

BitMask, EnumBitMask

v3.1.0 2025-08-28 13:48 UTC

This package is auto-updated.

Last update: 2025-08-28 13:54:01 UTC


README

PHP build codecov Infection MSI PHP

BitMask

PHP library for working with bitmask values

Getting Started

Usually enough for checking bits:

define('READ', 1 << 0);
define('WRITE', 1 << 1);
define('EXECUTE', 1 << 2);

$mask = READ | WRITE | EXECUTE;
echo sprintf('mask: %d', $mask); // mask: 7
if ($mask & READ) {} // if $mask has a single bit READ
$mask &= ~EXECUTE; // remove a single bit from the $mask
$mask |= EXECUTE; // set a single bit to the $mask

But you can try other way with this package:

use BitMask\BitMask;

// two arguments: integer mask (default: 0) and most significant bit for boundaries (default: null) 
$bitmask = new BitMask(READ | WRITE | EXECUTE);
echo sprintf('mask: %d', $bitmask->get()); // mask: 7
if ($bitmask->has(READ)) {}
$bitmask->remove(EXECUTE);
$bitmask->set(EXECUTE);

Exists EnumBitMask, which allows the same using PHP enum: The EnumBitMask allows you to work with bitmasks using PHP enums. It automatically detects if an enum is int-backed and uses the case's value. For int-backed enums, each case must represent a single bit value (e.g., 1, 2, 4, 8, etc.). Otherwise, an InvalidEnumException will be thrown.

use BitMask\EnumBitMask;

enum Permissions
{
    case READ; // Mapped to 1
    case WRITE; // Mapped to 2
    case EXECUTE; // Mapped to 4
}

// Automatically maps UnitEnum based on their position
$bitmask = new EnumBitMask(Permissions::class, 0b111);
echo sprintf('mask: %d', $bitmask->get()); // mask: 7
if ($bitmask->has(Permissions::READ)) {}
$bitmask->remove(Permissions::EXECUTE);
$bitmask->set(Permissions::EXECUTE);

// Works with int-backed enums
enum Flags: int
{
    case User = 1;      // 0b001
    case Admin = 8;     // 0b1000
    case Guest = 32;    // 0b100000
}

$flagmask = new EnumBitMask(Flags::class, Flags::User | Flags::Admin);
echo sprintf('mask: %d', $flagmask->get()); // mask: 9
$flagmask->set(Flags::Guest);

// Throws an InvalidEnumException if a value is not a single bit
enum BadFlags: int
{
    case Bad = 3; // 0b11 - not a single bit
}

new EnumBitMask(BadFlags::class, 3); // Throws InvalidEnumException

EnumBitMask have a factory methods:

# Create a bit mask using one or multiple enum cases
$bitmask = EnumBitMask::create(Permissions::class, Permissions::EXECUTE);

# Create a bit mask using all enum cases
$bitmask = EnumBitMask::all(Permissions::class);

# Create a bit mask with no flags on (equivalent to create with no additional flags)
$bitmask = EnumBitMask::none(Permissions::class);

# Create a bit mask without specific flags
$bitmask = EnumBitMask::without(Permissions::class, Permissions::EXECUTE);

Exists Bits helper with static methods:

use BitMask\Util\Bits;

$mask = 7; // 1 << 0 | 1 << 1 | 1 << 2
$integerMostSignificantBit = Bits::getMostSignificantBit($mask); // int 2
$arraySetBitsIndexes = Bits::getSetBitsIndexes($mask); // array:3 [0, 1, 2]
$arraySetBits = Bits::getSetBits($mask); // array:3 [1, 2, 4]
$string = Bits::toString($mask); // string "111"
$integerBit = Bits::indexToBit(16); // int 65536
$integerIndex = Bits::bitToIndex(65536); // int 16
$boolIsSingleBit = Bits::isSingleBit(8); // true

Installing

Install package via composer

composer require yaroslavche/bitmask

Contributing

Feel free to fork or contribute =)

CI build

$ composer ci:pack

Tests

PHPUnit
$ composer phpunit
$ ./vendor/bin/phpunit
Infection
$ composer infection
$ ./vendor/bin/infection --min-msi=100 --min-covered-msi=100

Benchmarks

$ composer phpbench
$ ./vendor/bin/phpbench run benchmarks --report=default

Static analyzer and code style

PHPStan
$ composer phpstan
$ ./vendor/bin/phpstan analyse src/ -c phpstan.neon --level=9 --no-progress -vvv --memory-limit=1024M
Psalm
$ composer psalm
$ ./vendor/bin/psalm
PHP-CS
Code style check
$ composer phpcs-check
$ ./vendor/bin/php-cs-fixer check --diff
Code style fix
$ composer phpcs-fix
$ ./vendor/bin/php-cs-fixer fix

License

This project is licensed under the MIT License - see the LICENSE file for details