aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/ramsey/uuid/src/UuidFactory.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ramsey/uuid/src/UuidFactory.php')
-rw-r--r--vendor/ramsey/uuid/src/UuidFactory.php406
1 files changed, 290 insertions, 116 deletions
diff --git a/vendor/ramsey/uuid/src/UuidFactory.php b/vendor/ramsey/uuid/src/UuidFactory.php
index 5a57b09b2..feddef88d 100644
--- a/vendor/ramsey/uuid/src/UuidFactory.php
+++ b/vendor/ramsey/uuid/src/UuidFactory.php
@@ -1,4 +1,5 @@
<?php
+
/**
* This file is part of the ramsey/uuid library
*
@@ -7,201 +8,314 @@
*
* @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;
+use DateTimeInterface;
+use Ramsey\Uuid\Builder\UuidBuilderInterface;
+use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
-use Ramsey\Uuid\Exception\InvalidUuidStringException;
-use Ramsey\Uuid\Provider\NodeProviderInterface;
+use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Generator\DceSecurityGeneratorInterface;
+use Ramsey\Uuid\Generator\DefaultTimeGenerator;
+use Ramsey\Uuid\Generator\NameGeneratorInterface;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Generator\TimeGeneratorInterface;
-use Ramsey\Uuid\Codec\CodecInterface;
-use Ramsey\Uuid\Builder\UuidBuilderInterface;
+use Ramsey\Uuid\Lazy\LazyUuidFromString;
+use Ramsey\Uuid\Provider\NodeProviderInterface;
+use Ramsey\Uuid\Provider\Time\FixedTimeProvider;
+use Ramsey\Uuid\Type\Hexadecimal;
+use Ramsey\Uuid\Type\Integer as IntegerObject;
+use Ramsey\Uuid\Type\Time;
+use Ramsey\Uuid\Validator\ValidatorInterface;
+
+use function bin2hex;
+use function hex2bin;
+use function pack;
+use function str_pad;
+use function strtolower;
+use function substr;
+use function substr_replace;
+use function unpack;
+
+use const STR_PAD_LEFT;
class UuidFactory implements UuidFactoryInterface
{
/**
* @var CodecInterface
*/
- private $codec = null;
+ private $codec;
+
+ /**
+ * @var DceSecurityGeneratorInterface
+ */
+ private $dceSecurityGenerator;
+
+ /**
+ * @var NameGeneratorInterface
+ */
+ private $nameGenerator;
/**
* @var NodeProviderInterface
*/
- private $nodeProvider = null;
+ private $nodeProvider;
/**
* @var NumberConverterInterface
*/
- private $numberConverter = null;
+ private $numberConverter;
/**
* @var RandomGeneratorInterface
*/
- private $randomGenerator = null;
+ private $randomGenerator;
+
+ /**
+ * @var TimeConverterInterface
+ */
+ private $timeConverter;
/**
* @var TimeGeneratorInterface
*/
- private $timeGenerator = null;
+ private $timeGenerator;
/**
* @var UuidBuilderInterface
*/
- private $uuidBuilder = null;
+ private $uuidBuilder;
/**
- * Constructs a `UuidFactory` for creating `Ramsey\Uuid\UuidInterface` instances
- *
- * @param FeatureSet $features A set of features for use when creating UUIDs
+ * @var ValidatorInterface
+ */
+ private $validator;
+
+ /** @var bool whether the feature set was provided from outside, or we can operate under "default" assumptions */
+ private $isDefaultFeatureSet;
+
+ /**
+ * @param FeatureSet $features A set of available features in the current environment
*/
- public function __construct(FeatureSet $features = null)
+ public function __construct(?FeatureSet $features = null)
{
+ $this->isDefaultFeatureSet = $features === null;
+
$features = $features ?: new FeatureSet();
$this->codec = $features->getCodec();
+ $this->dceSecurityGenerator = $features->getDceSecurityGenerator();
+ $this->nameGenerator = $features->getNameGenerator();
$this->nodeProvider = $features->getNodeProvider();
$this->numberConverter = $features->getNumberConverter();
$this->randomGenerator = $features->getRandomGenerator();
+ $this->timeConverter = $features->getTimeConverter();
$this->timeGenerator = $features->getTimeGenerator();
$this->uuidBuilder = $features->getBuilder();
+ $this->validator = $features->getValidator();
}
/**
- * Returns the UUID coder-decoder used by this factory
- *
- * @return CodecInterface
+ * Returns the codec used by this factory
*/
- public function getCodec()
+ public function getCodec(): CodecInterface
{
return $this->codec;
}
/**
- * Sets the UUID coder-decoder used by this factory
+ * Sets the codec to use for this factory
*
- * @param CodecInterface $codec
+ * @param CodecInterface $codec A UUID encoder-decoder
*/
- public function setCodec(CodecInterface $codec)
+ public function setCodec(CodecInterface $codec): void
{
+ $this->isDefaultFeatureSet = false;
+
$this->codec = $codec;
}
/**
- * Returns the system node ID provider used by this factory
+ * Returns the name generator used by this factory
+ */
+ public function getNameGenerator(): NameGeneratorInterface
+ {
+ return $this->nameGenerator;
+ }
+
+ /**
+ * Sets the name generator to use for this factory
*
- * @return NodeProviderInterface
+ * @param NameGeneratorInterface $nameGenerator A generator to generate
+ * binary data, based on a namespace and name
+ */
+ public function setNameGenerator(NameGeneratorInterface $nameGenerator): void
+ {
+ $this->isDefaultFeatureSet = false;
+
+ $this->nameGenerator = $nameGenerator;
+ }
+
+ /**
+ * Returns the node provider used by this factory
*/
- public function getNodeProvider()
+ public function getNodeProvider(): NodeProviderInterface
{
return $this->nodeProvider;
}
/**
- * Returns the random UUID generator used by this factory
- *
- * @return RandomGeneratorInterface
+ * Returns the random generator used by this factory
*/
- public function getRandomGenerator()
+ public function getRandomGenerator(): RandomGeneratorInterface
{
return $this->randomGenerator;
}
/**
- * Returns the time-based UUID generator used by this factory
- *
- * @return TimeGeneratorInterface
+ * Returns the time generator used by this factory
*/
- public function getTimeGenerator()
+ public function getTimeGenerator(): TimeGeneratorInterface
{
return $this->timeGenerator;
}
/**
- * Sets the time-based UUID generator this factory will use to generate version 1 UUIDs
+ * Sets the time generator to use for this factory
*
- * @param TimeGeneratorInterface $generator
+ * @param TimeGeneratorInterface $generator A generator to generate binary
+ * data, based on the time
*/
- public function setTimeGenerator(TimeGeneratorInterface $generator)
+ public function setTimeGenerator(TimeGeneratorInterface $generator): void
{
+ $this->isDefaultFeatureSet = false;
+
$this->timeGenerator = $generator;
}
/**
- * Returns the number converter used by this factory
+ * Returns the DCE Security generator used by this factory
+ */
+ public function getDceSecurityGenerator(): DceSecurityGeneratorInterface
+ {
+ return $this->dceSecurityGenerator;
+ }
+
+ /**
+ * Sets the DCE Security generator to use for this factory
*
- * @return NumberConverterInterface
+ * @param DceSecurityGeneratorInterface $generator A generator to generate
+ * binary data, based on a local domain and local identifier
*/
- public function getNumberConverter()
+ public function setDceSecurityGenerator(DceSecurityGeneratorInterface $generator): void
+ {
+ $this->isDefaultFeatureSet = false;
+
+ $this->dceSecurityGenerator = $generator;
+ }
+
+ /**
+ * Returns the number converter used by this factory
+ */
+ public function getNumberConverter(): NumberConverterInterface
{
return $this->numberConverter;
}
/**
- * Sets the random UUID generator this factory will use to generate version 4 UUIDs
+ * Sets the random generator to use for this factory
*
- * @param RandomGeneratorInterface $generator
+ * @param RandomGeneratorInterface $generator A generator to generate binary
+ * data, based on some random input
*/
- public function setRandomGenerator(RandomGeneratorInterface $generator)
+ public function setRandomGenerator(RandomGeneratorInterface $generator): void
{
+ $this->isDefaultFeatureSet = false;
+
$this->randomGenerator = $generator;
}
/**
- * Sets the number converter this factory will use
+ * Sets the number converter to use for this factory
*
- * @param NumberConverterInterface $converter
+ * @param NumberConverterInterface $converter A converter to use for working
+ * with large integers (i.e. integers greater than PHP_INT_MAX)
*/
- public function setNumberConverter(NumberConverterInterface $converter)
+ public function setNumberConverter(NumberConverterInterface $converter): void
{
+ $this->isDefaultFeatureSet = false;
+
$this->numberConverter = $converter;
}
/**
- * Returns the UUID builder this factory uses when creating `Uuid` instances
- *
- * @return UuidBuilderInterface $builder
+ * Returns the UUID builder used by this factory
*/
- public function getUuidBuilder()
+ public function getUuidBuilder(): UuidBuilderInterface
{
return $this->uuidBuilder;
}
/**
- * Sets the UUID builder this factory will use when creating `Uuid` instances
+ * Sets the UUID builder to use for this factory
*
- * @param UuidBuilderInterface $builder
+ * @param UuidBuilderInterface $builder A builder for constructing instances
+ * of UuidInterface
*/
- public function setUuidBuilder(UuidBuilderInterface $builder)
+ public function setUuidBuilder(UuidBuilderInterface $builder): void
{
+ $this->isDefaultFeatureSet = false;
+
$this->uuidBuilder = $builder;
}
/**
- * @inheritdoc
+ * @psalm-mutation-free
+ */
+ public function getValidator(): ValidatorInterface
+ {
+ return $this->validator;
+ }
+
+ /**
+ * Sets the validator to use for this factory
+ *
+ * @param ValidatorInterface $validator A validator to use for validating
+ * whether a string is a valid UUID
+ */
+ public function setValidator(ValidatorInterface $validator): void
+ {
+ $this->isDefaultFeatureSet = false;
+
+ $this->validator = $validator;
+ }
+
+ /**
+ * @psalm-pure
*/
- public function fromBytes($bytes)
+ public function fromBytes(string $bytes): UuidInterface
{
return $this->codec->decodeBytes($bytes);
}
/**
- * @inheritdoc
+ * @psalm-pure
*/
- public function fromString($uuid)
+ public function fromString(string $uuid): UuidInterface
{
$uuid = strtolower($uuid);
+
return $this->codec->decode($uuid);
}
/**
- * @inheritdoc
+ * @psalm-pure
*/
- public function fromInteger($integer)
+ public function fromInteger(string $integer): UuidInterface
{
$hex = $this->numberConverter->toHex($integer);
$hex = str_pad($hex, 32, '0', STR_PAD_LEFT);
@@ -209,107 +323,167 @@ class UuidFactory implements UuidFactoryInterface
return $this->fromString($hex);
}
+ public function fromDateTime(
+ DateTimeInterface $dateTime,
+ ?Hexadecimal $node = null,
+ ?int $clockSeq = null
+ ): UuidInterface {
+ $timeProvider = new FixedTimeProvider(
+ new Time($dateTime->format('U'), $dateTime->format('u'))
+ );
+
+ $timeGenerator = new DefaultTimeGenerator(
+ $this->nodeProvider,
+ $this->timeConverter,
+ $timeProvider
+ );
+
+ $nodeHex = $node ? $node->toString() : null;
+
+ $bytes = $timeGenerator->generate($nodeHex, $clockSeq);
+
+ return $this->uuidFromBytesAndVersion($bytes, 1);
+ }
+
/**
- * @inheritdoc
+ * @inheritDoc
*/
- public function uuid1($node = null, $clockSeq = null)
+ public function uuid1($node = null, ?int $clockSeq = null): UuidInterface
{
$bytes = $this->timeGenerator->generate($node, $clockSeq);
- $hex = bin2hex($bytes);
- return $this->uuidFromHashedName($hex, 1);
+ return $this->uuidFromBytesAndVersion($bytes, 1);
+ }
+
+ public function uuid2(
+ int $localDomain,
+ ?IntegerObject $localIdentifier = null,
+ ?Hexadecimal $node = null,
+ ?int $clockSeq = null
+ ): UuidInterface {
+ $bytes = $this->dceSecurityGenerator->generate(
+ $localDomain,
+ $localIdentifier,
+ $node,
+ $clockSeq
+ );
+
+ return $this->uuidFromBytesAndVersion($bytes, 2);
}
/**
- * @inheritdoc
+ * @inheritDoc
+ * @psalm-pure
*/
- public function uuid3($ns, $name)
+ public function uuid3($ns, string $name): UuidInterface
{
return $this->uuidFromNsAndName($ns, $name, 3, 'md5');
}
- /**
- * @inheritdoc
- */
- public function uuid4()
+ public function uuid4(): UuidInterface
{
$bytes = $this->randomGenerator->generate(16);
- // When converting the bytes to hex, it turns into a 32-character
- // hexadecimal string that looks a lot like an MD5 hash, so at this
- // point, we can just pass it to uuidFromHashedName.
- $hex = bin2hex($bytes);
-
- return $this->uuidFromHashedName($hex, 4);
+ return $this->uuidFromBytesAndVersion($bytes, 4);
}
/**
- * @inheritdoc
+ * @inheritDoc
+ * @psalm-pure
*/
- public function uuid5($ns, $name)
+ public function uuid5($ns, string $name): UuidInterface
{
return $this->uuidFromNsAndName($ns, $name, 5, 'sha1');
}
+ public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface
+ {
+ $nodeHex = $node ? $node->toString() : null;
+ $bytes = $this->timeGenerator->generate($nodeHex, $clockSeq);
+
+ // Rearrange the bytes, according to the UUID version 6 specification.
+ $v6 = $bytes[6] . $bytes[7] . $bytes[4] . $bytes[5]
+ . $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3];
+ $v6 = bin2hex($v6);
+
+ // Drop the first four bits, while adding an empty four bits for the
+ // version field. This allows us to reconstruct the correct time from
+ // the bytes of this UUID.
+ $v6Bytes = hex2bin(substr($v6, 1, 12) . '0' . substr($v6, -3));
+ $v6Bytes .= substr($bytes, 8);
+
+ return $this->uuidFromBytesAndVersion($v6Bytes, 6);
+ }
+
/**
- * Returns a `Uuid`
+ * Returns a Uuid created from the provided byte string
+ *
+ * Uses the configured builder and codec and the provided byte string to
+ * construct a Uuid object.
+ *
+ * @param string $bytes The byte string from which to construct a UUID
*
- * Uses the configured builder and codec and the provided array of hexadecimal
- * value UUID fields to construct a `Uuid` object.
+ * @return UuidInterface An instance of UuidInterface, created from the
+ * provided bytes
*
- * @param array $fields An array of fields from which to construct a UUID;
- * see {@see \Ramsey\Uuid\UuidInterface::getFieldsHex()} for array structure.
- * @return UuidInterface
+ * @psalm-pure
*/
- public function uuid(array $fields)
+ public function uuid(string $bytes): UuidInterface
{
- return $this->uuidBuilder->build($this->codec, $fields);
+ return $this->uuidBuilder->build($this->codec, $bytes);
}
/**
- * Returns a version 3 or 5 namespaced `Uuid`
+ * Returns a version 3 or 5 namespaced Uuid
*
- * @param string|UuidInterface $ns The UUID namespace to use
- * @param string $name The string to hash together with the namespace
+ * @param string|UuidInterface $ns The namespace (must be a valid UUID)
+ * @param string $name The name to hash together with the namespace
* @param int $version The version of UUID to create (3 or 5)
- * @param string $hashFunction The hash function to use when hashing together
- * the namespace and name
- * @return UuidInterface
- * @throws InvalidUuidStringException
+ * @param string $hashAlgorithm The hashing algorithm to use when hashing
+ * together the namespace and name
+ *
+ * @return UuidInterface An instance of UuidInterface, created by hashing
+ * together the provided namespace and name
+ *
+ * @psalm-pure
*/
- protected function uuidFromNsAndName($ns, $name, $version, $hashFunction)
+ private function uuidFromNsAndName($ns, string $name, int $version, string $hashAlgorithm): UuidInterface
{
if (!($ns instanceof UuidInterface)) {
- $ns = $this->codec->decode($ns);
+ $ns = $this->fromString($ns);
}
- $hash = call_user_func($hashFunction, ($ns->getBytes() . $name));
+ $bytes = $this->nameGenerator->generate($ns, $name, $hashAlgorithm);
- return $this->uuidFromHashedName($hash, $version);
+ return $this->uuidFromBytesAndVersion(substr($bytes, 0, 16), $version);
}
/**
- * Returns a `Uuid` created from `$hash` with the version field set to `$version`
- * and the variant field set for RFC 4122
+ * Returns an RFC 4122 variant Uuid, created from the provided bytes and version
+ *
+ * @param string $bytes The byte string to convert to a UUID
+ * @param int $version The RFC 4122 version to apply to the UUID
*
- * @param string $hash The hash to use when creating the UUID
- * @param int $version The UUID version to set for this hash (1, 3, 4, or 5)
- * @return UuidInterface
+ * @return UuidInterface An instance of UuidInterface, created from the
+ * byte string and version
+ *
+ * @psalm-pure
*/
- protected function uuidFromHashedName($hash, $version)
+ private function uuidFromBytesAndVersion(string $bytes, int $version): UuidInterface
{
- $timeHi = BinaryUtils::applyVersion(substr($hash, 12, 4), $version);
- $clockSeqHi = BinaryUtils::applyVariant(hexdec(substr($hash, 16, 2)));
-
- $fields = [
- 'time_low' => substr($hash, 0, 8),
- 'time_mid' => substr($hash, 8, 4),
- 'time_hi_and_version' => str_pad(dechex($timeHi), 4, '0', STR_PAD_LEFT),
- 'clock_seq_hi_and_reserved' => str_pad(dechex($clockSeqHi), 2, '0', STR_PAD_LEFT),
- 'clock_seq_low' => substr($hash, 18, 2),
- 'node' => substr($hash, 20, 12),
- ];
-
- return $this->uuid($fields);
+ $timeHi = (int) unpack('n*', substr($bytes, 6, 2))[1];
+ $timeHiAndVersion = pack('n*', BinaryUtils::applyVersion($timeHi, $version));
+
+ $clockSeqHi = (int) unpack('n*', substr($bytes, 8, 2))[1];
+ $clockSeqHiAndReserved = pack('n*', BinaryUtils::applyVariant($clockSeqHi));
+
+ $bytes = substr_replace($bytes, $timeHiAndVersion, 6, 2);
+ $bytes = substr_replace($bytes, $clockSeqHiAndReserved, 8, 2);
+
+ if ($this->isDefaultFeatureSet) {
+ return LazyUuidFromString::fromBytes($bytes);
+ }
+
+ return $this->uuid($bytes);
}
}