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