Skip to content

Commit

Permalink
refactor a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
fab2s committed Feb 9, 2018
1 parent 04d653e commit a5ca736
Showing 1 changed file with 35 additions and 24 deletions.
59 changes: 35 additions & 24 deletions src/SoUuid.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,11 @@ protected function __construct($uuid)
*/
public static function generate($identifier = null)
{
// 7 bit micro-time
$uuid = static::microTimeBin();
if ($identifier !== null) {
if (strpos($identifier, static::IDENTIFIER_SEPARATOR) !== false) {
throw new \InvalidArgumentException('SoUuid identifiers cannot contain ' . bin2hex(static::IDENTIFIER_SEPARATOR));
}

$len = strlen($identifier);
$identifier = substr($identifier, 0, 6) . ($len <= 4 ? static::IDENTIFIER_SEPARATOR . random_bytes(6 - $len - 1) : '');
} else {
$identifier = static::IDENTIFIER_SEPARATOR . random_bytes(5);
}

$uuid .= str_pad($identifier, 6, static::IDENTIFIER_SEPARATOR, STR_PAD_RIGHT);

// pick one out of 2^24 = 16 777 216
// 6 bytes identifier
$uuid .= static::encodeIdentifier($identifier);
// 3 random bytes (2^24 = 16 777 216 combinations)
$uuid .= random_bytes(3);

return new static($uuid);
Expand Down Expand Up @@ -198,11 +188,12 @@ public function getString()
{
if ($this->string === null) {
// microsecond epoch - 2/6 id bytes - 4/6 id bytes - 6/6 id bytes - 3 random bytes
$this->string = bin2hex(substr($this->uuid, 0, 7)) . '-' .
bin2hex(substr($this->uuid, 7, 2)) . '-' .
bin2hex(substr($this->uuid, 9, 2)) . '-' .
bin2hex(substr($this->uuid, 11, 2)) . '-' .
bin2hex(substr($this->uuid, 13));
$hex = $this->getHex();
$this->string = substr($hex, 0, 14) . '-' .
substr($hex, 14, 4) . '-' .
substr($hex, 18, 4) . '-' .
substr($hex, 22, 4) . '-' .
substr($hex, 26);
}

return $this->string;
Expand All @@ -214,9 +205,8 @@ public function getString()
public function getMicroTime()
{
if ($this->microTime === null) {
$timeBit = substr($this->uuid, 0, 7);
$timeBit = hexdec(bin2hex($timeBit));
$this->microTime = substr($timeBit, 0, 10) . '.' . substr($timeBit, 10, 6);
$timeBin = substr($this->uuid, 0, 7);
$this->microTime = hexdec(bin2hex($timeBin));
}

return $this->microTime;
Expand All @@ -243,9 +233,30 @@ public static function microTimeBin()
// are limited by php.ini precision
$timeParts = explode(' ', microtime(false));
$timeMicroSec = $timeParts[1] . substr($timeParts[0], 2, 6);
// convert to 56-bit integer
// convert to 56-bit integer (7 bytes), enough to store micro time is enough up to 4253-05-31 22:20:37
$time = base_convert($timeMicroSec, 10, 16);
// using 7 bytes to store micro time is enough up to 4253-05-31 22:20:37
// left pad the eventual gap
return hex2bin(str_pad($time, 14, '0', STR_PAD_LEFT));
}

/**
* @param string|null $identifier
*
* @return string
*/
public static function encodeIdentifier($identifier = null)
{
if ($identifier !== null) {
if (strpos($identifier, static::IDENTIFIER_SEPARATOR) !== false) {
throw new \InvalidArgumentException('SoUuid identifiers cannot contain ' . bin2hex(static::IDENTIFIER_SEPARATOR));
}

$len = strlen($identifier);
$identifier = substr($identifier, 0, 6) . ($len <= 4 ? static::IDENTIFIER_SEPARATOR . random_bytes(5 - $len) : '');

return str_pad($identifier, 6, static::IDENTIFIER_SEPARATOR, STR_PAD_RIGHT);
}

return static::IDENTIFIER_SEPARATOR . random_bytes(5);
}
}

0 comments on commit a5ca736

Please sign in to comment.