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

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 function assert;
  24. use function bin2hex;
  25. use function hex2bin;
  26. use function str_replace;
  27. use function substr;
  28. /**
  29.  * Lazy version of a UUID: its format has not been determined yet, so it is mostly only usable for string/bytes
  30.  * conversion. This object optimizes instantiation, serialization and string conversion time, at the cost of
  31.  * increased overhead for more advanced UUID operations.
  32.  *
  33.  * @internal this type is used internally for performance reasons, and is not supposed to be directly referenced
  34.  *           in consumer libraries.
  35.  *
  36.  * @psalm-immutable
  37.  *
  38.  * Note: the {@see FieldsInterface} does not declare methods that deprecated API
  39.  *        relies upon: the API has been ported from the {@see \Ramsey\Uuid\Uuid} definition,
  40.  *        and is deprecated anyway.
  41.  * Note: the deprecated API from {@see \Ramsey\Uuid\Uuid} is in use here (on purpose): it will be removed
  42.  *       once the deprecated API is gone from this class too.
  43.  *
  44.  * @psalm-suppress UndefinedInterfaceMethod
  45.  * @psalm-suppress DeprecatedMethod
  46.  */
  47. final class LazyUuidFromString implements UuidInterface
  48. {
  49.     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';
  50.     /**
  51.      * @var string
  52.      * @psalm-var non-empty-string
  53.      */
  54.     private $uuid;
  55.     /** @var UuidInterface|null */
  56.     private $unwrapped;
  57.     /** @psalm-param non-empty-string $uuid */
  58.     public function __construct(string $uuid)
  59.     {
  60.         $this->uuid $uuid;
  61.     }
  62.     /** @psalm-pure */
  63.     public static function fromBytes(string $bytes): self
  64.     {
  65.         $base16Uuid bin2hex($bytes);
  66.         return new self(
  67.             substr($base16Uuid08)
  68.             . '-'
  69.             substr($base16Uuid84)
  70.             . '-'
  71.             substr($base16Uuid124)
  72.             . '-'
  73.             substr($base16Uuid164)
  74.             . '-'
  75.             substr($base16Uuid2012)
  76.         );
  77.     }
  78.     public function serialize(): string
  79.     {
  80.         return $this->uuid;
  81.     }
  82.     /**
  83.      * {@inheritDoc}
  84.      *
  85.      * @param string $serialized
  86.      *
  87.      * @psalm-param non-empty-string $serialized
  88.      */
  89.     public function unserialize($serialized): void
  90.     {
  91.         $this->uuid $serialized;
  92.     }
  93.     /** @psalm-suppress DeprecatedMethod */
  94.     public function getNumberConverter(): NumberConverterInterface
  95.     {
  96.         return ($this->unwrapped ?? $this->unwrap())
  97.             ->getNumberConverter();
  98.     }
  99.     /**
  100.      * {@inheritDoc}
  101.      *
  102.      * @psalm-suppress DeprecatedMethod
  103.      */
  104.     public function getFieldsHex(): array
  105.     {
  106.         return ($this->unwrapped ?? $this->unwrap())
  107.             ->getFieldsHex();
  108.     }
  109.     /** @psalm-suppress DeprecatedMethod */
  110.     public function getClockSeqHiAndReservedHex(): string
  111.     {
  112.         return ($this->unwrapped ?? $this->unwrap())
  113.             ->getClockSeqHiAndReservedHex();
  114.     }
  115.     /** @psalm-suppress DeprecatedMethod */
  116.     public function getClockSeqLowHex(): string
  117.     {
  118.         return ($this->unwrapped ?? $this->unwrap())
  119.             ->getClockSeqLowHex();
  120.     }
  121.     /** @psalm-suppress DeprecatedMethod */
  122.     public function getClockSequenceHex(): string
  123.     {
  124.         return ($this->unwrapped ?? $this->unwrap())
  125.             ->getClockSequenceHex();
  126.     }
  127.     /** @psalm-suppress DeprecatedMethod */
  128.     public function getDateTime(): DateTimeInterface
  129.     {
  130.         return ($this->unwrapped ?? $this->unwrap())
  131.             ->getDateTime();
  132.     }
  133.     /** @psalm-suppress DeprecatedMethod */
  134.     public function getLeastSignificantBitsHex(): string
  135.     {
  136.         return ($this->unwrapped ?? $this->unwrap())
  137.             ->getLeastSignificantBitsHex();
  138.     }
  139.     /** @psalm-suppress DeprecatedMethod */
  140.     public function getMostSignificantBitsHex(): string
  141.     {
  142.         return ($this->unwrapped ?? $this->unwrap())
  143.             ->getMostSignificantBitsHex();
  144.     }
  145.     /** @psalm-suppress DeprecatedMethod */
  146.     public function getNodeHex(): string
  147.     {
  148.         return ($this->unwrapped ?? $this->unwrap())
  149.             ->getNodeHex();
  150.     }
  151.     /** @psalm-suppress DeprecatedMethod */
  152.     public function getTimeHiAndVersionHex(): string
  153.     {
  154.         return ($this->unwrapped ?? $this->unwrap())
  155.             ->getTimeHiAndVersionHex();
  156.     }
  157.     /** @psalm-suppress DeprecatedMethod */
  158.     public function getTimeLowHex(): string
  159.     {
  160.         return ($this->unwrapped ?? $this->unwrap())
  161.             ->getTimeLowHex();
  162.     }
  163.     /** @psalm-suppress DeprecatedMethod */
  164.     public function getTimeMidHex(): string
  165.     {
  166.         return ($this->unwrapped ?? $this->unwrap())
  167.             ->getTimeMidHex();
  168.     }
  169.     /** @psalm-suppress DeprecatedMethod */
  170.     public function getTimestampHex(): string
  171.     {
  172.         return ($this->unwrapped ?? $this->unwrap())
  173.             ->getTimestampHex();
  174.     }
  175.     /** @psalm-suppress DeprecatedMethod */
  176.     public function getUrn(): string
  177.     {
  178.         return ($this->unwrapped ?? $this->unwrap())
  179.             ->getUrn();
  180.     }
  181.     /** @psalm-suppress DeprecatedMethod */
  182.     public function getVariant(): ?int
  183.     {
  184.         return ($this->unwrapped ?? $this->unwrap())
  185.             ->getVariant();
  186.     }
  187.     /** @psalm-suppress DeprecatedMethod */
  188.     public function getVersion(): ?int
  189.     {
  190.         return ($this->unwrapped ?? $this->unwrap())
  191.             ->getVersion();
  192.     }
  193.     public function compareTo(UuidInterface $other): int
  194.     {
  195.         return ($this->unwrapped ?? $this->unwrap())
  196.             ->compareTo($other);
  197.     }
  198.     public function equals(?object $other): bool
  199.     {
  200.         if (! $other instanceof UuidInterface) {
  201.             return false;
  202.         }
  203.         return $this->uuid === $other->toString();
  204.     }
  205.     /**
  206.      * {@inheritDoc}
  207.      *
  208.      * @psalm-suppress MoreSpecificReturnType
  209.      * @psalm-suppress LessSpecificReturnStatement we know that {@see self::$uuid} is a non-empty string, so
  210.      *                                             we know that {@see hex2bin} will retrieve a non-empty string too.
  211.      */
  212.     public function getBytes(): string
  213.     {
  214.         return (string) hex2bin(str_replace('-'''$this->uuid));
  215.     }
  216.     public function getFields(): FieldsInterface
  217.     {
  218.         return ($this->unwrapped ?? $this->unwrap())
  219.             ->getFields();
  220.     }
  221.     public function getHex(): Hexadecimal
  222.     {
  223.         return ($this->unwrapped ?? $this->unwrap())
  224.             ->getHex();
  225.     }
  226.     public function getInteger(): IntegerObject
  227.     {
  228.         return ($this->unwrapped ?? $this->unwrap())
  229.             ->getInteger();
  230.     }
  231.     public function toString(): string
  232.     {
  233.         return $this->uuid;
  234.     }
  235.     public function __toString(): string
  236.     {
  237.         return $this->uuid;
  238.     }
  239.     public function jsonSerialize(): string
  240.     {
  241.         return $this->uuid;
  242.     }
  243.     /**
  244.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  245.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  246.      *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
  247.      *     and use the arbitrary-precision math library of your choice to
  248.      *     convert it to a string integer.
  249.      *
  250.      * @psalm-suppress UndefinedInterfaceMethod
  251.      * @psalm-suppress DeprecatedMethod
  252.      * @psalm-suppress MixedArgument
  253.      * @psalm-suppress MixedMethodCall
  254.      */
  255.     public function getClockSeqHiAndReserved(): string
  256.     {
  257.         $instance = ($this->unwrapped ?? $this->unwrap());
  258.         return $instance->getNumberConverter()
  259.             ->fromHex(
  260.                 $instance->getFields()
  261.                     ->getClockSeqHiAndReserved()
  262.                     ->toString()
  263.             );
  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::getClockSeqLow()}
  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 getClockSeqLow(): string
  278.     {
  279.         $instance = ($this->unwrapped ?? $this->unwrap());
  280.         return $instance->getNumberConverter()
  281.             ->fromHex(
  282.                 $instance->getFields()
  283.                     ->getClockSeqLow()
  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::getClockSeq()}
  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 getClockSequence(): string
  300.     {
  301.         $instance = ($this->unwrapped ?? $this->unwrap());
  302.         return $instance->getNumberConverter()
  303.             ->fromHex(
  304.                 $instance->getFields()
  305.                     ->getClockSeq()
  306.                     ->toString()
  307.             );
  308.     }
  309.     /**
  310.      * @deprecated This method will be removed in 5.0.0. There is no direct
  311.      *     alternative, but the same information may be obtained by splitting
  312.      *     in half the value returned by {@see UuidInterface::getHex()}.
  313.      *
  314.      * @psalm-suppress UndefinedInterfaceMethod
  315.      * @psalm-suppress DeprecatedMethod
  316.      * @psalm-suppress MixedArgument
  317.      * @psalm-suppress MixedMethodCall
  318.      */
  319.     public function getLeastSignificantBits(): string
  320.     {
  321.         $instance = ($this->unwrapped ?? $this->unwrap());
  322.         return $instance->getNumberConverter()
  323.             ->fromHex(substr($instance->getHex()->toString(), 16));
  324.     }
  325.     /**
  326.      * @deprecated This method will be removed in 5.0.0. There is no direct
  327.      *     alternative, but the same information may be obtained by splitting
  328.      *     in half the value returned by {@see UuidInterface::getHex()}.
  329.      *
  330.      * @psalm-suppress UndefinedInterfaceMethod
  331.      * @psalm-suppress DeprecatedMethod
  332.      * @psalm-suppress MixedArgument
  333.      * @psalm-suppress MixedMethodCall
  334.      */
  335.     public function getMostSignificantBits(): string
  336.     {
  337.         $instance = ($this->unwrapped ?? $this->unwrap());
  338.         return $instance->getNumberConverter()
  339.             ->fromHex(substr($instance->getHex()->toString(), 016));
  340.     }
  341.     /**
  342.      * @deprecated Use {@see UuidInterface::getFields()} to get a
  343.      *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
  344.      *     instance, you may call {@see Rfc4122FieldsInterface::getNode()}
  345.      *     and use the arbitrary-precision math library of your choice to
  346.      *     convert it to a string integer.
  347.      *
  348.      * @psalm-suppress UndefinedInterfaceMethod
  349.      * @psalm-suppress DeprecatedMethod
  350.      * @psalm-suppress MixedArgument
  351.      * @psalm-suppress MixedMethodCall
  352.      */
  353.     public function getNode(): string
  354.     {
  355.         $instance = ($this->unwrapped ?? $this->unwrap());
  356.         return $instance->getNumberConverter()
  357.             ->fromHex(
  358.                 $instance->getFields()
  359.                     ->getNode()
  360.                     ->toString()
  361.             );
  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::getTimeHiAndVersion()}
  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 getTimeHiAndVersion(): string
  376.     {
  377.         $instance = ($this->unwrapped ?? $this->unwrap());
  378.         return $instance->getNumberConverter()
  379.             ->fromHex(
  380.                 $instance->getFields()
  381.                     ->getTimeHiAndVersion()
  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::getTimeLow()}
  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 getTimeLow(): string
  398.     {
  399.         $instance = ($this->unwrapped ?? $this->unwrap());
  400.         return $instance->getNumberConverter()
  401.             ->fromHex(
  402.                 $instance->getFields()
  403.                     ->getTimeLow()
  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::getTimeMid()}
  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 getTimeMid(): string
  420.     {
  421.         $instance = ($this->unwrapped ?? $this->unwrap());
  422.         return $instance->getNumberConverter()
  423.             ->fromHex(
  424.                 $instance->getFields()
  425.                     ->getTimeMid()
  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::getTimestamp()}
  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 getTimestamp(): string
  442.     {
  443.         $instance = ($this->unwrapped ?? $this->unwrap());
  444.         $fields   $instance->getFields();
  445.         if ($fields->getVersion() !== 1) {
  446.             throw new UnsupportedOperationException('Not a time-based UUID');
  447.         }
  448.         return $instance->getNumberConverter()
  449.             ->fromHex($fields->getTimestamp()->toString());
  450.     }
  451.     public function toUuidV1(): UuidV1
  452.     {
  453.         $instance = ($this->unwrapped ?? $this->unwrap());
  454.         if ($instance instanceof UuidV1) {
  455.             return $instance;
  456.         }
  457.         assert($instance instanceof UuidV6);
  458.         return $instance->toUuidV1();
  459.     }
  460.     public function toUuidV6(): UuidV6
  461.     {
  462.         $instance = ($this->unwrapped ?? $this->unwrap());
  463.         assert($instance instanceof UuidV6);
  464.         return $instance;
  465.     }
  466.     /**
  467.      * @psalm-suppress ImpureMethodCall the retrieval of the factory is a clear violation of purity here: this is a
  468.      *                                  known pitfall of the design of this library, where a value object contains
  469.      *                                  a mutable reference to a factory. We use a fixed factory here, so the violation
  470.      *                                  will not have real-world effects, as this object is only instantiated with the
  471.      *                                  default factory settings/features.
  472.      * @psalm-suppress InaccessibleProperty property {@see $unwrapped} is used as a cache: we don't expose it to the
  473.      *                                      outside world, so we should be fine here.
  474.      */
  475.     private function unwrap(): UuidInterface
  476.     {
  477.         return $this->unwrapped = (new UuidFactory())
  478.             ->fromString($this->uuid);
  479.     }
  480. }