diff options
Diffstat (limited to 'vendor/ramsey/uuid/src/Rfc4122/Fields.php')
-rw-r--r-- | vendor/ramsey/uuid/src/Rfc4122/Fields.php | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/vendor/ramsey/uuid/src/Rfc4122/Fields.php b/vendor/ramsey/uuid/src/Rfc4122/Fields.php new file mode 100644 index 0000000..2ccc20b --- /dev/null +++ b/vendor/ramsey/uuid/src/Rfc4122/Fields.php @@ -0,0 +1,194 @@ +<?php + +/** + * This file is part of the ramsey/uuid library + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com> + * @license http://opensource.org/licenses/MIT MIT + */ + +declare(strict_types=1); + +namespace Ramsey\Uuid\Rfc4122; + +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Fields\SerializableFieldsTrait; +use Ramsey\Uuid\Type\Hexadecimal; +use Ramsey\Uuid\Uuid; + +use function bin2hex; +use function dechex; +use function hexdec; +use function sprintf; +use function str_pad; +use function strlen; +use function substr; +use function unpack; + +use const STR_PAD_LEFT; + +/** + * RFC 4122 variant UUIDs are comprised of a set of named fields + * + * Internally, this class represents the fields together as a 16-byte binary + * string. + * + * @psalm-immutable + */ +final class Fields implements FieldsInterface +{ + use NilTrait; + use SerializableFieldsTrait; + use VariantTrait; + use VersionTrait; + + /** + * @var string + */ + private $bytes; + + /** + * @param string $bytes A 16-byte binary string representation of a UUID + * + * @throws InvalidArgumentException if the byte string is not exactly 16 bytes + * @throws InvalidArgumentException if the byte string does not represent an RFC 4122 UUID + * @throws InvalidArgumentException if the byte string does not contain a valid version + */ + public function __construct(string $bytes) + { + if (strlen($bytes) !== 16) { + throw new InvalidArgumentException( + 'The byte string must be 16 bytes long; ' + . 'received ' . strlen($bytes) . ' bytes' + ); + } + + $this->bytes = $bytes; + + if (!$this->isCorrectVariant()) { + throw new InvalidArgumentException( + 'The byte string received does not conform to the RFC 4122 variant' + ); + } + + if (!$this->isCorrectVersion()) { + throw new InvalidArgumentException( + 'The byte string received does not contain a valid RFC 4122 version' + ); + } + } + + public function getBytes(): string + { + return $this->bytes; + } + + public function getClockSeq(): Hexadecimal + { + $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff; + + return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT)); + } + + public function getClockSeqHiAndReserved(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1))); + } + + public function getClockSeqLow(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1))); + } + + public function getNode(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 10))); + } + + public function getTimeHiAndVersion(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 6, 2))); + } + + public function getTimeLow(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 0, 4))); + } + + public function getTimeMid(): Hexadecimal + { + return new Hexadecimal(bin2hex(substr($this->bytes, 4, 2))); + } + + /** + * Returns the full 60-bit timestamp, without the version + * + * For version 2 UUIDs, the time_low field is the local identifier and + * should not be returned as part of the time. For this reason, we set the + * bottom 32 bits of the timestamp to 0's. As a result, there is some loss + * of fidelity of the timestamp, for version 2 UUIDs. The timestamp can be + * off by a range of 0 to 429.4967295 seconds (or 7 minutes, 9 seconds, and + * 496730 microseconds). + * + * For version 6 UUIDs, the timestamp order is reversed from the typical RFC + * 4122 order (the time bits are in the correct bit order, so that it is + * monotonically increasing). In returning the timestamp value, we put the + * bits in the order: time_low + time_mid + time_hi. + */ + public function getTimestamp(): Hexadecimal + { + switch ($this->getVersion()) { + case Uuid::UUID_TYPE_DCE_SECURITY: + $timestamp = sprintf( + '%03x%04s%08s', + hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff, + $this->getTimeMid()->toString(), + '' + ); + + break; + case Uuid::UUID_TYPE_PEABODY: + $timestamp = sprintf( + '%08s%04s%03x', + $this->getTimeLow()->toString(), + $this->getTimeMid()->toString(), + hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff + ); + + break; + default: + $timestamp = sprintf( + '%03x%04s%08s', + hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff, + $this->getTimeMid()->toString(), + $this->getTimeLow()->toString() + ); + } + + return new Hexadecimal($timestamp); + } + + public function getVersion(): ?int + { + if ($this->isNil()) { + return null; + } + + /** @var array $parts */ + $parts = unpack('n*', $this->bytes); + + return (int) $parts[4] >> 12; + } + + private function isCorrectVariant(): bool + { + if ($this->isNil()) { + return true; + } + + return $this->getVariant() === Uuid::RFC_4122; + } +} |