Skip to content

Latest commit

 

History

History
338 lines (253 loc) · 9.56 KB

bitmasks.md

File metadata and controls

338 lines (253 loc) · 9.56 KB

Bitmasks

enum Permission {
    use Henzeb\Enumhancer\Concerns\Bitmasks;

    case Create;
    case Read;
    case Update;
    case Delete;
}

Permission::Create->bit(); // returns 1
Permission::Read->bit(); // returns 2
Permission::Update->bit(); // returns 4
Permission::Delete->bit(); // returns 8

Integer backed enums

Enumhancer allows you to use your own bit values by using an integer or string backed enum. This is disabled by default. You can enable it by adding a constant called BIT_VALUES that returns true.

enum PermissionInt: int
{
    use Henzeb\Enumhancer\Concerns\Bitmasks;

    private const BIT_VALUES = true;

    case Create = 8;
    case Read = 16;
    case Update = 32;
    case Delete = 128;
}

PermissionInt::Create->bit(); // returns 8
PermissionInt::Read->bit(); // returns 16
PermissionInt::Update->bit(); // returns 32
PermissionInt::Delete->bit(); // returns 128

Note: when the flag BIT_VALUES is set, each case must have a valid bit set. For example: 7 would throw a fatal error as this consists of the bits 1 2 and 4.

Modifiers

Sometimes, you want to use your enum as a modifier where a combination might result in another case. This is not possible by default, so you need to enable the BIT_MODIFIER flag

enum Permission: int
{
    use Henzeb\Enumhancer\Concerns\Bitmasks;

    private const BIT_VALUES = true;
    
    private const BIT_MODIFIER = true;

    case Nothing = 0;
    case Read = 1;
    case Write = 2;
    case ReadAndWrite = 3;
}

Permission::mask(
    Permission::Read, 
    Permission::Write
)->cases(); // returns [Permission::ReadWrite] 

Bits

When you want to use the bits in a dropdown, you can easily use bits.

// returns [1 => 'Create', 2 => 'Read', 4 => 'Update', 8 => 'Delete']
Permission::bits();

// returns [8 => 'Create', 16 => 'Read', 32 => 'Update', 128 => 'Delete']
PermissionInt::bits();

Note: Just like Dropdown, bits uses Labels where applicable.

Create bitmasks

Enumhancer gives you easy tools to work with bitmasks. Just like everywhere else, if Mappers are being used, any value will be mapped.

mask

To get a mask, simply call the static method on your enum. just like with Comparison, you can add as many enum or values that represent enums as you need.

Permission::mask(); // returns a Bitmask object with value 0
Permission::mask(Permission::Create); // returns Bitmask with value 1
Permission::mask(Permission::Create, 'update'); // returns Bitmask with value 5
Permission::mask(Permission::Create, 'modify'); // throws error

fromMask

To transform a numeric bitmask, retreived from for example a database, into a Bitmask object, you can use fromMask.

Permission::fromMask(0); // returns a Bitmask object with value 0
Permission::fromMask(1); // returns Bitmask with value 1
Permission::fromMask(5); // returns Bitmask with value 5
Permission::fromMask(16); // throws error

PermissionInt::fromMask(32); // returns a Bitmask object with value 32
PermissionInt::fromMask(64); // throws error

numeric bitmasks are validated and can only represent any existing combination of bits corresponding to existing cases.

tryMask

This method works the same as fromMask, but will return a Bitmask with a value of 0 or a specified bitmask instead if an invalid bitmask is given.

Permission::tryMask(null); // returns a Bitmask object with value 0
Permission::tryMask(
    null,
    Permission::Read
); // returns a Bitmask object with value 1
Permission::tryMask(0); // returns a Bitmask object with value 0
Permission::tryMask(
    0,
    Permission::Read
); // returns a Bitmask object with value 0

Permission::tryMask(1); // returns Bitmask with value 1
Permission::tryMask(5); // returns Bitmask with value 5
Permission::tryMask(16); // returns a Bitmask object with value 0
Permission::tryMask(16, 'read'); // returns a Bitmask object with value 1

Permission::tryMask(
    16,
    Permission::Read
); // returns a Bitmask object with value 1
Permission::tryMask(
    16,
    Permission::mask('Read', 'Update')
); // returns a Bitmask object with value 3

PermissionInt::tryMask(32); // returns a Bitmask object with value 32
PermissionInt::tryMask(64); // returns a Bitmask object with value 0
PermissionInt::tryMask(
    64,
    'Read', 'Update'
); // returns a Bitmask object with value 3

Note: If Defaults is configured, tryMask will use that default. You can counteract by passing a null as the second value.

Bitmask operations

The Bitmask object operates a similar to a Flag Bag you see in other libraries. You can easily modify and validate. It is however tied to the enum that created it.

The Bitmask object is also implementing a fluent interface for all methods, unless specified otherwise.

All the methods accept either enums or strings or integers representing the enums either mapped or directly. You can also insert Bitmask instances as (one of) it's argument, as long as the Bitmask belongs to the same enum.

Value

Permission::mask()->value(); // returns 0
Permission::mask('Read')->value(); // returns 2
Permission::mask('Create', 'Read')->value(); // returns 3

Stringable

Bitmask objects are stringable. It will return the value as a string

(string)Permission::mask(); // returns "0"
(string)Permission::mask('Read'); // returns "2"
(string)Permission::mask('Create', 'Read'); // returns "3"

Cases

Returns an array of cases corresponding to the bits set.

Permission::mask()->cases(); // returns []
Permission::mask('Read')->cases(); // returns [Permission::Read]
Permission::mask('Create', 'Read')->cases(); // returns [Permission::Create, Permission::Read]

Set

Permission::mask()->set(Permission::Read); // sets value to 2
Permission::mask('Read')->set(Permission::Create); // sets value to 3
Permission::mask('Read')
    ->set(Permission::mask(Permission::Create)); // sets value to 3
Permission::mask('Read')->set(Permission::Create, 'Update'); // sets value to 7
Permission::mask('Read')->set(Permission::Read); // keeps value as 2

Unset

Permission::mask()->unset(Permission::Read); // keeps value as 0
Permission::mask('Read')->unset(Permission::Read); // sets value to 0
Permission::mask('Read')
             ->unset(Permission::mask(Permission::Read)); // sets value to 0
Permission::mask('Read', 'Update')
             ->unset(Permission::Create, 'Update'); // sets value to 2
Permission::mask('Read')->unset(Permission::Read); // keeps value as 2

Toggle

Toggle toggles between 0 and 1. If a bit is set, it wil unset it and vice versa. You can mix up as many as you like, it will toggle each value individually.

Permission::mask()->toggle(Permission::Read); // sets value to 1
Permission::mask('Read')->toggle(Permission::Read); // sets value to 0
Permission::mask()
            ->toggle(Permission::mask(Permission::Read)); // sets value to 1
Permission::mask('Read', 'Update')
            ->toggle(Permission::Create, 'Update'); // sets value to 3
Permission::mask('Update')->toggle(Permission::Read); // sets value to 6

Clear

Resets the value to 0. This means no bits are set after calling it.

Permission::mask()->clear(); // sets value to 0
Permission::mask('Read')->clear(); // sets value to 0
Permission::mask('Read', 'Update')->clear(); // sets value to 0

Copy

Copy allows you to duplicate the Bitmask. It creates a whole new instance, with the current value, you can modify, without modifying the original one.

Permission::mask()->copy(); // returns new Bitmask instance.

Has

Permission::mask()->has('Read'); // returns false
Permission::mask('Read')->has(Permission::Read); // returns true
Permission::mask('Create')->has('Read'); // returns false

All

Permission::mask()->all(); // returns true
Permission::mask()->all('Read', 'Create'); // returns false
Permission::mask('Read')->all('Read', 'Create'); // returns false
Permission::mask('Read', 'Update', 'Delete')->all('Read', 'Update'); // returns true

Any

Permission::mask()->all(); // returns true
Permission::mask()->all('Read', 'Create'); // returns false
Permission::mask('Read')->all('Read', 'Create'); // returns false
Permission::mask('Read', 'Update', 'Delete')->all('Read', 'Update'); // returns true

Xor

Permission::mask()->xor(); // returns false
Permission::mask()->xor('Read', 'Create'); // returns false
Permission::mask('Read')->xor('Read', 'Create'); // returns true
Permission::mask('Read', 'Update')->xor('Read', 'Update'); // returns false

None

Permission::mask()->none(); // returns true
Permission::mask()->none('Read', 'Create'); // returns true
Permission::mask('Read')->none('Read', 'Create'); // returns false
Permission::mask('Read', 'Update')->none('Delete', 'Create'); // returns true

for

Bitmask does it for you, but if you want to check up front, you can check if the Bitmask belongs to a certain enum.

Permission::mask()->for(Permission::class); // returns true
Permission::mask()->for(PermissionInt::class); // returns false

forOrFail

Does the same as for, but instead throws an exception when it does not match.

Permission::mask()->for(Permission::class); // returns true
Permission::mask()->for(PermissionInt::class); // throws exception

ForEnum

Returns the class name of the enum the Bitmask belongs to.

Permission::mask()->forEnum(); // returns Permission::class
PermissionInt::mask()->forEnum(); // returns PermissionInt::class