-
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathBinaryEnumFlags.php
More file actions
112 lines (91 loc) · 2.28 KB
/
Copy pathBinaryEnumFlags.php
File metadata and controls
112 lines (91 loc) · 2.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<?php
declare(strict_types=1);
namespace Reinder83\BinaryFlags;
use BackedEnum;
use Closure;
use Countable;
use Iterator;
use JsonSerializable;
/**
* Enum-aware variant of BinaryFlags.
*
* @template TEnum of BackedEnum
* @implements Iterator<int, TEnum>
*/
abstract class BinaryEnumFlags implements Countable, Iterator, JsonSerializable
{
/** @use Traits\InteractsWithEnumFlags<TEnum> */
use Traits\InteractsWithEnumFlags;
private int $currentPos = 0;
/**
* @param int|TEnum|Mask<TEnum> $mask
*/
public function __construct(int|BackedEnum|Mask $mask = 0, ?Closure $onModify = null)
{
$this->setMask($mask);
if ($onModify !== null) {
$this->setOnModifyCallback($onModify);
}
}
private function iterableMask(): int
{
return $this->mask & static::getAllFlagsMask();
}
/**
* @return TEnum
*/
public function current(): BackedEnum
{
$enumClass = static::getFlagEnumClass();
/** @var TEnum $enum */
$enum = $enumClass::from($this->currentPos);
return $enum;
}
public function next(): void
{
$iterableMask = $this->iterableMask();
$this->currentPos <<= 1;
while (($iterableMask & $this->currentPos) === 0 && $this->currentPos > 0) {
$this->currentPos <<= 1;
}
}
public function key(): int
{
return $this->currentPos;
}
public function valid(): bool
{
return $this->currentPos > 0 && ($this->iterableMask() & $this->currentPos) !== 0;
}
public function rewind(): void
{
$iterableMask = $this->iterableMask();
if ($iterableMask === 0) {
$this->currentPos = 0;
return;
}
$this->currentPos = 1;
while (($iterableMask & $this->currentPos) === 0) {
$this->currentPos <<= 1;
}
}
public function count(): int
{
$count = 0;
$mask = $this->mask;
while ($mask !== 0) {
if (($mask & 1) === 1) {
$count++;
}
$mask >>= 1;
}
return $count;
}
/**
* @return array{mask: int}
*/
public function jsonSerialize(): array
{
return ['mask' => $this->mask];
}
}