aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php')
-rw-r--r--vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php106
1 files changed, 75 insertions, 31 deletions
diff --git a/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php b/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
index de91aab8d..fe9f57c76 100644
--- a/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
+++ b/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
@@ -1,4 +1,5 @@
<?php
+
/**
* This file is part of the ramsey/uuid library
*
@@ -7,62 +8,105 @@
*
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
* @license http://opensource.org/licenses/MIT MIT
- * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
- * @link https://packagist.org/packages/ramsey/uuid Packagist
- * @link https://github.com/ramsey/uuid GitHub
*/
+
+declare(strict_types=1);
+
namespace Ramsey\Uuid\Codec;
-use InvalidArgumentException;
+use Ramsey\Uuid\Exception\InvalidArgumentException;
+use Ramsey\Uuid\Exception\UnsupportedOperationException;
+use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
+use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
+use function strlen;
+use function substr;
+
/**
- * OrderedTimeCodec optimizes the bytes to increment UUIDs when time goes by, to improve database INSERTs.
- * The string value will be unchanged from StringCodec. Only works for UUID type 1.
+ * OrderedTimeCodec encodes and decodes a UUID, optimizing the byte order for
+ * more efficient storage
+ *
+ * For binary representations of version 1 UUID, this codec may be used to
+ * reorganize the time fields, making the UUID closer to sequential when storing
+ * the bytes. According to Percona, this optimization can improve database
+ * INSERTs and SELECTs using the UUID column as a key.
+ *
+ * The string representation of the UUID will remain unchanged. Only the binary
+ * representation is reordered.
+ *
+ * **PLEASE NOTE:** Binary representations of UUIDs encoded with this codec must
+ * be decoded with this codec. Decoding using another codec can result in
+ * malformed UUIDs.
+ *
+ * @link https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ Storing UUID Values in MySQL
+ *
+ * @psalm-immutable
*/
class OrderedTimeCodec extends StringCodec
{
-
/**
- * Encodes a UuidInterface as an optimized binary representation of a UUID
+ * Returns a binary string representation of a UUID, with the timestamp
+ * fields rearranged for optimized storage
*
- * @param UuidInterface $uuid
- * @return string Binary string representation of a UUID
+ * @inheritDoc
+ * @psalm-return non-empty-string
+ * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
+ * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
*/
- public function encodeBinary(UuidInterface $uuid)
+ public function encodeBinary(UuidInterface $uuid): string
{
- $fields = $uuid->getFieldsHex();
+ if (
+ !($uuid->getFields() instanceof Rfc4122FieldsInterface)
+ || $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
+ ) {
+ throw new InvalidArgumentException(
+ 'Expected RFC 4122 version 1 (time-based) UUID'
+ );
+ }
- $optimized = [
- $fields['time_hi_and_version'],
- $fields['time_mid'],
- $fields['time_low'],
- $fields['clock_seq_hi_and_reserved'],
- $fields['clock_seq_low'],
- $fields['node'],
- ];
+ $bytes = $uuid->getFields()->getBytes();
- return hex2bin(implode('', $optimized));
+ return $bytes[6] . $bytes[7]
+ . $bytes[4] . $bytes[5]
+ . $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3]
+ . substr($bytes, 8);
}
/**
- * Decodes an optimized binary representation of a UUID into a UuidInterface object instance
+ * Returns a UuidInterface derived from an ordered-time binary string
+ * representation
*
- * @param string $bytes
- * @return UuidInterface
- * @throws InvalidArgumentException if string has not 16 characters
+ * @throws InvalidArgumentException if $bytes is an invalid length
+ *
+ * @inheritDoc
*/
- public function decodeBytes($bytes)
+ public function decodeBytes(string $bytes): UuidInterface
{
if (strlen($bytes) !== 16) {
- throw new InvalidArgumentException('$bytes string should contain 16 characters.');
+ throw new InvalidArgumentException(
+ '$bytes string should contain 16 characters.'
+ );
}
- $hex = unpack('H*', $bytes)[1];
+ // Rearrange the bytes to their original order.
+ $rearrangedBytes = $bytes[4] . $bytes[5] . $bytes[6] . $bytes[7]
+ . $bytes[2] . $bytes[3]
+ . $bytes[0] . $bytes[1]
+ . substr($bytes, 8);
+
+ $uuid = parent::decodeBytes($rearrangedBytes);
- // Rearrange the fields to their original order
- $hex = substr($hex, 8, 4) . substr($hex, 12, 4) . substr($hex, 4, 4) . substr($hex, 0, 4) . substr($hex, 16);
+ if (
+ !($uuid->getFields() instanceof Rfc4122FieldsInterface)
+ || $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
+ ) {
+ throw new UnsupportedOperationException(
+ 'Attempting to decode a non-time-based UUID using '
+ . 'OrderedTimeCodec'
+ );
+ }
- return $this->decode($hex);
+ return $uuid;
}
}