Skip to content

Commit

Permalink
Fixed #33
Browse files Browse the repository at this point in the history
  • Loading branch information
yaroslavche committed Sep 1, 2024
1 parent 0aa29e7 commit 2ec36b6
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/EnumBitMask.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace BitMask;

use BackedEnum;
use BitMask\Exception\InvalidEnumException;
use BitMask\Exception\NotSingleBitException;
use BitMask\Exception\UnknownEnumException;
use BitMask\Util\Bits;
Expand All @@ -19,16 +21,27 @@ final class EnumBitMask implements BitMaskInterface

/**
* @param class-string $enum
* @throws InvalidEnumException
* @throws UnknownEnumException
*/
public function __construct(
private readonly string $enum,
int $mask = 0,
bool $isIntBacked = false,
) {
if (!is_subclass_of($this->enum, UnitEnum::class)) {
throw new UnknownEnumException('EnumBitMask enum must be subclass of UnitEnum');
}
foreach ($this->enum::cases() as $index => $case) {
if ($isIntBacked) {
if (!is_subclass_of($this->enum, BackedEnum::class)) {
throw new InvalidEnumException('Enum must be a backed enum');
}
/** @phpstan-var BackedEnum $case */
if (!is_int($case->value)) {
throw new InvalidEnumException('Enum must be an int-backed enum with integer values');
}
}
$this->map[$case->name] = Bits::indexToBit($index);
}
$this->bitmask = new BitMask($mask, count($this->enum::cases()) - 1);
Expand All @@ -38,7 +51,7 @@ public function __construct(
* Create an instance with given flags on
*
* @param class-string $enum
* @throws UnknownEnumException|NotSingleBitException
* @throws UnknownEnumException|NotSingleBitException|InvalidEnumException
*/
public static function create(string $enum, UnitEnum ...$bits): self
{
Expand All @@ -50,7 +63,7 @@ public static function create(string $enum, UnitEnum ...$bits): self
*
* @psalm-suppress MixedMethodCall, MixedArgument
* @param class-string $enum
* @throws UnknownEnumException|NotSingleBitException
* @throws UnknownEnumException|NotSingleBitException|InvalidEnumException
*/
public static function all(string $enum): self
{
Expand All @@ -62,7 +75,7 @@ public static function all(string $enum): self
*
* @psalm-suppress PossiblyUnusedMethod
* @param class-string $enum
* @throws UnknownEnumException|NotSingleBitException
* @throws UnknownEnumException|NotSingleBitException|InvalidEnumException
*/
public static function none(string $enum): self
{
Expand All @@ -74,7 +87,7 @@ public static function none(string $enum): self
*
* @psalm-suppress PossiblyUnusedMethod
* @param class-string $enum
* @throws UnknownEnumException|NotSingleBitException
* @throws UnknownEnumException|NotSingleBitException|InvalidEnumException
*/
public static function without(string $enum, UnitEnum ...$bits): self
{
Expand Down
9 changes: 9 additions & 0 deletions src/Exception/InvalidEnumException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace BitMask\Exception;

use Exception;

final class InvalidEnumException extends Exception implements BitMaskExceptionInterface {}
22 changes: 22 additions & 0 deletions tests/EnumBitMaskTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace BitMask\Tests;

use BitMask\EnumBitMask;
use BitMask\Exception\InvalidEnumException;
use BitMask\Exception\OutOfRangeException;
use BitMask\Exception\UnknownEnumException;
use BitMask\Tests\fixtures\Enum\BackedInt;
Expand Down Expand Up @@ -174,4 +175,25 @@ public function testWithoutFactory(): void
$enumBitmask = EnumBitMask::without(Permissions::class, Permissions::Delete);
assertSame(7, $enumBitmask->get());
}

public function testIsIntBackedEnumInvalidEnum(): void
{
// UnitEnum
$this->expectException(InvalidEnumException::class);
new EnumBitMask(Permissions::class, 3, isIntBacked: true);
}

public function testIsIntBackedEnum(): void
{
// backed int
$backedIntEnumBitmask = new EnumBitMask(BackedInt::class, 3, isIntBacked: true);
assertTrue($backedIntEnumBitmask->has(BackedInt::Create, BackedInt::Read));
assertFalse($backedIntEnumBitmask->has(BackedInt::Update, BackedInt::Delete));

// backed string
$this->expectException(InvalidEnumException::class);
$backedStringEnumBitmask = new EnumBitMask(BackedString::class, 3, isIntBacked: true);
assertTrue($backedStringEnumBitmask->has(BackedString::Create, BackedString::Read));
assertFalse($backedStringEnumBitmask->has(BackedString::Update, BackedString::Delete));
}
}

0 comments on commit 2ec36b6

Please # to comment.