diff options
Diffstat (limited to 'vendor/ramsey/uuid/src')
21 files changed, 464 insertions, 145 deletions
diff --git a/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php b/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php index f11e9d50a..04872e0bc 100644 --- a/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php +++ b/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php @@ -18,6 +18,7 @@ use Ramsey\Uuid\Guid\Guid; use Ramsey\Uuid\UuidInterface; use function bin2hex; +use function sprintf; use function substr; /** @@ -29,6 +30,26 @@ use function substr; */ class GuidStringCodec extends StringCodec { + public function encode(UuidInterface $uuid): string + { + $hex = bin2hex($uuid->getFields()->getBytes()); + + /** @var non-empty-string */ + return sprintf( + '%02s%02s%02s%02s-%02s%02s-%02s%02s-%04s-%012s', + substr($hex, 6, 2), + substr($hex, 4, 2), + substr($hex, 2, 2), + substr($hex, 0, 2), + substr($hex, 10, 2), + substr($hex, 8, 2), + substr($hex, 14, 2), + substr($hex, 12, 2), + substr($hex, 16, 4), + substr($hex, 20), + ); + } + public function decode(string $encodedUuid): UuidInterface { $bytes = $this->getBytes($encodedUuid); diff --git a/vendor/ramsey/uuid/src/Codec/StringCodec.php b/vendor/ramsey/uuid/src/Codec/StringCodec.php index 4b6e4e5b9..95f38d2e8 100644 --- a/vendor/ramsey/uuid/src/Codec/StringCodec.php +++ b/vendor/ramsey/uuid/src/Codec/StringCodec.php @@ -17,12 +17,13 @@ namespace Ramsey\Uuid\Codec; use Ramsey\Uuid\Builder\UuidBuilderInterface; use Ramsey\Uuid\Exception\InvalidArgumentException; use Ramsey\Uuid\Exception\InvalidUuidStringException; -use Ramsey\Uuid\Rfc4122\FieldsInterface; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; +use function bin2hex; use function hex2bin; use function implode; +use function sprintf; use function str_replace; use function strlen; use function substr; @@ -47,19 +48,17 @@ class StringCodec implements CodecInterface public function encode(UuidInterface $uuid): string { - /** @var FieldsInterface $fields */ - $fields = $uuid->getFields(); - - return $fields->getTimeLow()->toString() - . '-' - . $fields->getTimeMid()->toString() - . '-' - . $fields->getTimeHiAndVersion()->toString() - . '-' - . $fields->getClockSeqHiAndReserved()->toString() - . $fields->getClockSeqLow()->toString() - . '-' - . $fields->getNode()->toString(); + $hex = bin2hex($uuid->getFields()->getBytes()); + + /** @var non-empty-string */ + return sprintf( + '%08s-%04s-%04s-%04s-%012s', + substr($hex, 0, 8), + substr($hex, 8, 4), + substr($hex, 12, 4), + substr($hex, 16, 4), + substr($hex, 20), + ); } /** diff --git a/vendor/ramsey/uuid/src/FeatureSet.php b/vendor/ramsey/uuid/src/FeatureSet.php index 6c8ccb0de..b9af869f9 100644 --- a/vendor/ramsey/uuid/src/FeatureSet.php +++ b/vendor/ramsey/uuid/src/FeatureSet.php @@ -23,7 +23,6 @@ use Ramsey\Uuid\Converter\Number\GenericNumberConverter; use Ramsey\Uuid\Converter\NumberConverterInterface; use Ramsey\Uuid\Converter\Time\GenericTimeConverter; use Ramsey\Uuid\Converter\Time\PhpTimeConverter; -use Ramsey\Uuid\Converter\Time\UnixTimeConverter; use Ramsey\Uuid\Converter\TimeConverterInterface; use Ramsey\Uuid\Generator\DceSecurityGenerator; use Ramsey\Uuid\Generator\DceSecurityGeneratorInterface; @@ -105,7 +104,7 @@ class FeatureSet $this->validator = new GenericValidator(); assert($this->timeProvider !== null); - $this->unixTimeGenerator = $this->buildUnixTimeGenerator($this->timeProvider); + $this->unixTimeGenerator = $this->buildUnixTimeGenerator(); } /** @@ -339,17 +338,10 @@ class FeatureSet /** * Returns a Unix Epoch time generator configured for this environment - * - * @param TimeProviderInterface $timeProvider The time provider to use with - * the time generator */ - private function buildUnixTimeGenerator(TimeProviderInterface $timeProvider): TimeGeneratorInterface + private function buildUnixTimeGenerator(): TimeGeneratorInterface { - return new UnixTimeGenerator( - new UnixTimeConverter(new BrickMathCalculator()), - $timeProvider, - $this->randomGenerator, - ); + return new UnixTimeGenerator($this->randomGenerator); } /** diff --git a/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php b/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php index a1b39b04a..ea1e2a6ff 100644 --- a/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php +++ b/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php @@ -23,11 +23,11 @@ use Ramsey\Uuid\Provider\TimeProviderInterface; use Ramsey\Uuid\Type\Hexadecimal; use Throwable; -use function ctype_xdigit; use function dechex; use function hex2bin; use function is_int; use function pack; +use function preg_match; use function sprintf; use function str_pad; use function strlen; @@ -120,7 +120,7 @@ class DefaultTimeGenerator implements TimeGeneratorInterface $node = dechex($node); } - if (!ctype_xdigit((string) $node) || strlen((string) $node) > 12) { + if (!preg_match('/^[A-Fa-f0-9]+$/', (string) $node) || strlen((string) $node) > 12) { throw new InvalidArgumentException('Invalid node value'); } diff --git a/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php b/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php index 1aef8699a..af94decf2 100644 --- a/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php +++ b/vendor/ramsey/uuid/src/Generator/UnixTimeGenerator.php @@ -14,39 +14,156 @@ declare(strict_types=1); namespace Ramsey\Uuid\Generator; -use Ramsey\Uuid\Converter\TimeConverterInterface; -use Ramsey\Uuid\Provider\TimeProviderInterface; +use Brick\Math\BigInteger; +use DateTimeImmutable; +use DateTimeInterface; +use Ramsey\Uuid\Type\Hexadecimal; -use function hex2bin; +use function hash; +use function pack; +use function str_pad; +use function strlen; +use function substr; +use function substr_replace; +use function unpack; + +use const PHP_INT_SIZE; +use const STR_PAD_LEFT; /** * UnixTimeGenerator generates bytes that combine a 48-bit timestamp in * milliseconds since the Unix Epoch with 80 random bits + * + * Code and concepts within this class are borrowed from the symfony/uid package + * and are used under the terms of the MIT license distributed with symfony/uid. + * + * symfony/uid is copyright (c) Fabien Potencier. + * + * @link https://symfony.com/components/Uid Symfony Uid component + * @link https://github.com/symfony/uid/blob/4f9f537e57261519808a7ce1d941490736522bbc/UuidV7.php Symfony UuidV7 class + * @link https://github.com/symfony/uid/blob/6.2/LICENSE MIT License */ class UnixTimeGenerator implements TimeGeneratorInterface { + private static string $time = ''; + private static ?string $seed = null; + private static int $seedIndex = 0; + + /** @var int[] */ + private static array $rand = []; + + /** @var int[] */ + private static array $seedParts; + public function __construct( - private TimeConverterInterface $timeConverter, - private TimeProviderInterface $timeProvider, - private RandomGeneratorInterface $randomGenerator + private RandomGeneratorInterface $randomGenerator, + private int $intSize = PHP_INT_SIZE ) { } /** + * @param Hexadecimal|int|string|null $node Unused in this generator + * @param int|null $clockSeq Unused in this generator + * @param DateTimeInterface $dateTime A date-time instance to use when + * generating bytes + * * @inheritDoc */ - public function generate($node = null, ?int $clockSeq = null): string + public function generate($node = null, ?int $clockSeq = null, ?DateTimeInterface $dateTime = null): string + { + $time = ($dateTime ?? new DateTimeImmutable('now'))->format('Uv'); + + if ($time > self::$time || ($dateTime !== null && $time !== self::$time)) { + $this->randomize($time); + } else { + $time = $this->increment(); + } + + if ($this->intSize >= 8) { + $time = substr(pack('J', (int) $time), -6); + } else { + $time = str_pad(BigInteger::of($time)->toBytes(false), 6, "\x00", STR_PAD_LEFT); + } + + /** @var non-empty-string */ + return $time . pack('n*', self::$rand[1], self::$rand[2], self::$rand[3], self::$rand[4], self::$rand[5]); + } + + private function randomize(string $time): void { - // Generate 10 random bytes to append to the string returned, since our - // time bytes will consist of 6 bytes. - $random = $this->randomGenerator->generate(10); + if (self::$seed === null) { + $seed = $this->randomGenerator->generate(16); + self::$seed = $seed; + } else { + $seed = $this->randomGenerator->generate(10); + } + + /** @var int[] $rand */ + $rand = unpack('n*', $seed); + $rand[1] &= 0x03ff; + + self::$rand = $rand; + self::$time = $time; + } + + /** + * Special thanks to Nicolas Grekas for sharing the following information: + * + * Within the same ms, we increment the rand part by a random 24-bit number. + * + * Instead of getting this number from random_bytes(), which is slow, we get + * it by sha512-hashing self::$seed. This produces 64 bytes of entropy, + * which we need to split in a list of 24-bit numbers. unpack() first splits + * them into 16 x 32-bit numbers; we take the first byte of each of these + * numbers to get 5 extra 24-bit numbers. Then, we consume those numbers + * one-by-one and run this logic every 21 iterations. + * + * self::$rand holds the random part of the UUID, split into 5 x 16-bit + * numbers for x86 portability. We increment this random part by the next + * 24-bit number in the self::$seedParts list and decrement + * self::$seedIndex. + * + * @link https://twitter.com/nicolasgrekas/status/1583356938825261061 Tweet from Nicolas Grekas + */ + private function increment(): string + { + if (self::$seedIndex === 0 && self::$seed !== null) { + self::$seed = hash('sha512', self::$seed, true); + + /** @var int[] $s */ + $s = unpack('l*', self::$seed); + $s[] = ($s[1] >> 8 & 0xff0000) | ($s[2] >> 16 & 0xff00) | ($s[3] >> 24 & 0xff); + $s[] = ($s[4] >> 8 & 0xff0000) | ($s[5] >> 16 & 0xff00) | ($s[6] >> 24 & 0xff); + $s[] = ($s[7] >> 8 & 0xff0000) | ($s[8] >> 16 & 0xff00) | ($s[9] >> 24 & 0xff); + $s[] = ($s[10] >> 8 & 0xff0000) | ($s[11] >> 16 & 0xff00) | ($s[12] >> 24 & 0xff); + $s[] = ($s[13] >> 8 & 0xff0000) | ($s[14] >> 16 & 0xff00) | ($s[15] >> 24 & 0xff); + + self::$seedParts = $s; + self::$seedIndex = 21; + } + + self::$rand[5] = 0xffff & $carry = self::$rand[5] + (self::$seedParts[self::$seedIndex--] & 0xffffff); + self::$rand[4] = 0xffff & $carry = self::$rand[4] + ($carry >> 16); + self::$rand[3] = 0xffff & $carry = self::$rand[3] + ($carry >> 16); + self::$rand[2] = 0xffff & $carry = self::$rand[2] + ($carry >> 16); + self::$rand[1] += $carry >> 16; + + if (0xfc00 & self::$rand[1]) { + $time = self::$time; + $mtime = (int) substr($time, -9); + + if ($this->intSize >= 8 || strlen($time) < 10) { + $time = (string) ((int) $time + 1); + } elseif ($mtime === 999999999) { + $time = (1 + (int) substr($time, 0, -9)) . '000000000'; + } else { + $mtime++; + $time = substr_replace($time, str_pad((string) $mtime, 9, '0', STR_PAD_LEFT), -9); + } - $time = $this->timeProvider->getTime(); - $unixTimeHex = $this->timeConverter->calculateTime( - $time->getSeconds()->toString(), - $time->getMicroseconds()->toString(), - ); + $this->randomize($time); + } - return hex2bin($unixTimeHex->toString()) . $random; + return self::$time; } } diff --git a/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php b/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php index 1a7bbaf75..7497dd101 100644 --- a/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php +++ b/vendor/ramsey/uuid/src/Nonstandard/UuidV6.php @@ -23,7 +23,7 @@ use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Rfc4122\TimeTrait; use Ramsey\Uuid\Rfc4122\UuidInterface; use Ramsey\Uuid\Rfc4122\UuidV1; -use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\Uuid as BaseUuid; /** * Reordered time, or version 6, UUIDs include timestamp, clock sequence, and @@ -36,7 +36,7 @@ use Ramsey\Uuid\Uuid; * * @psalm-immutable */ -class UuidV6 extends Uuid implements UuidInterface +class UuidV6 extends BaseUuid implements UuidInterface { use TimeTrait; diff --git a/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php b/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php index d0a1e697f..a03c93b4d 100644 --- a/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php +++ b/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php @@ -133,12 +133,15 @@ class SystemNodeProvider implements NodeProviderInterface $ifconfig = (string) ob_get_clean(); - $node = ''; if (preg_match_all(self::IFCONFIG_PATTERN, $ifconfig, $matches, PREG_PATTERN_ORDER)) { - $node = $matches[1][0] ?? ''; + foreach ($matches[1] as $iface) { + if ($iface !== '00:00:00:00:00:00' && $iface !== '00-00-00-00-00-00') { + return $iface; + } + } } - return $node; + return ''; } /** diff --git a/vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php b/vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php index 2ec304723..dedb72798 100644 --- a/vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php +++ b/vendor/ramsey/uuid/src/Rfc4122/MaxTrait.php @@ -20,7 +20,7 @@ namespace Ramsey\Uuid\Rfc4122; * The max UUID is special form of UUID that is specified to have all 128 bits * set to one. It is the inverse of the nil UUID. * - * @link https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.4 Max UUID + * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.10 Max UUID * * @psalm-immutable */ diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php b/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php index 859649fd9..2c2677db7 100644 --- a/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php +++ b/vendor/ramsey/uuid/src/Rfc4122/UuidBuilder.php @@ -95,6 +95,8 @@ class UuidBuilder implements UuidBuilderInterface return new UuidV6($fields, $this->numberConverter, $codec, $this->timeConverter); case Uuid::UUID_TYPE_UNIX_TIME: return new UuidV7($fields, $this->numberConverter, $codec, $this->unixTimeConverter); + case Uuid::UUID_TYPE_CUSTOM: + return new UuidV8($fields, $this->numberConverter, $codec, $this->timeConverter); } throw new UnsupportedOperationException( diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV6.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV6.php index 9b2ddee00..7e3743391 100644 --- a/vendor/ramsey/uuid/src/Rfc4122/UuidV6.php +++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV6.php @@ -20,7 +20,7 @@ use Ramsey\Uuid\Nonstandard\UuidV6 as NonstandardUuidV6; * Reordered time, or version 6, UUIDs include timestamp, clock sequence, and * node values that are combined into a 128-bit unsigned integer * - * @link https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.1 UUID Version 6 + * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.6 UUID Version 6 * * @psalm-immutable */ diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV7.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV7.php index 90c2471ac..5b524c486 100644 --- a/vendor/ramsey/uuid/src/Rfc4122/UuidV7.php +++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV7.php @@ -22,8 +22,10 @@ use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; use Ramsey\Uuid\Uuid; /** - * Gregorian time, or version 1, UUIDs include timestamp, clock sequence, and node - * values that are combined into a 128-bit unsigned integer + * Unix Epoch time, or version 7, UUIDs include a timestamp in milliseconds + * since the Unix Epoch, along with random bytes + * + * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.7 UUID Version 7 * * @psalm-immutable */ diff --git a/vendor/ramsey/uuid/src/Rfc4122/UuidV8.php b/vendor/ramsey/uuid/src/Rfc4122/UuidV8.php new file mode 100644 index 000000000..78b0290c7 --- /dev/null +++ b/vendor/ramsey/uuid/src/Rfc4122/UuidV8.php @@ -0,0 +1,65 @@ +<?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\Codec\CodecInterface; +use Ramsey\Uuid\Converter\NumberConverterInterface; +use Ramsey\Uuid\Converter\TimeConverterInterface; +use Ramsey\Uuid\Exception\InvalidArgumentException; +use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface; +use Ramsey\Uuid\Uuid; + +/** + * Version 8, Custom UUIDs provide an RFC 4122 compatible format for + * experimental or vendor-specific uses + * + * The only requirement for version 8 UUIDs is that the version and variant bits + * must be set. Otherwise, implementations are free to set the other bits + * according to their needs. As a result, the uniqueness of version 8 UUIDs is + * implementation-specific and should not be assumed. + * + * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.8 UUID Version 8 + * + * @psalm-immutable + */ +final class UuidV8 extends Uuid implements UuidInterface +{ + /** + * Creates a version 8 (custom) UUID + * + * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID + * @param NumberConverterInterface $numberConverter The number converter to use + * for converting hex values to/from integers + * @param CodecInterface $codec The codec to use when encoding or decoding + * UUID strings + * @param TimeConverterInterface $timeConverter The time converter to use + * for converting timestamps extracted from a UUID to unix timestamps + */ + public function __construct( + Rfc4122FieldsInterface $fields, + NumberConverterInterface $numberConverter, + CodecInterface $codec, + TimeConverterInterface $timeConverter + ) { + if ($fields->getVersion() !== Uuid::UUID_TYPE_CUSTOM) { + throw new InvalidArgumentException( + 'Fields used to create a UuidV8 must represent a ' + . 'version 8 (custom) UUID' + ); + } + + parent::__construct($fields, $numberConverter, $codec, $timeConverter); + } +} diff --git a/vendor/ramsey/uuid/src/Rfc4122/Validator.php b/vendor/ramsey/uuid/src/Rfc4122/Validator.php index 6b1f0de06..e82a11e6e 100644 --- a/vendor/ramsey/uuid/src/Rfc4122/Validator.php +++ b/vendor/ramsey/uuid/src/Rfc4122/Validator.php @@ -28,7 +28,7 @@ use function str_replace; final class Validator implements ValidatorInterface { private const VALID_PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-' - . '[1-7][0-9A-Fa-f]{3}-[ABab89][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z'; + . '[1-8][0-9A-Fa-f]{3}-[ABab89][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z'; /** * @psalm-return non-empty-string diff --git a/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php b/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php index 316f780c4..0195e46c7 100644 --- a/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php +++ b/vendor/ramsey/uuid/src/Rfc4122/VersionTrait.php @@ -53,7 +53,7 @@ trait VersionTrait Uuid::UUID_TYPE_TIME, Uuid::UUID_TYPE_DCE_SECURITY, Uuid::UUID_TYPE_HASH_MD5, Uuid::UUID_TYPE_RANDOM, Uuid::UUID_TYPE_HASH_SHA1, Uuid::UUID_TYPE_REORDERED_TIME, - Uuid::UUID_TYPE_UNIX_TIME => true, + Uuid::UUID_TYPE_UNIX_TIME, Uuid::UUID_TYPE_CUSTOM => true, default => false, }; } diff --git a/vendor/ramsey/uuid/src/Type/Hexadecimal.php b/vendor/ramsey/uuid/src/Type/Hexadecimal.php index 3c8f30adf..bf71ec4b1 100644 --- a/vendor/ramsey/uuid/src/Type/Hexadecimal.php +++ b/vendor/ramsey/uuid/src/Type/Hexadecimal.php @@ -17,10 +17,8 @@ namespace Ramsey\Uuid\Type; use Ramsey\Uuid\Exception\InvalidArgumentException; use ValueError; -use function ctype_xdigit; +use function preg_match; use function sprintf; -use function str_starts_with; -use function strtolower; use function substr; /** @@ -37,23 +35,11 @@ final class Hexadecimal implements TypeInterface private string $value; /** - * @param string $value The hexadecimal value to store + * @param self|string $value The hexadecimal value to store */ - public function __construct(string $value) + public function __construct(self | string $value) { - $value = strtolower($value); - - if (str_starts_with($value, '0x')) { - $value = substr($value, 2); - } - - if (!ctype_xdigit($value)) { - throw new InvalidArgumentException( - 'Value must be a hexadecimal number' - ); - } - - $this->value = $value; + $this->value = $value instanceof self ? (string) $value : $this->prepareValue($value); } public function toString(): string @@ -109,4 +95,21 @@ final class Hexadecimal implements TypeInterface $this->unserialize($data['string']); } + + private function prepareValue(string $value): string + { + $value = strtolower($value); + + if (str_starts_with($value, '0x')) { + $value = substr($value, 2); + } + + if (!preg_match('/^[A-Fa-f0-9]+$/', $value)) { + throw new InvalidArgumentException( + 'Value must be a hexadecimal number' + ); + } + + return $value; + } } diff --git a/vendor/ramsey/uuid/src/Type/Integer.php b/vendor/ramsey/uuid/src/Type/Integer.php index e41b3cad5..50dac9934 100644 --- a/vendor/ramsey/uuid/src/Type/Integer.php +++ b/vendor/ramsey/uuid/src/Type/Integer.php @@ -17,10 +17,10 @@ namespace Ramsey\Uuid\Type; use Ramsey\Uuid\Exception\InvalidArgumentException; use ValueError; -use function ctype_digit; -use function ltrim; +use function assert; +use function is_numeric; +use function preg_match; use function sprintf; -use function str_starts_with; use function substr; /** @@ -46,40 +46,7 @@ final class Integer implements NumberInterface public function __construct(float | int | string | self $value) { - $value = (string) $value; - $sign = '+'; - - // If the value contains a sign, remove it for ctype_digit() check. - if (str_starts_with($value, '-') || str_starts_with($value, '+')) { - $sign = substr($value, 0, 1); - $value = substr($value, 1); - } - - if (!ctype_digit($value)) { - throw new InvalidArgumentException( - 'Value must be a signed integer or a string containing only ' - . 'digits 0-9 and, optionally, a sign (+ or -)' - ); - } - - // Trim any leading zeros. - $value = ltrim($value, '0'); - - // Set to zero if the string is empty after trimming zeros. - if ($value === '') { - $value = '0'; - } - - // Add the negative sign back to the value. - if ($sign === '-' && $value !== '0') { - $value = $sign . $value; - $this->isNegative = true; - } - - /** @psalm-var numeric-string $numericValue */ - $numericValue = $value; - - $this->value = $numericValue; + $this->value = $value instanceof self ? (string) $value : $this->prepareValue($value); } public function isNegative(): bool @@ -95,6 +62,9 @@ final class Integer implements NumberInterface return $this->value; } + /** + * @psalm-return numeric-string + */ public function __toString(): string { return $this->toString(); @@ -143,4 +113,46 @@ final class Integer implements NumberInterface $this->unserialize($data['string']); } + + /** + * @return numeric-string + */ + private function prepareValue(float | int | string $value): string + { + $value = (string) $value; + $sign = '+'; + + // If the value contains a sign, remove it for digit pattern check. + if (str_starts_with($value, '-') || str_starts_with($value, '+')) { + $sign = substr($value, 0, 1); + $value = substr($value, 1); + } + + if (!preg_match('/^\d+$/', $value)) { + throw new InvalidArgumentException( + 'Value must be a signed integer or a string containing only ' + . 'digits 0-9 and, optionally, a sign (+ or -)' + ); + } + + // Trim any leading zeros. + $value = ltrim($value, '0'); + + // Set to zero if the string is empty after trimming zeros. + if ($value === '') { + $value = '0'; + } + + // Add the negative sign back to the value. + if ($sign === '-' && $value !== '0') { + $value = $sign . $value; + + /** @psalm-suppress InaccessibleProperty */ + $this->isNegative = true; + } + + assert(is_numeric($value)); + + return $value; + } } diff --git a/vendor/ramsey/uuid/src/Type/Time.php b/vendor/ramsey/uuid/src/Type/Time.php index 745b5ccab..0cedb4476 100644 --- a/vendor/ramsey/uuid/src/Type/Time.php +++ b/vendor/ramsey/uuid/src/Type/Time.php @@ -56,7 +56,7 @@ final class Time implements TypeInterface public function toString(): string { - return $this->seconds->toString() . '.' . $this->microseconds->toString(); + return $this->seconds->toString() . '.' . sprintf('%06s', $this->microseconds->toString()); } public function __toString(): string diff --git a/vendor/ramsey/uuid/src/Uuid.php b/vendor/ramsey/uuid/src/Uuid.php index 6656aba02..e0384a50c 100644 --- a/vendor/ramsey/uuid/src/Uuid.php +++ b/vendor/ramsey/uuid/src/Uuid.php @@ -14,6 +14,7 @@ declare(strict_types=1); namespace Ramsey\Uuid; +use BadMethodCallException; use DateTimeInterface; use Ramsey\Uuid\Codec\CodecInterface; use Ramsey\Uuid\Converter\NumberConverterInterface; @@ -88,7 +89,7 @@ class Uuid implements UuidInterface * The max UUID is a special form of UUID that is specified to have all 128 * bits set to one * - * @link https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.4 Max UUID + * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.10 Max UUID */ public const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff'; @@ -173,18 +174,23 @@ class Uuid implements UuidInterface /** * Version 6 (reordered time) UUID * - * @link https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.1 UUID Version 6 + * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.6 UUID Version 6 */ public const UUID_TYPE_REORDERED_TIME = 6; /** * Version 7 (Unix Epoch time) UUID * - * @link https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.2 UUID Version 7 + * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.7 UUID Version 7 */ public const UUID_TYPE_UNIX_TIME = 7; /** + * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.8 UUID Version 8 + */ + public const UUID_TYPE_CUSTOM = 8; + + /** * DCE Security principal domain * * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, ยง11.5.1.1 @@ -287,7 +293,7 @@ class Uuid implements UuidInterface */ public function serialize(): string { - return $this->getFields()->getBytes(); + return $this->codec->encode($this); } /** @@ -440,20 +446,20 @@ class Uuid implements UuidInterface */ public static function fromBytes(string $bytes): UuidInterface { - if (! self::$factoryReplaced && strlen($bytes) === 16) { + if (!self::$factoryReplaced && strlen($bytes) === 16) { $base16Uuid = bin2hex($bytes); // Note: we are calling `fromString` internally because we don't know if the given `$bytes` is a valid UUID return self::fromString( substr($base16Uuid, 0, 8) - . '-' - . substr($base16Uuid, 8, 4) - . '-' - . substr($base16Uuid, 12, 4) - . '-' - . substr($base16Uuid, 16, 4) - . '-' - . substr($base16Uuid, 20, 12) + . '-' + . substr($base16Uuid, 8, 4) + . '-' + . substr($base16Uuid, 12, 4) + . '-' + . substr($base16Uuid, 16, 4) + . '-' + . substr($base16Uuid, 20, 12) ); } @@ -479,7 +485,7 @@ class Uuid implements UuidInterface public static function fromString(string $uuid): UuidInterface { $uuid = strtolower($uuid); - if (! self::$factoryReplaced && preg_match(LazyUuidFromString::VALID_REGEX, $uuid) === 1) { + if (!self::$factoryReplaced && preg_match(LazyUuidFromString::VALID_REGEX, $uuid) === 1) { assert($uuid !== ''); return new LazyUuidFromString($uuid); @@ -510,6 +516,33 @@ class Uuid implements UuidInterface } /** + * Creates a UUID from the Hexadecimal object + * + * @param Hexadecimal $hex Hexadecimal object representing a hexadecimal number + * + * @return UuidInterface A UuidInterface instance created from the Hexadecimal + * object representing a hexadecimal number + * + * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, + * but under constant factory setups, this method operates in functionally pure manners + * @psalm-suppress MixedInferredReturnType,MixedReturnStatement + */ + public static function fromHexadecimal(Hexadecimal $hex): UuidInterface + { + $factory = self::getFactory(); + + if (method_exists($factory, 'fromHexadecimal')) { + /** + * @phpstan-ignore-next-line + * @psalm-suppress UndefinedInterfaceMethod + */ + return self::getFactory()->fromHexadecimal($hex); + } + + throw new BadMethodCallException('The method fromHexadecimal() does not exist on the provided factory'); + } + + /** * Creates a UUID from a 128-bit integer string * * @param string $integer String representation of 128-bit integer @@ -522,6 +555,7 @@ class Uuid implements UuidInterface */ public static function fromInteger(string $integer): UuidInterface { + /** @psalm-suppress ImpureMethodCall */ return self::getFactory()->fromInteger($integer); } @@ -535,10 +569,11 @@ class Uuid implements UuidInterface * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants, * but under constant factory setups, this method operates in functionally pure manners * - * @psalm-assert-if-true non-empty-string $uuid + * @psalm-assert-if-true =non-empty-string $uuid */ public static function isValid(string $uuid): bool { + /** @psalm-suppress ImpureMethodCall */ return self::getFactory()->getValidator()->validate($uuid); } @@ -549,7 +584,7 @@ class Uuid implements UuidInterface * @param Hexadecimal|int|string|null $node A 48-bit number representing the * hardware address; this number may be represented as an integer or a * hexadecimal string - * @param int $clockSeq A 14-bit number used to help avoid duplicates that + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates that * could arise when the clock is set backwards in time or if the node ID * changes * @@ -653,7 +688,7 @@ class Uuid implements UuidInterface * * @param Hexadecimal|null $node A 48-bit number representing the hardware * address - * @param int $clockSeq A 14-bit number used to help avoid duplicates that + * @param int|null $clockSeq A 14-bit number used to help avoid duplicates that * could arise when the clock is set backwards in time or if the node ID * changes * @@ -690,4 +725,34 @@ class Uuid implements UuidInterface 'The provided factory does not support the uuid7() method', ); } + + /** + * Returns a version 8 (custom) UUID + * + * The bytes provided may contain any value according to your application's + * needs. Be aware, however, that other applications may not understand the + * semantics of the value. + * + * @param string $bytes A 16-byte octet string. This is an open blob + * of data that you may fill with 128 bits of information. Be aware, + * however, bits 48 through 51 will be replaced with the UUID version + * field, and bits 64 and 65 will be replaced with the UUID variant. You + * MUST NOT rely on these bits for your application needs. + * + * @return UuidInterface A UuidInterface instance that represents a + * version 8 UUID + */ + public static function uuid8(string $bytes): UuidInterface + { + $factory = self::getFactory(); + + if (method_exists($factory, 'uuid8')) { + /** @var UuidInterface */ + return $factory->uuid8($bytes); + } + + throw new UnsupportedOperationException( + 'The provided factory does not support the uuid8() method', + ); + } } diff --git a/vendor/ramsey/uuid/src/UuidFactory.php b/vendor/ramsey/uuid/src/UuidFactory.php index ab730f741..1b06ea6ed 100644 --- a/vendor/ramsey/uuid/src/UuidFactory.php +++ b/vendor/ramsey/uuid/src/UuidFactory.php @@ -18,7 +18,6 @@ use DateTimeInterface; use Ramsey\Uuid\Builder\UuidBuilderInterface; use Ramsey\Uuid\Codec\CodecInterface; use Ramsey\Uuid\Converter\NumberConverterInterface; -use Ramsey\Uuid\Converter\Time\UnixTimeConverter; use Ramsey\Uuid\Converter\TimeConverterInterface; use Ramsey\Uuid\Generator\DceSecurityGeneratorInterface; use Ramsey\Uuid\Generator\DefaultTimeGenerator; @@ -27,7 +26,6 @@ use Ramsey\Uuid\Generator\RandomGeneratorInterface; use Ramsey\Uuid\Generator\TimeGeneratorInterface; use Ramsey\Uuid\Generator\UnixTimeGenerator; use Ramsey\Uuid\Lazy\LazyUuidFromString; -use Ramsey\Uuid\Math\BrickMathCalculator; use Ramsey\Uuid\Provider\NodeProviderInterface; use Ramsey\Uuid\Provider\Time\FixedTimeProvider; use Ramsey\Uuid\Type\Hexadecimal; @@ -315,6 +313,14 @@ class UuidFactory implements UuidFactoryInterface } /** + * @psalm-pure + */ + public function fromHexadecimal(Hexadecimal $hex): UuidInterface + { + return $this->codec->decode($hex->__toString()); + } + + /** * @inheritDoc */ public function uuid1($node = null, ?int $clockSeq = null): UuidInterface @@ -396,26 +402,34 @@ class UuidFactory implements UuidFactoryInterface */ public function uuid7(?DateTimeInterface $dateTime = null): UuidInterface { - if ($dateTime !== null) { - $timeProvider = new FixedTimeProvider( - new Time($dateTime->format('U'), $dateTime->format('u')) - ); - - $timeGenerator = new UnixTimeGenerator( - new UnixTimeConverter(new BrickMathCalculator()), - $timeProvider, - $this->randomGenerator, - ); - - $bytes = $timeGenerator->generate(); - } else { - $bytes = $this->unixTimeGenerator->generate(); - } + assert($this->unixTimeGenerator instanceof UnixTimeGenerator); + $bytes = $this->unixTimeGenerator->generate(null, null, $dateTime); return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_UNIX_TIME); } /** + * Returns a version 8 (Custom) UUID + * + * The bytes provided may contain any value according to your application's + * needs. Be aware, however, that other applications may not understand the + * semantics of the value. + * + * @param string $bytes A 16-byte octet string. This is an open blob + * of data that you may fill with 128 bits of information. Be aware, + * however, bits 48 through 51 will be replaced with the UUID version + * field, and bits 64 and 65 will be replaced with the UUID variant. You + * MUST NOT rely on these bits for your application needs. + * + * @return UuidInterface A UuidInterface instance that represents a + * version 8 UUID + */ + public function uuid8(string $bytes): UuidInterface + { + return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_CUSTOM); + } + + /** * Returns a Uuid created from the provided byte string * * Uses the configured builder and codec and the provided byte string to @@ -430,6 +444,7 @@ class UuidFactory implements UuidFactoryInterface */ public function uuid(string $bytes): UuidInterface { + /** @psalm-suppress ImpurePropertyFetch */ return $this->uuidBuilder->build($this->codec, $bytes); } @@ -492,6 +507,7 @@ class UuidFactory implements UuidFactoryInterface return LazyUuidFromString::fromBytes($bytes); } + /** @psalm-suppress ImpureVariable */ return $this->uuid($bytes); } } diff --git a/vendor/ramsey/uuid/src/UuidInterface.php b/vendor/ramsey/uuid/src/UuidInterface.php index 5f41675bf..0a9780805 100644 --- a/vendor/ramsey/uuid/src/UuidInterface.php +++ b/vendor/ramsey/uuid/src/UuidInterface.php @@ -19,6 +19,7 @@ use Ramsey\Uuid\Fields\FieldsInterface; use Ramsey\Uuid\Type\Hexadecimal; use Ramsey\Uuid\Type\Integer as IntegerObject; use Serializable; +use Stringable; /** * A UUID is a universally unique identifier adhering to an agreed-upon @@ -29,7 +30,8 @@ use Serializable; interface UuidInterface extends DeprecatedUuidInterface, JsonSerializable, - Serializable + Serializable, + Stringable { /** * Returns -1, 0, or 1 if the UUID is less than, equal to, or greater than diff --git a/vendor/ramsey/uuid/src/functions.php b/vendor/ramsey/uuid/src/functions.php index fa80f4e85..1b3ce00f7 100644 --- a/vendor/ramsey/uuid/src/functions.php +++ b/vendor/ramsey/uuid/src/functions.php @@ -136,3 +136,23 @@ function v7(?DateTimeInterface $dateTime = null): string { return Uuid::uuid7($dateTime)->toString(); } + +/** + * Returns a version 8 (custom) UUID + * + * The bytes provided may contain any value according to your application's + * needs. Be aware, however, that other applications may not understand the + * semantics of the value. + * + * @param string $bytes A 16-byte octet string. This is an open blob + * of data that you may fill with 128 bits of information. Be aware, + * however, bits 48 through 51 will be replaced with the UUID version + * field, and bits 64 and 65 will be replaced with the UUID variant. You + * MUST NOT rely on these bits for your application needs. + * + * @return non-empty-string Version 8 UUID as a string + */ +function v8(string $bytes): string +{ + return Uuid::uuid8($bytes)->toString(); +} |