mirror of
https://github.com/ramsey/uuid.git
synced 2026-06-17 16:26:51 +03:00
feat: add new BinaryUtils::applyVersionAndVariant() method
This commit is contained in:
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
a date/time value.
|
||||
* Introduce `Ramsey\Uuid\Variant` enum to represent the variant field.
|
||||
* Introduce `Ramsey\Uuid\Rfc4122\Version` enum to represent the version field.
|
||||
* Add new static method `Ramsey\Uuid\BinaryUtils::applyVersionAndVariant()`.
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@ namespace Ramsey\Uuid;
|
||||
|
||||
use Ramsey\Uuid\Rfc4122\Version;
|
||||
|
||||
use function pack;
|
||||
use function substr;
|
||||
use function substr_replace;
|
||||
use function unpack;
|
||||
|
||||
/**
|
||||
* Provides binary math utilities
|
||||
*/
|
||||
@@ -64,4 +69,38 @@ class BinaryUtils
|
||||
|
||||
return $timeHi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the RFC 4122 version number and variant field to the 128-bit
|
||||
* integer (as a 16-byte string) provided
|
||||
*
|
||||
* @param non-empty-string $bytes A 128-bit integer (16-byte string) to
|
||||
* which the RFC 4122 version number and variant field will be applied,
|
||||
* making the number a valid UUID
|
||||
* @param Version $version The RFC 4122 version to apply
|
||||
*
|
||||
* @return non-empty-string A 16-byte string with the UUID version and variant applied
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function applyVersionAndVariant(
|
||||
string $bytes,
|
||||
Version $version,
|
||||
Variant $variant = Variant::Rfc4122
|
||||
): string {
|
||||
/** @var array $unpackedTime */
|
||||
$unpackedTime = unpack('n*', substr($bytes, 6, 2));
|
||||
$timeHi = (int) $unpackedTime[1];
|
||||
$timeHiAndVersion = pack('n*', self::applyVersion($timeHi, $version));
|
||||
|
||||
/** @var array $unpackedClockSeq */
|
||||
$unpackedClockSeq = unpack('n*', substr($bytes, 8, 2));
|
||||
$clockSeqHi = (int) $unpackedClockSeq[1];
|
||||
$clockSeqHiAndReserved = pack('n*', self::applyVariant($clockSeqHi, $variant));
|
||||
|
||||
$bytes = substr_replace($bytes, $timeHiAndVersion, 6, 2);
|
||||
|
||||
/** @var non-empty-string */
|
||||
return substr_replace($bytes, $clockSeqHiAndReserved, 8, 2);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-19
@@ -35,12 +35,9 @@ use Ramsey\Uuid\Validator\ValidatorInterface;
|
||||
|
||||
use function bin2hex;
|
||||
use function hex2bin;
|
||||
use function pack;
|
||||
use function str_pad;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
use function substr_replace;
|
||||
use function unpack;
|
||||
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
@@ -484,25 +481,12 @@ class UuidFactory implements UuidFactoryInterface
|
||||
*/
|
||||
private function uuidFromBytesAndVersion(string $bytes, Version $version): UuidInterface
|
||||
{
|
||||
/** @var array $unpackedTime */
|
||||
$unpackedTime = unpack('n*', substr($bytes, 6, 2));
|
||||
$timeHi = (int) $unpackedTime[1];
|
||||
$timeHiAndVersion = pack('n*', BinaryUtils::applyVersion($timeHi, $version));
|
||||
|
||||
/** @var array $unpackedClockSeq */
|
||||
$unpackedClockSeq = unpack('n*', substr($bytes, 8, 2));
|
||||
$clockSeqHi = (int) $unpackedClockSeq[1];
|
||||
$clockSeqHiAndReserved = pack('n*', BinaryUtils::applyVariant($clockSeqHi));
|
||||
|
||||
$bytes = substr_replace($bytes, $timeHiAndVersion, 6, 2);
|
||||
|
||||
/** @var non-empty-string $bytes */
|
||||
$bytes = substr_replace($bytes, $clockSeqHiAndReserved, 8, 2);
|
||||
$bytesWithVariantAndVersion = BinaryUtils::applyVersionAndVariant($bytes, $version);
|
||||
|
||||
if ($this->isDefaultFeatureSet) {
|
||||
return LazyUuidFromString::fromBytes($bytes);
|
||||
return LazyUuidFromString::fromBytes($bytesWithVariantAndVersion);
|
||||
}
|
||||
|
||||
return $this->uuid($bytes);
|
||||
return $this->uuid($bytesWithVariantAndVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ use Ramsey\Uuid\BinaryUtils;
|
||||
use Ramsey\Uuid\Rfc4122\Version;
|
||||
use Ramsey\Uuid\Variant;
|
||||
|
||||
use function bin2hex;
|
||||
use function dechex;
|
||||
use function hex2bin;
|
||||
|
||||
class BinaryUtilsTest extends TestCase
|
||||
{
|
||||
@@ -30,6 +32,19 @@ class BinaryUtilsTest extends TestCase
|
||||
$this->assertSame($expectedHex, dechex(BinaryUtils::applyVariant($clockSeq, $variant)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param non-empty-string $bytes
|
||||
*
|
||||
* @dataProvider provideVersionAndVariantTestValues
|
||||
*/
|
||||
public function testApplyVersionAndVariant(
|
||||
string $bytes,
|
||||
Version $version,
|
||||
string $expectedHex
|
||||
): void {
|
||||
$this->assertSame($expectedHex, bin2hex(BinaryUtils::applyVersionAndVariant($bytes, $version)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<array{timeHi: int, version: Version, expectedInt: int, expectedHex: string}>
|
||||
*/
|
||||
@@ -66,6 +81,24 @@ class BinaryUtilsTest extends TestCase
|
||||
'expectedInt' => 21481,
|
||||
'expectedHex' => '53e9',
|
||||
],
|
||||
[
|
||||
'timeHi' => 1001,
|
||||
'version' => Version::ReorderedTime,
|
||||
'expectedInt' => 25577,
|
||||
'expectedHex' => '63e9',
|
||||
],
|
||||
[
|
||||
'timeHi' => 1001,
|
||||
'version' => Version::UnixTime,
|
||||
'expectedInt' => 29673,
|
||||
'expectedHex' => '73e9',
|
||||
],
|
||||
[
|
||||
'timeHi' => 1001,
|
||||
'version' => Version::Custom,
|
||||
'expectedInt' => 33769,
|
||||
'expectedHex' => '83e9',
|
||||
],
|
||||
[
|
||||
'timeHi' => 65535,
|
||||
'version' => Version::Time,
|
||||
@@ -96,6 +129,24 @@ class BinaryUtilsTest extends TestCase
|
||||
'expectedInt' => 24575,
|
||||
'expectedHex' => '5fff',
|
||||
],
|
||||
[
|
||||
'timeHi' => 65535,
|
||||
'version' => Version::ReorderedTime,
|
||||
'expectedInt' => 28671,
|
||||
'expectedHex' => '6fff',
|
||||
],
|
||||
[
|
||||
'timeHi' => 65535,
|
||||
'version' => Version::UnixTime,
|
||||
'expectedInt' => 32767,
|
||||
'expectedHex' => '7fff',
|
||||
],
|
||||
[
|
||||
'timeHi' => 65535,
|
||||
'version' => Version::Custom,
|
||||
'expectedInt' => 36863,
|
||||
'expectedHex' => '8fff',
|
||||
],
|
||||
[
|
||||
'timeHi' => 0,
|
||||
'version' => Version::Time,
|
||||
@@ -126,6 +177,24 @@ class BinaryUtilsTest extends TestCase
|
||||
'expectedInt' => 20480,
|
||||
'expectedHex' => '5000',
|
||||
],
|
||||
[
|
||||
'timeHi' => 0,
|
||||
'version' => Version::ReorderedTime,
|
||||
'expectedInt' => 24576,
|
||||
'expectedHex' => '6000',
|
||||
],
|
||||
[
|
||||
'timeHi' => 0,
|
||||
'version' => Version::UnixTime,
|
||||
'expectedInt' => 28672,
|
||||
'expectedHex' => '7000',
|
||||
],
|
||||
[
|
||||
'timeHi' => 0,
|
||||
'version' => Version::Custom,
|
||||
'expectedInt' => 32768,
|
||||
'expectedHex' => '8000',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -257,4 +326,56 @@ class BinaryUtilsTest extends TestCase
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<array{bytes: non-empty-string, version: Version, expectedHex: non-empty-string}>
|
||||
*/
|
||||
public function provideVersionAndVariantTestValues(): array
|
||||
{
|
||||
/** @var non-empty-string $bytes */
|
||||
$bytes = hex2bin('426a25b74e975e743af1700fa4e42455');
|
||||
|
||||
return [
|
||||
[
|
||||
'bytes' => $bytes,
|
||||
'version' => Version::Time,
|
||||
'expectedHex' => '426a25b74e971e74baf1700fa4e42455',
|
||||
],
|
||||
[
|
||||
'bytes' => $bytes,
|
||||
'version' => Version::DceSecurity,
|
||||
'expectedHex' => '426a25b74e972e74baf1700fa4e42455',
|
||||
],
|
||||
[
|
||||
'bytes' => $bytes,
|
||||
'version' => Version::HashMd5,
|
||||
'expectedHex' => '426a25b74e973e74baf1700fa4e42455',
|
||||
],
|
||||
[
|
||||
'bytes' => $bytes,
|
||||
'version' => Version::Random,
|
||||
'expectedHex' => '426a25b74e974e74baf1700fa4e42455',
|
||||
],
|
||||
[
|
||||
'bytes' => $bytes,
|
||||
'version' => Version::HashSha1,
|
||||
'expectedHex' => '426a25b74e975e74baf1700fa4e42455',
|
||||
],
|
||||
[
|
||||
'bytes' => $bytes,
|
||||
'version' => Version::ReorderedTime,
|
||||
'expectedHex' => '426a25b74e976e74baf1700fa4e42455',
|
||||
],
|
||||
[
|
||||
'bytes' => $bytes,
|
||||
'version' => Version::UnixTime,
|
||||
'expectedHex' => '426a25b74e977e74baf1700fa4e42455',
|
||||
],
|
||||
[
|
||||
'bytes' => $bytes,
|
||||
'version' => Version::Custom,
|
||||
'expectedHex' => '426a25b74e978e74baf1700fa4e42455',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user