docs/bitmasks.md
# Bitmasks
````php
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.
````php
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
````php
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`.
````php
// 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](dropdown.md), `bits` uses [Labels](labels.md) where applicable.
## Create bitmasks
Enumhancer gives you easy tools to work with bitmasks. Just like everywhere else,
if [Mappers](mappers.md) 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](comparison.md), you can add as many enum or values that represent enums
as you need.
````php
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`.
````php
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.
````php
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](defaults.md) 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
````php
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
````php
(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.
````php
Permission::mask()->cases(); // returns []
Permission::mask('Read')->cases(); // returns [Permission::Read]
Permission::mask('Create', 'Read')->cases(); // returns [Permission::Create, Permission::Read]
````
### Set
````php
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
````php
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.
````php
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.
````php
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.
````php
Permission::mask()->copy(); // returns new Bitmask instance.
````
### Has
````php
Permission::mask()->has('Read'); // returns false
Permission::mask('Read')->has(Permission::Read); // returns true
Permission::mask('Create')->has('Read'); // returns false
````
### All
````php
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
````php
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
````php
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
````php
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.
````php
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.
````php
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.
````php
Permission::mask()->forEnum(); // returns Permission::class
PermissionInt::mask()->forEnum(); // returns PermissionInt::class
````