Block: split generateStatePermutations into type and state parts

this makes it marginally faster, since we can skip all permutations containing invalid type data.
I measured a performance improvement of about 20% across all blocks.
In addition, this makes it easier to locate where a problem is coming from if invalid inputs are accepted.
This commit is contained in:
Dylan K. Taylor 2023-10-17 11:28:58 +01:00
parent 82d6fc3890
commit b0936a50c1
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D

View File

@ -304,18 +304,32 @@ class Block{
if($bits > Block::INTERNAL_STATE_DATA_BITS){ if($bits > Block::INTERNAL_STATE_DATA_BITS){
throw new \LogicException("Block state data cannot use more than " . Block::INTERNAL_STATE_DATA_BITS . " bits"); throw new \LogicException("Block state data cannot use more than " . Block::INTERNAL_STATE_DATA_BITS . " bits");
} }
for($stateData = 0; $stateData < (1 << $bits); ++$stateData){ for($blockItemStateData = 0; $blockItemStateData < (1 << $this->requiredBlockItemStateDataBits); ++$blockItemStateData){
$v = clone $this; $withType = clone $this;
try{ try{
$v->decodeFullState($stateData); $withType->decodeBlockItemState($blockItemStateData);
if($v->encodeFullState() !== $stateData){ $encoded = $withType->encodeBlockItemState();
throw new \LogicException(static::class . "::decodeStateData() accepts invalid state data (returned " . $v->encodeFullState() . " for input $stateData)"); if($encoded !== $blockItemStateData){
throw new \LogicException(static::class . "::decodeBlockItemState() accepts invalid inputs (returned $encoded for input $blockItemStateData)");
} }
}catch(InvalidSerializedRuntimeDataException){ //invalid property combination, leave it }catch(InvalidSerializedRuntimeDataException){ //invalid property combination, leave it
continue; continue;
} }
yield $v; for($blockOnlyStateData = 0; $blockOnlyStateData < (1 << $this->requiredBlockOnlyStateDataBits); ++$blockOnlyStateData){
$withState = clone $withType;
try{
$withState->decodeBlockOnlyState($blockOnlyStateData);
$encoded = $withState->encodeBlockOnlyState();
if($encoded !== $blockOnlyStateData){
throw new \LogicException(static::class . "::decodeBlockOnlyState() accepts invalid inputs (returned $encoded for input $blockOnlyStateData)");
}
}catch(InvalidSerializedRuntimeDataException){ //invalid property combination, leave it
continue;
}
yield $withState;
}
} }
} }