Skip to content

Commit

Permalink
Merge pull request #62 from geekwright/uuidextend
Browse files Browse the repository at this point in the history
Convert UUID to/from 16 byte binary strings
  • Loading branch information
mambax7 authored Jul 30, 2019
2 parents 54c0176 + 7873042 commit e8e176e
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 3 deletions.
52 changes: 49 additions & 3 deletions src/Uuid.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
* @category Xmf\Uuid
* @package Xmf
* @author Richard Griffith <[email protected]>
* @copyright 2017 XOOPS Project (https://xoops.org)
* @license GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
* @link https://xoops.org
* @copyright 2017-2019 XOOPS Project (https://xoops.org)
* @license GNU GPL 2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
*/
class Uuid
{
// match spec for version 4 UUID as per rfc4122
protected const UUID_REGEX = '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/';

/**
* generate - generate a version 4 (random) UUID
*
Expand All @@ -41,4 +43,48 @@ public static function generate()

return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

/**
* Pack a UUID into a binary string
*
* @param string $uuid a valid UUID
*
* @return string packed UUID as a binary string
*
* @throws \InvalidArgumentException
* @throws \UnexpectedValueException
*/
public static function packAsBinary($uuid)
{
if (!preg_match(static::UUID_REGEX, $uuid)) {
throw new \InvalidArgumentException('Invalid UUID');
}
$return = pack("H*", str_replace('-', '', $uuid));
if (false === $return) {
throw new \UnexpectedValueException('Packing UUID Failed');
}
return $return;
}

/**
* Unpack a UUID stored as a binary string
*
* @param string $packedUuid a packed UUID as returned by packAsBinary()
*
* @return string unpacked UUID
*
* @throws \InvalidArgumentException
* @throws \UnexpectedValueException
*/
public static function unpackBinary($packedUuid)
{
if (16 !== strlen($packedUuid)) {
throw new \InvalidArgumentException('Invalid packed UUID');
}
$return = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($packedUuid), 4));
if (!preg_match(static::UUID_REGEX, $return)) {
throw new \UnexpectedValueException('Unpacking UUID Failed');
}
return $return;
}
}
43 changes: 43 additions & 0 deletions tests/unit/UuidTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,48 @@ public function testGenerate()

$this->assertNotEquals($result, $anotherResult);
}

public function testPackUnpack()
{
$uuid = Uuid::generate();
$binUuid = Uuid::packAsBinary($uuid);
$strUuid = Uuid::unpackBinary($binUuid);
$this->assertEquals($uuid, $strUuid);
}

public function testInvalidPack()
{
$this->expectException('\InvalidArgumentException');
$binUuid = Uuid::packAsBinary('garbage-data');
}

public function testInvalidUnpack()
{
$this->expectException('\InvalidArgumentException');
$binUuid = Uuid::unpackBinary('123456789012345');
}

public function testInvalidUnpack2()
{
$this->expectException('\UnexpectedValueException');
$binUuid = Uuid::unpackBinary('0000000000000000');
}

/* verify natural sort order is the same for readable and binary formats */
public function testSortOrder()
{
$auuid = [];
$buuid = [];
for ($i=1; $i<10; ++$i) {
$uuid = Uuid::generate();
$auuid[] = $uuid;
$buuid[] = Uuid::packAsBinary($uuid);
}
sort($auuid);
sort($buuid);
foreach ($auuid as $key => $uuid) {
$this->assertEquals($auuid[$key], Uuid::unpackBinary($buuid[$key]));
}
}
}

0 comments on commit e8e176e

Please sign in to comment.