Optimize how OrderedTimeCodec rearranges bytes and validates instances

This commit is contained in:
Ben Ramsey
2020-01-13 16:33:28 -06:00
parent 12a2b0680d
commit 0b64d6d995
2 changed files with 27 additions and 30 deletions
+13 -20
View File
@@ -16,7 +16,7 @@ namespace Ramsey\Uuid\Codec;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
@@ -50,16 +50,15 @@ class OrderedTimeCodec extends StringCodec
public function encodeBinary(UuidInterface $uuid): string
{
if (
$uuid->getVariant() !== Uuid::RFC_4122
|| $uuid->getVersion() !== Uuid::UUID_TYPE_TIME
|| !($uuid->getFields() instanceof FieldsInterface)
!($uuid->getFields() instanceof Rfc4122FieldsInterface)
|| $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
) {
throw new InvalidArgumentException(
'Expected RFC 4122 version 1 (time-based) UUID'
);
}
/** @var FieldsInterface $fields */
/** @var Rfc4122FieldsInterface $fields */
$fields = $uuid->getFields();
$optimized = [
@@ -92,24 +91,18 @@ class OrderedTimeCodec extends StringCodec
);
}
$unpacked = unpack('H*', $bytes);
// Rearrange the bytes to their original order.
$rearrangedBytes = substr($bytes, 4, 2)
. substr($bytes, 6, 2)
. substr($bytes, 2, 2)
. substr($bytes, 0, 2)
. substr($bytes, 8);
assert(is_string($unpacked[1]));
$hex = $unpacked[1];
// Rearrange the fields to their original order
$hex = substr($hex, 8, 4)
. substr($hex, 12, 4)
. substr($hex, 4, 4)
. substr($hex, 0, 4)
. substr($hex, 16);
$uuid = $this->decode($hex);
$uuid = parent::decodeBytes($rearrangedBytes);
if (
$uuid->getVariant() !== Uuid::RFC_4122
|| $uuid->getVersion() !== Uuid::UUID_TYPE_TIME
!($uuid->getFields() instanceof Rfc4122FieldsInterface)
|| $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
) {
throw new UnsupportedOperationException(
'Attempting to decode a non-time-based UUID using '
+14 -10
View File
@@ -9,13 +9,17 @@ use PHPUnit\Framework\MockObject\MockObject;
use Ramsey\Uuid\Builder\DefaultUuidBuilder;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\OrderedTimeCodec;
use Ramsey\Uuid\Converter\Number\GenericNumberConverter;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\Time\GenericTimeConverter;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Nonstandard\Fields as NonstandardFields;
use Ramsey\Uuid\Nonstandard\UuidBuilder;
use Ramsey\Uuid\Rfc4122\Fields;
use Ramsey\Uuid\Test\TestCase;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidFactory;
use Ramsey\Uuid\UuidInterface;
@@ -120,7 +124,8 @@ class OrderedTimeCodecTest extends TestCase
{
$bytes = (string) hex2bin($this->optimizedHex);
$numberConverter = Mockery::mock(NumberConverterInterface::class);
$calculator = new BrickMathCalculator();
$numberConverter = new GenericNumberConverter($calculator);
$timeConverter = Mockery::mock(TimeConverterInterface::class);
$builder = new DefaultUuidBuilder($numberConverter, $timeConverter);
$codec = new OrderedTimeCodec($builder);
@@ -138,6 +143,7 @@ class OrderedTimeCodecTest extends TestCase
{
$nonRfc4122Uuid = '58e0a7d7-eebc-11d8-d669-0800200c9a66';
$fields = new NonstandardFields((string) hex2bin(str_replace('-', '', $nonRfc4122Uuid)));
$numberConverter = Mockery::mock(NumberConverterInterface::class);
$timeConverter = Mockery::mock(TimeConverterInterface::class);
$builder = new DefaultUuidBuilder($numberConverter, $timeConverter);
@@ -146,6 +152,7 @@ class OrderedTimeCodecTest extends TestCase
$uuid = Mockery::mock(UuidInterface::class, [
'getVariant' => 0,
'toString' => $nonRfc4122Uuid,
'getFields' => $fields,
]);
$this->expectException(InvalidArgumentException::class);
@@ -183,15 +190,12 @@ class OrderedTimeCodecTest extends TestCase
$nonRfc4122OptimizedHex = '11d8eebc58e0a7d716690800200c9a66';
$bytes = (string) hex2bin($nonRfc4122OptimizedHex);
$uuid = Mockery::mock(UuidInterface::class, [
'getVariant' => Uuid::RESERVED_NCS,
]);
$calculator = new BrickMathCalculator();
$numberConverter = new GenericNumberConverter($calculator);
$timeConverter = new GenericTimeConverter($calculator);
$builder = new UuidBuilder($numberConverter, $timeConverter);
$codec = Mockery::mock(OrderedTimeCodec::class, [
'decode' => $uuid,
]);
$codec->shouldReceive('decodeBytes')->passthru();
$codec = new OrderedTimeCodec($builder);
$this->expectException(UnsupportedOperationException::class);
$this->expectExceptionMessage(