vendor/ramsey/uuid/src/Lazy/LazyUuidFromString.php line 55

Open in your IDE?
  1. <?php
  2. /**
  3.  * This file is part of the ramsey/uuid library
  4.  *
  5.  * For the full copyright and license information, please view the LICENSE
  6.  * file that was distributed with this source code.
  7.  *
  8.  * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
  9.  * @license http://opensource.org/licenses/MIT MIT
  10.  */
  11. declare(strict_types=1);
  12. namespace Ramsey\Uuid\Lazy;
  13. use DateTimeInterface;
  14. use Ramsey\Uuid\Converter\NumberConverterInterface;
  15. use Ramsey\Uuid\Exception\UnsupportedOperationException;
  16. use Ramsey\Uuid\Fields\FieldsInterface;
  17. use Ramsey\Uuid\Nonstandard\UuidV6;
  18. use Ramsey\Uuid\Rfc4122\UuidV1;
  19. use Ramsey\Uuid\Type\Hexadecimal;
  20. use Ramsey\Uuid\Type\Integer as IntegerObject;
  21. use Ramsey\Uuid\UuidFactory;
  22. use Ramsey\Uuid\UuidInterface;
  23. use ValueError;
  24. use function assert;
  25. use function bin2hex;
  26. use function hex2bin;
  27. use function sprintf;
  28. use function str_replace;
  29. use function substr;
  30. /**
  31.  * Lazy version of a UUID: its format has not been determined yet, so it is mostly only usable for string/bytes
  32.  * conversion. This object optimizes instantiation, serialization and string conversion time, at the cost of
  33.  * increased overhead for more advanced UUID operations.
  34.  *
  35.  * @internal this type is used internally for performance reasons, and is not supposed to be directly referenced
  36.  *           in consumer libraries.
  37.  *
  38.  * @psalm-immutable
  39.  *
  40.  * Note: the {@see FieldsInterface} does not declare methods that deprecated API
  41.  *        relies upon: the API has been ported from the {@see \Ramsey\Uuid\Uuid} definition,
  42.  *        and is deprecated anyway.
  43.  * Note: the deprecated API from {@see \Ramsey\Uuid\Uuid} is in use here (on purpose): it will be removed
  44.  *       once the deprecated API is gone from this class too.
  45.  *
  46.  * @psalm-suppress UndefinedInterfaceMethod
  47.  * @psalm-suppress DeprecatedMethod
  48.  */
  49. final class LazyUuidFromString implements UuidInterface
  50. {
  51.     public const VALID_REGEX '/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/ms';
  52.     /**
  53.      * @var string
  54.      * @psalm-var non-empty-string
  55.      */
  56.     private $uuid;
  57.     /** @var UuidInterface|null */
  58.     private $unwrapped;
  59.     /** @psalm-param non-empty-string $uuid */
  60.     public function __construct(string $uuid)
  61.     {
  62.         $this->uuid $uuid;
  63.     }
  64.     /** @psalm-pure */
  65.     public static function fromBytes(string $bytes): self
  66.     {
  67.         $base16Uuid bin2hex($bytes);
  68.         return new self(
  69.             substr($base16Uuid08)
  70.             . '-'
  71.             substr($base16Uuid84)
  72.             . '-'
  73.             substr($base16Uuid124)
  74.             . '-'
  75.             substr($base16Uuid164)
  76.             . '-'
  77.             substr($base16Uuid2012)
  78.         );
  79.     }
  80.     public function serialize(): string
  81.     {
  82.         return $this->uuid;
  83.     }
  84.     /**
  85.      * @return array{string: string}
  86.      *
  87.      * @psalm-return array{string: non-empty-string}
  88.      */
  89.     public function __serialize(): array
  90.     {
  91.         return ['string' => $this->uuid];
  92.     }
  93.     /**
  94.      * {@inheritDoc}
  95.      *
  96.      * @param string $serialized
  97.      *
  98.      * @psalm-param non-empty-string $serialized
  99.      */
  100.     public function unserialize($serialized): void
  101.     {
  102.         $this->uuid $serialized;
  103.     }
  104.     /**
  105.      * @param array{string: string} $data
  106.      *
  107.      * @psalm-param array{string: non-empty-string} $data
  108.      */
  109.     public function __unserialize(array $data): void
  110.     {
  111.         // @codeCoverageIgnoreStart
  112.         if (!isset($data['string'])) {
  113.             throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid'__METHOD__));
  114.         }
  115.         // @codeCoverageIgnoreEnd
  116.         $this->unserialize($data['string']);
  117.     }
  118.     /** @psalm-suppress DeprecatedMethod */
  119.     public function getNumberConverter(): NumberConverterInterface
  120.     {
  121.         return ($this->unwrapped ?? $this->unwrap())
  122.             ->getNumberConverter();
  123.     }
  124.     /**
  125.      * {@inheritDoc}
  126.      *
  127.      * @psalm-suppress DeprecatedMethod
  128.      */
  129.     public function getFieldsHex(): array
  130.     {
  131.         return ($this->unwrapped ?? $this->unwrap())
  132.             ->getFieldsHex();
  133.     }
  134.     /** @psalm-suppress DeprecatedMethod */
  135.     public function getClockSeqHiAndReservedHex(): string
  136.     {
  137.         return ($this->unwrapped ?? $this->unwrap())
  138.             ->getClockSeqHiAndReservedHex();
  139.     }
  140.     /** @psalm-suppress DeprecatedMethod */
  141.     public function getClockSeqLowHex(): string
  142.     {
  143.         return ($this->unwrapped ?? $this->unwrap())
  144.             ->getClockSeqLowHex();
  145.     }
  146.     /** @psalm-suppress DeprecatedMethod */
  147.     public function getClockSequenceHex(): string
  148.     {
  149.         return ($this->unwrapped ?? $this->unwrap())
  150.             ->getClockSequenceHex();
  151.     }
  152.     /** @psalm-suppress DeprecatedMethod */
  153.     public function getDateTime(): DateTimeInterface
  154.     {
  155.         return ($this->unwrapped ?? $this->unwrap())
  156.             ->getDateTime();
  157.     }
  158.     /** @psalm-suppress DeprecatedMethod */
  159.     public function getLeastSignificantBitsHex(): string
  160.     {
  161.         return ($this->unwrapped ?? $this->unwrap())
  162.             ->getLeastSignificantBitsHex();
  163.     }
  164.     /** @psalm-suppress DeprecatedMethod */
  165.     public function getMostSignificantBitsHex(): string
  166.     {
  167.         return ($this->unwrapped ?? $this->unwrap())
  168.             ->getMostSignificantBitsHex();
  169.     }
  170.     /** @psalm-suppress DeprecatedMethod */
  171.     public function getNodeHex(): string
  172.     {
  173.         return ($this->unwrapped ?? $this->unwrap())
  174.             ->getNodeHex();
  175.     }
  176.     /** @psalm-suppress DeprecatedMethod */
  177.     public function getTimeHiAndVersionHex(): string
  178.     {
  179.         return ($this->unwrapped ?? $this->unwrap())
  180.             ->getTimeHiAndVersionHex();
  181.     }
  182.     /** @psalm-suppress DeprecatedMethod */
  183.     public function getTimeLowHex(): string
  184.     {
  185.         return ($this->unwrapped ?? $this->unwrap())
  186.             ->getTimeLowHex();
  187.     }
  188.     /** @psalm-suppress DeprecatedMethod */
  189.     public function getTimeMidHex(): string
  190.     {
  191.         return ($this->unwrapped ?? $this->unwrap())
  192.             ->getTimeMidHex();
  193.     }
  194.     /** @psalm-suppress DeprecatedMethod */
  195.     public function getTimestampHex(): string
  196.     {
  197.         return ($this->unwrapped ?? $this->unwrap())
  198.             ->getTimestampHex();
  199.     }
  200.     /** @psalm-suppress DeprecatedMethod */
  201.     public function getUrn(): string
  202.     {
  203.         return ($this->unwrapped ?? $this->unwrap())
  204.             ->getUrn();
  205.     }
  206.     /** @psalm-suppress DeprecatedMethod */
  207.     public function getVariant(): ?int
  208.     {
  209.         return ($this->unwrapped ?? $this->unwrap())
  210.             ->getVariant();
  211.     }
  212.     /** @psalm-suppress DeprecatedMethod */
  213.     public function getVersion(): ?int
  214.     {
  215.         return ($this->unwrapped ?? $this->unwrap())
  216.             ->getVersion();
  217.     }
  218.     public function compareTo(UuidInterface $other): int
  219.     {
  220.         return ($this->unwrapped ?? $this->unwrap())
  221.             ->compareTo($other);
  222.     }
  223.     public function equals(?object $other): bool
  224.     {
  225.         if (! $other instanceof UuidInterface) {
  226.             return false;
  227.         }
  228.         return $this->uuid === $other->toString();
  229.     }
  230.     /**
  231.      * {@inheritDoc}
  232.      *
  233.      * @psalm-suppress MoreSpecificReturnType
  234.      * @psalm-suppress LessSpecificReturnStatement we know that {@see self::$uuid} is a non-empty string, so
  235.      *                                             we know that {@see hex2bin} will retrieve a non-empty string too.
  236.      */
  237.     public function getBytes(): string
  238.     {
  239.         /** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
  240.         return (string) hex2bin(str_replace('-'''$this->uuid));
  241.     }
  242.     public function getFields(): FieldsInterface
  243.     {
  244.         return ($this->unwrapped ?? $this->unwrap())
  245.             ->getFields();
  246.     }
  247.     public function getHex(): Hexadecimal
  248.     {
  249.         return ($this->unwrapped ?? $this->unwrap())
  250.             ->getHex();
  251.     }
  252.     public function getInteger(): IntegerObject
  253.     {
  254.         return ($this->unwrapped ?? $this->unwrap())
  255.             ->getInteger();
  256.     }
  257.     public function toString(): string
  258.     {
  259.         return $this->uuid;
  260.     }
  261.     public function __toString(): string
  262.     {
  263.         return $this->uuid;
  264.     }
  265.     public function jsonSerialize(): string
  266.     {
  267.         return $this->uuid;
  268.     }
  269.     /**
  270.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  271.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  272.      *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
  273.      *     and use the arbitrary-precision math library of your choice to
  274.      *     convert it to a string integer.
  275.      *
  276.      * @psalm-suppress UndefinedInterfaceMethod
  277.      * @psalm-suppress DeprecatedMethod
  278.      * @psalm-suppress MixedArgument
  279.      * @psalm-suppress MixedMethodCall
  280.      */
  281.     public function getClockSeqHiAndReserved(): string
  282.     {
  283.         $instance = ($this->unwrapped ?? $this->unwrap());
  284.         return $instance->getNumberConverter()
  285.             ->fromHex(
  286.                 $instance->getFields()
  287.                     ->getClockSeqHiAndReserved()
  288.                     ->toString()
  289.             );
  290.     }
  291.     /**
  292.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  293.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  294.      *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}
  295.      *     and use the arbitrary-precision math library of your choice to
  296.      *     convert it to a string integer.
  297.      *
  298.      * @psalm-suppress UndefinedInterfaceMethod
  299.      * @psalm-suppress DeprecatedMethod
  300.      * @psalm-suppress MixedArgument
  301.      * @psalm-suppress MixedMethodCall
  302.      */
  303.     public function getClockSeqLow(): string
  304.     {
  305.         $instance = ($this->unwrapped ?? $this->unwrap());
  306.         return $instance->getNumberConverter()
  307.             ->fromHex(
  308.                 $instance->getFields()
  309.                     ->getClockSeqLow()
  310.                     ->toString()
  311.             );
  312.     }
  313.     /**
  314.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  315.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  316.      *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}
  317.      *     and use the arbitrary-precision math library of your choice to
  318.      *     convert it to a string integer.
  319.      *
  320.      * @psalm-suppress UndefinedInterfaceMethod
  321.      * @psalm-suppress DeprecatedMethod
  322.      * @psalm-suppress MixedArgument
  323.      * @psalm-suppress MixedMethodCall
  324.      */
  325.     public function getClockSequence(): string
  326.     {
  327.         $instance = ($this->unwrapped ?? $this->unwrap());
  328.         return $instance->getNumberConverter()
  329.             ->fromHex(
  330.                 $instance->getFields()
  331.                     ->getClockSeq()
  332.                     ->toString()
  333.             );
  334.     }
  335.     /**
  336.      * @deprecated This method will be removed in 5.0.0. There is no direct
  337.      *     alternative, but the same information may be obtained by splitting
  338.      *     in half the value returned by {@see UuidInterface::getHex()}.
  339.      *
  340.      * @psalm-suppress UndefinedInterfaceMethod
  341.      * @psalm-suppress DeprecatedMethod
  342.      * @psalm-suppress MixedArgument
  343.      * @psalm-suppress MixedMethodCall
  344.      */
  345.     public function getLeastSignificantBits(): string
  346.     {
  347.         $instance = ($this->unwrapped ?? $this->unwrap());
  348.         return $instance->getNumberConverter()
  349.             ->fromHex(substr($instance->getHex()->toString(), 16));
  350.     }
  351.     /**
  352.      * @deprecated This method will be removed in 5.0.0. There is no direct
  353.      *     alternative, but the same information may be obtained by splitting
  354.      *     in half the value returned by {@see UuidInterface::getHex()}.
  355.      *
  356.      * @psalm-suppress UndefinedInterfaceMethod
  357.      * @psalm-suppress DeprecatedMethod
  358.      * @psalm-suppress MixedArgument
  359.      * @psalm-suppress MixedMethodCall
  360.      */
  361.     public function getMostSignificantBits(): string
  362.     {
  363.         $instance = ($this->unwrapped ?? $this->unwrap());
  364.         return $instance->getNumberConverter()
  365.             ->fromHex(substr($instance->getHex()->toString(), 016));
  366.     }
  367.     /**
  368.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  369.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  370.      *     instance, you may call {@see Rfc4122FieldsInterface::getNode()}
  371.      *     and use the arbitrary-precision math library of your choice to
  372.      *     convert it to a string integer.
  373.      *
  374.      * @psalm-suppress UndefinedInterfaceMethod
  375.      * @psalm-suppress DeprecatedMethod
  376.      * @psalm-suppress MixedArgument
  377.      * @psalm-suppress MixedMethodCall
  378.      */
  379.     public function getNode(): string
  380.     {
  381.         $instance = ($this->unwrapped ?? $this->unwrap());
  382.         return $instance->getNumberConverter()
  383.             ->fromHex(
  384.                 $instance->getFields()
  385.                     ->getNode()
  386.                     ->toString()
  387.             );
  388.     }
  389.     /**
  390.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  391.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  392.      *     instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}
  393.      *     and use the arbitrary-precision math library of your choice to
  394.      *     convert it to a string integer.
  395.      *
  396.      * @psalm-suppress UndefinedInterfaceMethod
  397.      * @psalm-suppress DeprecatedMethod
  398.      * @psalm-suppress MixedArgument
  399.      * @psalm-suppress MixedMethodCall
  400.      */
  401.     public function getTimeHiAndVersion(): string
  402.     {
  403.         $instance = ($this->unwrapped ?? $this->unwrap());
  404.         return $instance->getNumberConverter()
  405.             ->fromHex(
  406.                 $instance->getFields()
  407.                     ->getTimeHiAndVersion()
  408.                     ->toString()
  409.             );
  410.     }
  411.     /**
  412.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  413.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  414.      *     instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}
  415.      *     and use the arbitrary-precision math library of your choice to
  416.      *     convert it to a string integer.
  417.      *
  418.      * @psalm-suppress UndefinedInterfaceMethod
  419.      * @psalm-suppress DeprecatedMethod
  420.      * @psalm-suppress MixedArgument
  421.      * @psalm-suppress MixedMethodCall
  422.      */
  423.     public function getTimeLow(): string
  424.     {
  425.         $instance = ($this->unwrapped ?? $this->unwrap());
  426.         return $instance->getNumberConverter()
  427.             ->fromHex(
  428.                 $instance->getFields()
  429.                     ->getTimeLow()
  430.                     ->toString()
  431.             );
  432.     }
  433.     /**
  434.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  435.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  436.      *     instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}
  437.      *     and use the arbitrary-precision math library of your choice to
  438.      *     convert it to a string integer.
  439.      *
  440.      * @psalm-suppress UndefinedInterfaceMethod
  441.      * @psalm-suppress DeprecatedMethod
  442.      * @psalm-suppress MixedArgument
  443.      * @psalm-suppress MixedMethodCall
  444.      */
  445.     public function getTimeMid(): string
  446.     {
  447.         $instance = ($this->unwrapped ?? $this->unwrap());
  448.         return $instance->getNumberConverter()
  449.             ->fromHex(
  450.                 $instance->getFields()
  451.                     ->getTimeMid()
  452.                     ->toString()
  453.             );
  454.     }
  455.     /**
  456.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  457.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  458.      *     instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}
  459.      *     and use the arbitrary-precision math library of your choice to
  460.      *     convert it to a string integer.
  461.      *
  462.      * @psalm-suppress UndefinedInterfaceMethod
  463.      * @psalm-suppress DeprecatedMethod
  464.      * @psalm-suppress MixedArgument
  465.      * @psalm-suppress MixedMethodCall
  466.      */
  467.     public function getTimestamp(): string
  468.     {
  469.         $instance = ($this->unwrapped ?? $this->unwrap());
  470.         $fields $instance->getFields();
  471.         if ($fields->getVersion() !== 1) {
  472.             throw new UnsupportedOperationException('Not a time-based UUID');
  473.         }
  474.         return $instance->getNumberConverter()
  475.             ->fromHex($fields->getTimestamp()->toString());
  476.     }
  477.     public function toUuidV1(): UuidV1
  478.     {
  479.         $instance = ($this->unwrapped ?? $this->unwrap());
  480.         if ($instance instanceof UuidV1) {
  481.             return $instance;
  482.         }
  483.         assert($instance instanceof UuidV6);
  484.         return $instance->toUuidV1();
  485.     }
  486.     public function toUuidV6(): UuidV6
  487.     {
  488.         $instance = ($this->unwrapped ?? $this->unwrap());
  489.         assert($instance instanceof UuidV6);
  490.         return $instance;
  491.     }
  492.     /**
  493.      * @psalm-suppress ImpureMethodCall the retrieval of the factory is a clear violation of purity here: this is a
  494.      *                                  known pitfall of the design of this library, where a value object contains
  495.      *                                  a mutable reference to a factory. We use a fixed factory here, so the violation
  496.      *                                  will not have real-world effects, as this object is only instantiated with the
  497.      *                                  default factory settings/features.
  498.      * @psalm-suppress InaccessibleProperty property {@see $unwrapped} is used as a cache: we don't expose it to the
  499.      *                                      outside world, so we should be fine here.
  500.      */
  501.     private function unwrap(): UuidInterface
  502.     {
  503.         return $this->unwrapped = (new UuidFactory())
  504.             ->fromString($this->uuid);
  505.     }
  506. }