diff --git a/src/BitMask.php b/src/BitMask.php index d85507b..8ad6a52 100644 --- a/src/BitMask.php +++ b/src/BitMask.php @@ -37,9 +37,12 @@ public function set(int ...$bits): void /** @throws NotSingleBitException */ public function remove(int ...$bits): void { - array_walk($bits, fn(int $bit) => $this->checkBit($bit)); - array_walk($bits, fn(int $bit) => $this->mask ^= $bit); - // $this->mask &= ~$bit; + foreach ($bits as $bit) { + if ($this->has($bit)) { + $this->mask ^= $bit; + // $this->mask &= ~$bit; + } + } } /** @throws NotSingleBitException */ diff --git a/tests/BitMaskTest.php b/tests/BitMaskTest.php index 827ef66..98beb92 100644 --- a/tests/BitMaskTest.php +++ b/tests/BitMaskTest.php @@ -137,4 +137,14 @@ public function testToString(): void $bitmask->set(8); assertSame('15', (string) $bitmask); } + + public function testRemoveTwice(): void + { + $bitmask = new BitMask(self::READ | self::WRITE | self::EXECUTE); + $bitmask->remove(self::READ); + assertFalse($bitmask->has(self::READ)); + $bitmask->remove(self::READ); + assertFalse($bitmask->has(self::READ)); + assertSame(self::WRITE | self::EXECUTE, $bitmask->get()); + } } diff --git a/tests/EnumBitMaskTest.php b/tests/EnumBitMaskTest.php index afa9c97..2526022 100644 --- a/tests/EnumBitMaskTest.php +++ b/tests/EnumBitMaskTest.php @@ -80,6 +80,40 @@ public function testSetUnset(): void $this->expectException(UnknownEnumException::class); $enumBitmask->remove(Unknown::Case); } + public function testSetTwice(): void + { + $enumBitmask = new EnumBitMask(Permissions::class, 3); + assertTrue($enumBitmask->has(Permissions::Create)); + $enumBitmask->set(Permissions::Create); + assertSame(3, $enumBitmask->get()); + assertTrue($enumBitmask->has(Permissions::Create)); + $enumBitmask->set(Permissions::Create, Permissions::Read); + assertTrue($enumBitmask->has(Permissions::Create)); + assertTrue($enumBitmask->has(Permissions::Read)); + assertSame(3, $enumBitmask->get()); + $enumBitmask->set(Permissions::Update); + assertTrue($enumBitmask->has(Permissions::Update)); + assertSame(7, $enumBitmask->get()); + } + + public function testRemoveTwice(): void + { + $enumBitmask = new EnumBitMask(Permissions::class, 3); + assertTrue($enumBitmask->has(Permissions::Create)); + $enumBitmask->remove(Permissions::Create); + assertSame(2, $enumBitmask->get()); + $enumBitmask->remove(Permissions::Create); + assertSame(2, $enumBitmask->get()); + $enumBitmask->remove(Permissions::Create, Permissions::Read); + assertSame(0, $enumBitmask->get()); + + $enumBitmask->set(...Permissions::cases()); + foreach (Permissions::cases() as $case) { + $enumBitmask->remove($case); + $enumBitmask->remove($case); + } + assertSame(0, $enumBitmask->get()); + } public function testBackedEnum(): void {