*/ private readonly array $intToEnum; /** * @var int[] * @phpstan-var array */ private readonly array $enumToInt; /** * @param \UnitEnum[] $members * @phpstan-param list $members */ public function __construct( array $members ){ usort($members, fn(\UnitEnum $a, \UnitEnum $b) => $a->name <=> $b->name); //sort by name to ensure consistent ordering (and thus consistent bit assignments) $this->bits = (int) ceil(log(count($members), 2)); $this->intToEnum = $members; //usort strips keys so this is already a list $reversed = []; foreach($this->intToEnum as $int => $enum){ $reversed[spl_object_id($enum)] = $int; } $this->enumToInt = $reversed; } /** * @phpstan-return T|null */ public function intToEnum(int $value) : ?object{ return $this->intToEnum[$value] ?? null; } /** * @phpstan-param T $enum */ public function enumToInt(object $enum) : int{ return $this->enumToInt[spl_object_id($enum)]; } /** * @var self[] * @phpstan-var array */ private static array $cache = []; /** * @phpstan-template TEnum of \UnitEnum * @phpstan-param TEnum $case * * @phpstan-return self */ public static function from(\UnitEnum $case) : self{ $class = $case::class; /** @phpstan-var self|null $metadata */ $metadata = self::$cache[$class] ?? null; if($metadata === null){ /** * PHPStan can't infer this correctly :( https://github.com/phpstan/phpstan/issues/7162 * @phpstan-var list $cases */ $cases = $case::cases(); self::$cache[$class] = $metadata = new self($cases); } return $metadata; } }