Skip to content

Commit

Permalink
[Uid] improve the API of Uuid
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Mar 12, 2020
1 parent d108f7b commit 31ec854
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 21 deletions.
85 changes: 85 additions & 0 deletions src/Symfony/Component/Uid/InternalUtil.php
@@ -0,0 +1,85 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Uid;

/**
* @internal
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class InternalUtil
{
public static function toBinary(string $digits): string
{
$bytes = '';
$len = \strlen($digits);

while ($len > $i = strspn($digits, '0')) {
for ($j = 2, $r = 0; $i < $len; $i += $j, $j = 0) {
do {
$r *= 10;
$d = (int) substr($digits, $i, ++$j);
} while ($i + $j < $len && $r + $d < 256);

$j = \strlen((string) $d);
$q = str_pad(($d += $r) >> 8, $j, '0', STR_PAD_LEFT);
$digits = substr_replace($digits, $q, $i, $j);
$r = $d % 256;
}

$bytes .= \chr($r);
}

return strrev($bytes);
}

public static function toDecimal(string $bytes): string
{
$digits = '';
$len = \strlen($bytes);

while ($len > $i = strspn($bytes, "\0")) {
for ($r = 0; $i < $len; $i += $j) {
$j = $d = 0;
do {
$r <<= 8;
$d = ($d << 8) + \ord($bytes[$i + $j]);
} while ($i + ++$j < $len && $r + $d < 10);

if (256 < $d) {
$q = intdiv($d += $r, 10);
$bytes[$i] = \chr($q >> 8);
$bytes[1 + $i] = \chr($q & 0xFF);
} else {
$bytes[$i] = \chr(intdiv($d += $r, 10));
}
$r = $d % 10;
}

$digits .= (string) $r;
}

return strrev($digits);
}

public static function binaryAdd(string $a, string $b): string
{
$sum = 0;
for ($i = 7; 0 <= $i; --$i) {
$sum += \ord($a[$i]) + \ord($b[$i]);
$a[$i] = \chr($sum & 0xFF);
$sum >>= 8;
}

return $a;
}
}
6 changes: 3 additions & 3 deletions src/Symfony/Component/Uid/Tests/UuidTest.php
Expand Up @@ -116,9 +116,9 @@ public function testExtraMethods()
{
$uuid = new Uuid(self::A_UUID_V1);

$this->assertSame(Uuid::VARIANT_DCE, $uuid->getVariant());
$this->assertSame(1583245966, $uuid->getTime());
$this->assertSame('3499710062d0', $uuid->getMac());
$this->assertSame(UUID_VARIANT_DCE, uuid_variant($uuid));
$this->assertSame('3499710062d0', uuid_mac($uuid));
$this->assertSame(1583245966.746458, $uuid->getTime());
$this->assertSame(self::A_UUID_V1, (string) $uuid);
}
}
27 changes: 9 additions & 18 deletions src/Symfony/Component/Uid/Uuid.php
Expand Up @@ -23,11 +23,6 @@ class Uuid implements \JsonSerializable
public const TYPE_4 = UUID_TYPE_RANDOM;
public const TYPE_5 = UUID_TYPE_SHA1;

public const VARIANT_NCS = UUID_VARIANT_NCS;
public const VARIANT_DCE = UUID_VARIANT_DCE;
public const VARIANT_MICROSOFT = UUID_VARIANT_MICROSOFT;
public const VARIANT_OTHER = UUID_VARIANT_OTHER;

private $uuid;

public function __construct(string $uuid = null)
Expand Down Expand Up @@ -100,27 +95,23 @@ public function getType(): int
return uuid_type($this->uuid);
}

public function getVariant(): int
{
return uuid_variant($this->uuid);
}

public function getTime(): int
public function getTime(): float
{
if (self::TYPE_1 !== $t = uuid_type($this->uuid)) {
throw new \LogicException("UUID of type $t doesn't contain a time.");
}

return uuid_time($this->uuid);
}
$time = '0'.substr($this->uuid, 15, 3).substr($this->uuid, 9, 4).substr($this->uuid, 0, 8);

public function getMac(): string
{
if (self::TYPE_1 !== $t = uuid_type($this->uuid)) {
throw new \LogicException("UUID of type $t doesn't contain a MAC.");
if (\PHP_INT_SIZE >= 8) {
return (hexdec($time) - 0x01b21dd213814000) / 10000000;
}

return uuid_mac($this->uuid);
$time = str_pad(hex2bin($time), 8, "\0", STR_PAD_LEFT);
$time = InternalUtil::binaryAdd($time, "\xfe\x4d\xe2\x2d\xec\x7e\xc0\x00");
$time[0] = $time[0] & "\x7F";

return InternalUtil::toDecimal($time) / 10000000;
}

public function __toString(): string
Expand Down

0 comments on commit 31ec854

Please sign in to comment.