From 35d40b26c0e02c4278368e8c4bc12cd84a320958 Mon Sep 17 00:00:00 2001 From: Giso Stallenberg Date: Tue, 11 Jun 2024 12:47:13 +0200 Subject: [PATCH] Add factory methods to create an enum bit mask * Add a method to create a bit mask using one or multiple cases * Add a method to create a bit mask using all cases * Add a method to create a bit mask with no flags on * Add a method to create a bit mask without some flags --- src/EnumBitMask.php | 81 +++++++++++++++++++++++++++++++++++---- tests/EnumBitMaskTest.php | 40 +++++++++++++++++++ 2 files changed, 114 insertions(+), 7 deletions(-) diff --git a/src/EnumBitMask.php b/src/EnumBitMask.php index a154f5c..beb8ccf 100644 --- a/src/EnumBitMask.php +++ b/src/EnumBitMask.php @@ -13,7 +13,10 @@ final class EnumBitMask implements BitMaskInterface { private BitMask $bitmask; - /** @var array $map case => bit */ + + /** + * @var array $map case => bit + */ private array $map = []; /** @@ -33,26 +36,88 @@ public function __construct( $this->bitmask = new BitMask($mask, count($this->enum::cases()) - 1); } + /** + * Create an instance with given flags on + * + * @param class-string $enum + * + * @return static + */ + public static function create(string $enum, UnitEnum ...$bits): static + { + return (new static($enum))->set(...$bits); + } + + /** + * Create an instance with all flags on + * + * @param class-string $enum + * + * @return static + */ + public static function all(string $enum): static + { + return self::create($enum, ...$enum::cases()); + } + + /** + * Create an instance with no flags on + * + * @param class-string $enum + * + * @return static + */ + public static function none(string $enum): static + { + return self::create($enum); + } + + /** + * Create an instance without given flags on + * + * @param class-string $enum + * + * @return static + */ + public static function without(string $enum, UnitEnum ...$bits): static + { + return self::all($enum)->remove(...$bits); + } + public function get(): int { return $this->bitmask->get(); } - /** @throws UnknownEnumException|NotSingleBitException */ - public function set(UnitEnum ...$bits): void + /** + * @throws UnknownEnumException|NotSingleBitException + * + * @return $this + */ + public function set(UnitEnum ...$bits): self { $this->has(...$bits); $this->bitmask->set(...$this->enumToInt(...$bits)); + + return $this; } - /** @throws UnknownEnumException|NotSingleBitException */ - public function remove(UnitEnum ...$bits): void + /** + * @throws UnknownEnumException|NotSingleBitException + * + * @return $this + */ + public function remove(UnitEnum ...$bits): self { $this->has(...$bits); $this->bitmask->remove(...$this->enumToInt(...$bits)); + + return $this; } - /** @throws UnknownEnumException|NotSingleBitException */ + /** + * @throws UnknownEnumException|NotSingleBitException + */ public function has(UnitEnum ...$bits): bool { array_walk( @@ -65,7 +130,9 @@ public function has(UnitEnum ...$bits): bool return $this->bitmask->has(...$this->enumToInt(...$bits)); } - /** @return int[] */ + /** + * @return int[] + */ private function enumToInt(UnitEnum ...$bits): array { return array_map(fn(UnitEnum $bit) => $this->map[$bit->name], $bits); diff --git a/tests/EnumBitMaskTest.php b/tests/EnumBitMaskTest.php index afa9c97..6003c2c 100644 --- a/tests/EnumBitMaskTest.php +++ b/tests/EnumBitMaskTest.php @@ -100,4 +100,44 @@ public function testBackedEnum(): void assertFalse($backedIntEnumBitmask->has(BackedInt::Create, BackedInt::Read)); assertTrue($backedIntEnumBitmask->has(BackedInt::Update, BackedInt::Delete)); } + + public function testCreateFactory(): void + { + $enumBitmask = EnumBitMask::create(Permissions::class); + assertSame(0, $enumBitmask->get()); + + $enumBitmask = EnumBitMask::create(Permissions::class, Permissions::Create); + assertSame(1, $enumBitmask->get()); + + $enumBitmask = EnumBitMask::create(Permissions::class, Permissions::Delete); + assertSame(8, $enumBitmask->get()); + + $enumBitmask = EnumBitMask::create(Permissions::class, Permissions::Delete, Permissions::Create); + assertSame(9, $enumBitmask->get()); + + $enumBitmask = EnumBitMask::create(Permissions::class, Permissions::Create, Permissions::Delete); + assertSame(9, $enumBitmask->get()); + + + $this->expectException(UnknownEnumException::class); + EnumBitMask::create(Permissions::class, Unknown::Case); + } + + public function testNoneFactory(): void + { + $enumBitmask = EnumBitMask::none(Permissions::class); + assertSame(0, $enumBitmask->get()); + } + + public function testAllFactory(): void + { + $enumBitmask = EnumBitMask::all(Permissions::class); + assertSame(15, $enumBitmask->get()); + } + + public function testWithoutFactory(): void + { + $enumBitmask = EnumBitMask::without(Permissions::class, Permissions::Delete); + assertSame(7, $enumBitmask->get()); + } }