Server IP : 213.176.29.180  /  Your IP : 3.142.251.42
Web Server : Apache
System : Linux 213.176.29.180.hostiran.name 4.18.0-553.22.1.el8_10.x86_64 #1 SMP Tue Sep 24 05:16:59 EDT 2024 x86_64
User : webtaragh ( 1001)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON
Directory (0750) :  /home/webtaragh/public_html/whmcs/feeds/../../

[  Home  ][  C0mmand  ][  Upload File  ]

Current File : /home/webtaragh/public_html/whmcs/feeds/../../ramsey.tar
uuid/CONTRIBUTING.md000064400000010640147361033650007754 0ustar00# Contributing

Contributions are welcome. We accept pull requests on [GitHub](https://github.com/ramsey/uuid).

This project adheres to a [Contributor Code of Conduct](https://github.com/ramsey/uuid/blob/master/CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code.

## Team members

* [Ben Ramsey](https://github.com/ramsey) - original author and maintainer
* [Marijn Huizendveld](https://github.com/marijn) - contributor, author of UUID type definition for Doctrine DBAL
* [Thibaud Fabre](https://github.com/aztech-dev) - contributor, lead developer for version 3.0.0 re-architecture

## Communication Channels

You can find help and discussion in the following places:

* Gitter chat: <https://gitter.im/ramsey/uuid>
* GitHub Issues: <https://github.com/ramsey/uuid/issues>
* Wiki: <https://github.com/ramsey/uuid/wiki>

## Reporting Bugs

Bugs are tracked in our project's [issue tracker](https://github.com/ramsey/uuid/issues).

When submitting a bug report, please include enough information for us to reproduce the bug. A good bug report includes the following sections:

* Expected outcome
* Actual outcome
* Steps to reproduce, including sample code
* Any other information that will help us debug and reproduce the issue, including stack traces, system/environment information, and screenshots

**Please do not include passwords or any personally identifiable information in your bug report and sample code.**

## Fixing Bugs

We welcome pull requests to fix bugs!

If you see a bug report that you'd like to fix, please feel free to do so. Following the directions and guidelines described in the "Adding New Features" section below, you may create bugfix branches and send us pull requests.

## Adding New Features

If you have an idea for a new feature, it's a good idea to check out our [issues](https://github.com/ramsey/uuid/issues) or active [pull requests](https://github.com/ramsey/uuid/pulls) first to see if the feature is already being worked on. If not, feel free to submit an issue first, asking whether the feature is beneficial to the project. This will save you from doing a lot of development work only to have your feature rejected. We don't enjoy rejecting your hard work, but some features just don't fit with the goals of the project.

When you do begin working on your feature, here are some guidelines to consider:

* Your pull request description should clearly detail the changes you have made. We will use this description to add to our CHANGELOG. If there is no description or it does not adequately describe your feature, we will ask you to update the description.
* We following the **[PSR-2 coding standard](http://www.php-fig.org/psr/psr-2/)**. Please ensure your code does, too.
* Please **write tests** for any new features you add.
* Please **ensure that tests pass** before submitting your pull request. We have Travis CI automatically running tests for pull requests. However, running the tests locally will help save time.
* **Use topic/feature branches.** Please do not ask us to pull from your master branch.
* **Submit one feature per pull request.** If you have multiple features you wish to submit, please break them up into separate pull requests.
* **Send coherent history**. Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.

## Running Tests

The following tests must pass before we will accept a pull request. If any of these do not pass, it will result in a complete build failure. Before you can run these, be sure to `composer install`.

```
./vendor/bin/parallel-lint src tests
./vendor/bin/phpcs src tests --standard=psr2 -sp
./vendor/bin/phpunit --verbose
```

### Locally Test With Emulated MIPS Architecture

The following commands use [Vagrant](https://www.vagrantup.com/) to start an Ubuntu VM, install necessary dependencies, and then run the `util/run-tests.sh` script that will download a Docker image emulating the MIPS architecture. This is especially helpful for testing UUID generation in a big-endian environment.

```
vagrant init ubuntu/trusty64
vagrant up
vagrant ssh
sudo apt-get install docker.io qemu-user-static php5-cli php5-curl
cd /vagrant
curl -sS https://getcomposer.org/installer | php
php composer.phar install --no-interaction --prefer-dist
mkdir -p build/logs
ARCH=mips PHP_VERSION=5.6.14 TRAVIS_BUILD_DIR=/vagrant ./util/run-tests.sh
```
uuid/.readthedocs.yml000064400000000215147361033650010606 0ustar00version: 2

sphinx:
  configuration: docs/conf.py

formats: all

python:
  version: 3.7
  install:
    - requirements: docs/requirements.txt
uuid/util/hhvm-docker/Dockerfile000064400000001220147361033650012673 0ustar00FROM benramsey/hhvm-dev:3.12.0

RUN apt-get update -y && apt-get install -y build-essential curl wget git uuid-dev libuuid1
RUN wget https://github.com/vipsoft/hhvm-ext-uuid/archive/ba0ebae0fe.tar.gz \
  && tar zxf ba0ebae0fe.tar.gz \
  && cd hhvm-ext-uuid-ba0ebae0fe123e8545ea02110db2f0102c08d637/ \
  && hphpize \
  && cmake . \
  && make \
  && cp uuid.so /etc/hhvm/ext/uuid.so \
  && printf "hhvm.dynamic_extensions[uuid] = uuid.so\n" >> /etc/hhvm/php.ini
RUN rm ba0ebae0fe.tar.gz && rm -rf hhvm-ext-uuid-ba0ebae0fe123e8545ea02110db2f0102c08d637/
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
uuid/util/run-tests.sh000064400000002362147361033650011002 0ustar00#!/bin/bash
### Run tests based on CPU architecture
#
# Depending on the ARCH indicated for this test job, run the tests in a
# Docker container based on the PHP version for this job.
#

if [ -z "${ARCH}" ]; then
    echo "The ARCH environment variable must be provided"
    exit 1
fi

if [ -z "${PHP_VERSION}" ]; then
    echo "The PHP_VERSION environment variable must be provided"
    exit 1
fi

if [ -z "${TRAVIS_BUILD_DIR}" ]; then
    echo "The TRAVIS_BUILD_DIR environment variable must be provided"
    exit 1
fi

if [ "${PHP_VERSION}" = "hhvm" ]; then
    docker_tag="${ARCH}-trusty-php-${PHP_VERSION}"
else
    docker_tag="${ARCH}-wheezy-php-${PHP_VERSION}"
fi

declare -a commands
commands[0]="echo \"Environment: \$(uname -a)\""
commands[1]="php --version"
commands[2]="cd ${TRAVIS_BUILD_DIR}"
commands[3]="composer install --no-interaction --prefer-dist"
commands[4]="./vendor/bin/parallel-lint src tests"
commands[5]="./vendor/bin/phpcs src tests --standard=psr2 -sp"
commands[6]="./vendor/bin/phpunit --verbose --coverage-clover build/logs/clover.xml"

printf -v command "%s && " "${commands[@]}"
command=${command::-4}

sudo docker run -v "${TRAVIS_BUILD_DIR}":"${TRAVIS_BUILD_DIR}" \
    benramsey/ramsey-uuid:$docker_tag \
    bash -c "${command}"
uuid/util/build-docker-image.sh000064400000012164147361033650012463 0ustar00#!/bin/bash
### Build a Docker image for a target PHP version, CPU arch, and Debian version
#
# Based on: https://github.com/docker-32bit/debian
#
# See also:
# https://www.tomaz.me/2013/12/02/running-travis-ci-tests-on-arm.html
#
# Note: Building HHVM with this script is not supported. See instead:
# https://gist.github.com/ramsey/04cb15ff955d54484980
#
# Recommended approach for running this script to build Docker images:
#
#     vagrant init ubuntu/trusty64
#     vagrant up
#     vagrant ssh
#     sudo apt-get install docker.io
#     sudo docker login
#     cd /vagrant
#     sudo ./util/build-docker-image.sh 5.6.14 mips mips wheezy
#
# or (for 64-bit, standard Debian):
#
#     sudo ./util/build-docker-image.sh 5.6.14 x86_64 amd64 wheezy
#

if [ $EUID -ne 0 ]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

### settings
php_version=${1:-5.6.14}
qemu_arch=${2:-mips}
deb_arch=${3:-mips}
suite=${4:-wheezy}

chroot_dir="/tmp/chroot/${qemu_arch}-${suite}-php-${php_version}"
apt_mirror="http://ftp.us.debian.org/debian"
docker_image="benramsey/ramsey-uuid:${qemu_arch}-${suite}-php-${php_version}"
tmp_package="/tmp/${qemu_arch}-${suite}-php-${php_version}.tgz"
php_package="https://secure.php.net/distributions/php-${php_version}.tar.bz2"


### make sure that the required tools are installed
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y wget debootstrap qemu-user-static binfmt-support \
    docker.io php5-cli php5-curl

### install a minbase system with debootstrap
debootstrap --foreign --arch=$deb_arch $suite $chroot_dir $apt_mirror
cp "/usr/bin/qemu-${qemu_arch}-static" $chroot_dir/usr/bin/
chroot $chroot_dir ./debootstrap/debootstrap --second-stage

### update the list of package sources
cat <<EOF > $chroot_dir/etc/apt/sources.list
deb $apt_mirror $suite main contrib non-free
deb $apt_mirror $suite-updates main contrib non-free
deb http://security.debian.org/ $suite/updates main contrib non-free
EOF

### upgrade packages
chroot $chroot_dir apt-get update -qq
chroot $chroot_dir apt-get upgrade -qq -y

### locale configuration
chroot $chroot_dir apt-get install -qq -y debconf
chroot $chroot_dir bash -c 'echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen'
chroot $chroot_dir dpkg-reconfigure locales

### install dependencies to build PHP
chroot $chroot_dir apt-get --allow-unauthenticated install -qq -y \
    autoconf build-essential libcurl3-openssl-dev libgmp-dev libmcrypt-dev \
    libreadline-dev libxml2-dev uuid-dev curl git

### download, build, and install the PHP version needed for this chroot
mkdir -p $chroot_dir/php-src
cd $chroot_dir/php-src
wget $php_package
tar xf "php-${php_version}.tar.bz2"
chroot $chroot_dir bash -c "cd /php-src/php-${php_version} && ./configure --disable-all --enable-bcmath --with-gmp --disable-cgi --enable-xml --enable-libxml --enable-dom --enable-filter --enable-ctype --enable-json --with-openssl --enable-phar --enable-hash --with-curl --enable-simplexml --enable-tokenizer --enable-xmlwriter --enable-zip"
chroot $chroot_dir bash -c "cd /php-src/php-${php_version} && make && make install"
chroot $chroot_dir cp "/php-src/php-${php_version}/php.ini-development" /usr/local/lib/php.ini
chroot $chroot_dir bash -c 'printf "date.timezone=UTC\n" >> /usr/local/lib/php.ini'

### download, build, and install the PECL UUID extension
wget https://pecl.php.net/get/uuid-1.0.4.tgz
tar zxf uuid-1.0.4.tgz
chroot $chroot_dir bash -c "cd /php-src/uuid-1.0.4 && phpize && ./configure && make && make install"
chroot $chroot_dir bash -c 'printf "extension=uuid.so\n" >> /usr/local/lib/php.ini'


### download, build, and install the PECL libsodium extension
mkdir -p $chroot_dir/libsodium-src
cd $chroot_dir/libsodium-src
wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.8.tar.gz
tar zxf libsodium-1.0.8.tar.gz
chroot $chroot_dir bash -c "cd /libsodium-src/libsodium-1.0.8 && ./configure && make && make install"
cd $chroot_dir/php-src
wget http://pecl.php.net/get/libsodium-1.0.2.tgz
tar zxf libsodium-1.0.2.tgz
chroot $chroot_dir bash -c "cd /php-src/libsodium-1.0.2 && phpize && ./configure && make && make install"
chroot $chroot_dir bash -c 'printf "extension=libsodium.so\n" >> /usr/local/lib/php.ini'


### download, build, and install Xdebug
wget http://xdebug.org/files/xdebug-2.4.0rc3.tgz
tar zxf xdebug-2.4.0rc3.tgz
chroot $chroot_dir bash -c "cd /php-src/xdebug-2.4.0RC3 && phpize && ./configure --enable-xdebug && make && make install"
chroot $chroot_dir bash -c "printf \"zend_extension=\$(php -r \"echo ini_get('extension_dir');\")/xdebug.so\n\" >> /usr/local/lib/php.ini"


### globally install Composer
chroot $chroot_dir bash -c "curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer"

### cleanup
chroot $chroot_dir apt-get autoclean
chroot $chroot_dir apt-get clean
chroot $chroot_dir apt-get autoremove

cd /tmp
rm -rf $chroot_dir/php-src

### create a tar archive from the chroot directory
tar cfz $tmp_package -C $chroot_dir .

### import this tar archive into a docker image:
cat $tmp_package | docker import - $docker_image

### push image to Docker Hub
docker push $docker_image

### cleanup
rm $tmp_package
rm -rf $chroot_dir

echo "Done!"
uuid/CODE_OF_CONDUCT.md000064400000006230147361033650010322 0ustar00# Contributor Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
  address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project maintainer at <ben@benramsey.com>. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
uuid/src/DeprecatedUuidInterface.php000064400000012530147361033650013533 0ustar00<?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;

use DateTimeInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;

/**
 * This interface encapsulates deprecated methods for ramsey/uuid; this
 * interface and its methods will be removed in ramsey/uuid 5.0.0.
 *
 * @psalm-immutable
 */
interface DeprecatedUuidInterface
{
    /**
     * @deprecated This method will be removed in 5.0.0. There is no alternative
     *     recommendation, so plan accordingly.
     */
    public function getNumberConverter(): NumberConverterInterface;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance.
     *
     * @return string[]
     */
    public function getFieldsHex(): array;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()}.
     */
    public function getClockSeqHiAndReservedHex(): string;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()}.
     */
    public function getClockSeqLowHex(): string;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()}.
     */
    public function getClockSequenceHex(): string;

    /**
     * @deprecated In ramsey/uuid version 5.0.0, this will be removed from the
     *     interface. It is available at {@see UuidV1::getDateTime()}.
     */
    public function getDateTime(): DateTimeInterface;

    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct
     *     alternative, but the same information may be obtained by splitting
     *     in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getLeastSignificantBitsHex(): string;

    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct
     *     alternative, but the same information may be obtained by splitting
     *     in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getMostSignificantBitsHex(): string;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()}.
     */
    public function getNodeHex(): string;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()}.
     */
    public function getTimeHiAndVersionHex(): string;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()}.
     */
    public function getTimeLowHex(): string;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()}.
     */
    public function getTimeMidHex(): string;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()}.
     */
    public function getTimestampHex(): string;

    /**
     * @deprecated In ramsey/uuid version 5.0.0, this will be removed from this
     *     interface. It has moved to {@see \Ramsey\Uuid\Rfc4122\UuidInterface::getUrn()}.
     */
    public function getUrn(): string;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
     */
    public function getVariant(): ?int;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
     */
    public function getVersion(): ?int;
}
uuid/src/UuidFactory.php000064400000031234147361033650011263 0ustar00<?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;

use DateTimeInterface;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
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\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;

    /**
     * @var DceSecurityGeneratorInterface
     */
    private $dceSecurityGenerator;

    /**
     * @var NameGeneratorInterface
     */
    private $nameGenerator;

    /**
     * @var NodeProviderInterface
     */
    private $nodeProvider;

    /**
     * @var NumberConverterInterface
     */
    private $numberConverter;

    /**
     * @var RandomGeneratorInterface
     */
    private $randomGenerator;

    /**
     * @var TimeConverterInterface
     */
    private $timeConverter;

    /**
     * @var TimeGeneratorInterface
     */
    private $timeGenerator;

    /**
     * @var UuidBuilderInterface
     */
    private $uuidBuilder;

    /**
     * @var ValidatorInterface
     */
    private $validator;

    /**
     * @param FeatureSet $features A set of available features in the current environment
     */
    public function __construct(?FeatureSet $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 codec used by this factory
     */
    public function getCodec(): CodecInterface
    {
        return $this->codec;
    }

    /**
     * Sets the codec to use for this factory
     *
     * @param CodecInterface $codec A UUID encoder-decoder
     */
    public function setCodec(CodecInterface $codec): void
    {
        $this->codec = $codec;
    }

    /**
     * Returns the name generator used by this factory
     */
    public function getNameGenerator(): NameGeneratorInterface
    {
        return $this->nameGenerator;
    }

    /**
     * Sets the name generator to use for this factory
     *
     * @param NameGeneratorInterface $nameGenerator A generator to generate
     *     binary data, based on a namespace and name
     */
    public function setNameGenerator(NameGeneratorInterface $nameGenerator): void
    {
        $this->nameGenerator = $nameGenerator;
    }

    /**
     * Returns the node provider used by this factory
     */
    public function getNodeProvider(): NodeProviderInterface
    {
        return $this->nodeProvider;
    }

    /**
     * Returns the random generator used by this factory
     */
    public function getRandomGenerator(): RandomGeneratorInterface
    {
        return $this->randomGenerator;
    }

    /**
     * Returns the time generator used by this factory
     */
    public function getTimeGenerator(): TimeGeneratorInterface
    {
        return $this->timeGenerator;
    }

    /**
     * Sets the time generator to use for this factory
     *
     * @param TimeGeneratorInterface $generator A generator to generate binary
     *     data, based on the time
     */
    public function setTimeGenerator(TimeGeneratorInterface $generator): void
    {
        $this->timeGenerator = $generator;
    }

    /**
     * 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
     *
     * @param DceSecurityGeneratorInterface $generator A generator to generate
     *     binary data, based on a local domain and local identifier
     */
    public function setDceSecurityGenerator(DceSecurityGeneratorInterface $generator): void
    {
        $this->dceSecurityGenerator = $generator;
    }

    /**
     * Returns the number converter used by this factory
     */
    public function getNumberConverter(): NumberConverterInterface
    {
        return $this->numberConverter;
    }

    /**
     * Sets the random generator to use for this factory
     *
     * @param RandomGeneratorInterface $generator A generator to generate binary
     *     data, based on some random input
     */
    public function setRandomGenerator(RandomGeneratorInterface $generator): void
    {
        $this->randomGenerator = $generator;
    }

    /**
     * Sets the number converter to use for this factory
     *
     * @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): void
    {
        $this->numberConverter = $converter;
    }

    /**
     * Returns the UUID builder used by this factory
     */
    public function getUuidBuilder(): UuidBuilderInterface
    {
        return $this->uuidBuilder;
    }

    /**
     * Sets the UUID builder to use for this factory
     *
     * @param UuidBuilderInterface $builder A builder for constructing instances
     *     of UuidInterface
     */
    public function setUuidBuilder(UuidBuilderInterface $builder): void
    {
        $this->uuidBuilder = $builder;
    }

    /**
     * @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->validator = $validator;
    }

    /**
     * @psalm-pure
     */
    public function fromBytes(string $bytes): UuidInterface
    {
        return $this->codec->decodeBytes($bytes);
    }

    /**
     * @psalm-pure
     */
    public function fromString(string $uuid): UuidInterface
    {
        $uuid = strtolower($uuid);

        return $this->codec->decode($uuid);
    }

    /**
     * @psalm-pure
     */
    public function fromInteger(string $integer): UuidInterface
    {
        $hex = $this->numberConverter->toHex($integer);
        $hex = str_pad($hex, 32, '0', STR_PAD_LEFT);

        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
     */
    public function uuid1($node = null, ?int $clockSeq = null): UuidInterface
    {
        $bytes = $this->timeGenerator->generate($node, $clockSeq);

        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
     * @psalm-pure
     */
    public function uuid3($ns, string $name): UuidInterface
    {
        return $this->uuidFromNsAndName($ns, $name, 3, 'md5');
    }

    public function uuid4(): UuidInterface
    {
        $bytes = $this->randomGenerator->generate(16);

        return $this->uuidFromBytesAndVersion($bytes, 4);
    }

    /**
     * @inheritDoc
     * @psalm-pure
     */
    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 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
     *
     * @return UuidInterface An instance of UuidInterface, created from the
     *     provided bytes
     *
     * @psalm-pure
     */
    public function uuid(string $bytes): UuidInterface
    {
        return $this->uuidBuilder->build($this->codec, $bytes);
    }

    /**
     * Returns a version 3 or 5 namespaced Uuid
     *
     * @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 $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
     */
    private function uuidFromNsAndName($ns, string $name, int $version, string $hashAlgorithm): UuidInterface
    {
        if (!($ns instanceof UuidInterface)) {
            $ns = $this->fromString($ns);
        }

        $bytes = $this->nameGenerator->generate($ns, $name, $hashAlgorithm);

        return $this->uuidFromBytesAndVersion(substr($bytes, 0, 16), $version);
    }

    /**
     * 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
     *
     * @return UuidInterface An instance of UuidInterface, created from the
     *     byte string and version
     *
     * @psalm-pure
     */
    private function uuidFromBytesAndVersion(string $bytes, int $version): UuidInterface
    {
        $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);

        return $this->uuid($bytes);
    }
}
uuid/src/BinaryUtils.php000064400000003316147361033650011272 0ustar00<?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;

/**
 * Provides binary math utilities
 */
class BinaryUtils
{
    /**
     * Applies the RFC 4122 variant field to the 16-bit clock sequence
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
     *
     * @param int $clockSeq The 16-bit clock sequence value before the RFC 4122
     *     variant is applied
     *
     * @return int The 16-bit clock sequence multiplexed with the UUID variant
     *
     * @psalm-pure
     */
    public static function applyVariant(int $clockSeq): int
    {
        $clockSeq = $clockSeq & 0x3fff;
        $clockSeq |= 0x8000;

        return $clockSeq;
    }

    /**
     * Applies the RFC 4122 version number to the 16-bit `time_hi_and_version` field
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
     *
     * @param int $timeHi The value of the 16-bit `time_hi_and_version` field
     *     before the RFC 4122 version is applied
     * @param int $version The RFC 4122 version to apply to the `time_hi` field
     *
     * @return int The 16-bit time_hi field of the timestamp multiplexed with
     *     the UUID version number
     *
     * @psalm-pure
     */
    public static function applyVersion(int $timeHi, int $version): int
    {
        $timeHi = $timeHi & 0x0fff;
        $timeHi |= $version << 12;

        return $timeHi;
    }
}
uuid/src/Converter/NumberConverterInterface.php000064400000003052147361033650015732 0ustar00<?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\Converter;

/**
 * A number converter converts UUIDs from hexadecimal characters into
 * representations of integers and vice versa
 *
 * @psalm-immutable
 */
interface NumberConverterInterface
{
    /**
     * Converts a hexadecimal number into an string integer representation of
     * the number
     *
     * The integer representation returned is a string representation of the
     * integer, to accommodate unsigned integers greater than PHP_INT_MAX.
     *
     * @param string $hex The hexadecimal string representation to convert
     *
     * @return string String representation of an integer
     *
     * @psalm-return numeric-string
     *
     * @psalm-pure
     */
    public function fromHex(string $hex): string;

    /**
     * Converts a string integer representation into a hexadecimal string
     * representation of the number
     *
     * @param string $number A string integer representation to convert; this
     *     must be a numeric string to accommodate unsigned integers greater
     *     than PHP_INT_MAX.
     *
     * @return string Hexadecimal string
     *
     * @psalm-return non-empty-string
     *
     * @psalm-pure
     */
    public function toHex(string $number): string;
}
uuid/src/Converter/Time/PhpTimeConverter.php000064400000013067147361033650015134 0ustar00<?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\Converter\Time;

use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Math\CalculatorInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Type\Time;

use function count;
use function dechex;
use function explode;
use function is_float;
use function is_int;
use function str_pad;
use function strlen;
use function substr;

use const STR_PAD_LEFT;
use const STR_PAD_RIGHT;

/**
 * PhpTimeConverter uses built-in PHP functions and standard math operations
 * available to the PHP programming language to provide facilities for
 * converting parts of time into representations that may be used in UUIDs
 *
 * @psalm-immutable
 */
class PhpTimeConverter implements TimeConverterInterface
{
    /**
     * The number of 100-nanosecond intervals from the Gregorian calendar epoch
     * to the Unix epoch.
     */
    private const GREGORIAN_TO_UNIX_INTERVALS = 0x01b21dd213814000;

    /**
     * The number of 100-nanosecond intervals in one second.
     */
    private const SECOND_INTERVALS = 10000000;

    /**
     * The number of 100-nanosecond intervals in one microsecond.
     */
    private const MICROSECOND_INTERVALS = 10;

    /**
     * @var CalculatorInterface
     */
    private $calculator;

    /**
     * @var TimeConverterInterface
     */
    private $fallbackConverter;

    /**
     * @var int
     */
    private $phpPrecision;

    public function __construct(
        ?CalculatorInterface $calculator = null,
        ?TimeConverterInterface $fallbackConverter = null
    ) {
        if ($calculator === null) {
            $calculator = new BrickMathCalculator();
        }

        if ($fallbackConverter === null) {
            $fallbackConverter = new GenericTimeConverter($calculator);
        }

        $this->calculator = $calculator;
        $this->fallbackConverter = $fallbackConverter;
        $this->phpPrecision = (int) ini_get('precision');
    }

    public function calculateTime(string $seconds, string $microseconds): Hexadecimal
    {
        $seconds = new IntegerObject($seconds);
        $microseconds = new IntegerObject($microseconds);

        // Calculate the count of 100-nanosecond intervals since the Gregorian
        // calendar epoch for the given seconds and microseconds.
        $uuidTime = ((int) $seconds->toString() * self::SECOND_INTERVALS)
            + ((int) $microseconds->toString() * self::MICROSECOND_INTERVALS)
            + self::GREGORIAN_TO_UNIX_INTERVALS;

        // Check to see whether we've overflowed the max/min integer size.
        // If so, we will default to a different time converter.
        /** @psalm-suppress RedundantCondition */
        if (!is_int($uuidTime)) {
            return $this->fallbackConverter->calculateTime(
                $seconds->toString(),
                $microseconds->toString()
            );
        }

        return new Hexadecimal(str_pad(dechex((int) $uuidTime), 16, '0', STR_PAD_LEFT));
    }

    public function convertTime(Hexadecimal $uuidTimestamp): Time
    {
        $timestamp = $this->calculator->toInteger($uuidTimestamp);

        // Convert the 100-nanosecond intervals into seconds and microseconds.
        $splitTime = $this->splitTime(
            ((int) $timestamp->toString() - self::GREGORIAN_TO_UNIX_INTERVALS)
            / self::SECOND_INTERVALS
        );

        if (count($splitTime) === 0) {
            return $this->fallbackConverter->convertTime($uuidTimestamp);
        }

        return new Time($splitTime['sec'], $splitTime['usec']);
    }

    /**
     * @param int|float $time The time to split into seconds and microseconds
     *
     * @return string[]
     */
    private function splitTime($time): array
    {
        $split = explode('.', (string) $time, 2);

        // If the $time value is a float but $split only has 1 element, then the
        // float math was rounded up to the next second, so we want to return
        // an empty array to allow use of the fallback converter.
        if (is_float($time) && count($split) === 1) {
            return [];
        }

        if (count($split) === 1) {
            return [
                'sec' => $split[0],
                'usec' => '0',
            ];
        }

        // If the microseconds are less than six characters AND the length of
        // the number is greater than or equal to the PHP precision, then it's
        // possible that we lost some precision for the microseconds. Return an
        // empty array, so that we can choose to use the fallback converter.
        if (strlen($split[1]) < 6 && strlen((string) $time) >= $this->phpPrecision) {
            return [];
        }

        $microseconds = $split[1];

        // Ensure the microseconds are no longer than 6 digits. If they are,
        // truncate the number to the first 6 digits and round up, if needed.
        if (strlen($microseconds) > 6) {
            $roundingDigit = (int) substr($microseconds, 6, 1);
            $microseconds = (int) substr($microseconds, 0, 6);

            if ($roundingDigit >= 5) {
                $microseconds++;
            }
        }

        return [
            'sec' => $split[0],
            'usec' => str_pad((string) $microseconds, 6, '0', STR_PAD_RIGHT),
        ];
    }
}
uuid/src/Converter/Time/GenericTimeConverter.php000064400000007342147361033650015760 0ustar00<?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\Converter\Time;

use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Math\CalculatorInterface;
use Ramsey\Uuid\Math\RoundingMode;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Type\Time;

use function explode;
use function str_pad;

use const STR_PAD_LEFT;

/**
 * GenericTimeConverter uses the provided calculator to calculate and convert
 * time values
 *
 * @psalm-immutable
 */
class GenericTimeConverter implements TimeConverterInterface
{
    /**
     * The number of 100-nanosecond intervals from the Gregorian calendar epoch
     * to the Unix epoch.
     */
    private const GREGORIAN_TO_UNIX_INTERVALS = '122192928000000000';

    /**
     * The number of 100-nanosecond intervals in one second.
     */
    private const SECOND_INTERVALS = '10000000';

    /**
     * The number of 100-nanosecond intervals in one microsecond.
     */
    private const MICROSECOND_INTERVALS = '10';

    /**
     * @var CalculatorInterface
     */
    private $calculator;

    public function __construct(CalculatorInterface $calculator)
    {
        $this->calculator = $calculator;
    }

    public function calculateTime(string $seconds, string $microseconds): Hexadecimal
    {
        $timestamp = new Time($seconds, $microseconds);

        // Convert the seconds into a count of 100-nanosecond intervals.
        $sec = $this->calculator->multiply(
            $timestamp->getSeconds(),
            new IntegerObject(self::SECOND_INTERVALS)
        );

        // Convert the microseconds into a count of 100-nanosecond intervals.
        $usec = $this->calculator->multiply(
            $timestamp->getMicroseconds(),
            new IntegerObject(self::MICROSECOND_INTERVALS)
        );

        // Combine the seconds and microseconds intervals and add the count of
        // 100-nanosecond intervals from the Gregorian calendar epoch to the
        // Unix epoch. This gives us the correct count of 100-nanosecond
        // intervals since the Gregorian calendar epoch for the given seconds
        // and microseconds.
        /** @var IntegerObject $uuidTime */
        $uuidTime = $this->calculator->add(
            $sec,
            $usec,
            new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS)
        );

        $uuidTimeHex = str_pad(
            $this->calculator->toHexadecimal($uuidTime)->toString(),
            16,
            '0',
            STR_PAD_LEFT
        );

        return new Hexadecimal($uuidTimeHex);
    }

    public function convertTime(Hexadecimal $uuidTimestamp): Time
    {
        // From the total, subtract the number of 100-nanosecond intervals from
        // the Gregorian calendar epoch to the Unix epoch. This gives us the
        // number of 100-nanosecond intervals from the Unix epoch, which also
        // includes the microtime.
        $epochNanoseconds = $this->calculator->subtract(
            $this->calculator->toInteger($uuidTimestamp),
            new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS)
        );

        // Convert the 100-nanosecond intervals into seconds and microseconds.
        $unixTimestamp = $this->calculator->divide(
            RoundingMode::HALF_UP,
            6,
            $epochNanoseconds,
            new IntegerObject(self::SECOND_INTERVALS)
        );

        $split = explode('.', (string) $unixTimestamp, 2);

        return new Time($split[0], $split[1] ?? 0);
    }
}
uuid/src/Converter/Time/BigNumberTimeConverter.php000064400000002510147361033650016246 0ustar00<?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\Converter\Time;

use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Time;

/**
 * Previously used to integrate moontoast/math as a bignum arithmetic library,
 * BigNumberTimeConverter is deprecated in favor of GenericTimeConverter
 *
 * @deprecated Transition to {@see GenericTimeConverter}.
 *
 * @psalm-immutable
 */
class BigNumberTimeConverter implements TimeConverterInterface
{
    /**
     * @var TimeConverterInterface
     */
    private $converter;

    public function __construct()
    {
        $this->converter = new GenericTimeConverter(new BrickMathCalculator());
    }

    public function calculateTime(string $seconds, string $microseconds): Hexadecimal
    {
        return $this->converter->calculateTime($seconds, $microseconds);
    }

    public function convertTime(Hexadecimal $uuidTimestamp): Time
    {
        return $this->converter->convertTime($uuidTimestamp);
    }
}
uuid/src/Converter/Time/DegradedTimeConverter.php000064400000001147147361033650016100 0ustar00<?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\Converter\Time;

/**
 * @deprecated DegradedTimeConverter is no longer necessary for converting
 *     time on 32-bit systems. Transition to {@see GenericTimeConverter}.
 *
 * @psalm-immutable
 */
class DegradedTimeConverter extends BigNumberTimeConverter
{
}
uuid/src/Converter/TimeConverterInterface.php000064400000003423147361033650015402 0ustar00<?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\Converter;

use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Time;

/**
 * A time converter converts timestamps into representations that may be used
 * in UUIDs
 *
 * @psalm-immutable
 */
interface TimeConverterInterface
{
    /**
     * Uses the provided seconds and micro-seconds to calculate the count of
     * 100-nanosecond intervals since UTC 00:00:00.00, 15 October 1582, for
     * RFC 4122 variant UUIDs
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.2.2 RFC 4122, § 4.2.2: Generation Details
     *
     * @param string $seconds A string representation of the number of seconds
     *     since the Unix epoch for the time to calculate
     * @param string $microseconds A string representation of the micro-seconds
     *     associated with the time to calculate
     *
     * @return Hexadecimal The full UUID timestamp as a Hexadecimal value
     *
     * @psalm-pure
     */
    public function calculateTime(string $seconds, string $microseconds): Hexadecimal;

    /**
     * Converts a timestamp extracted from a UUID to a Unix timestamp
     *
     * @param Hexadecimal $uuidTimestamp A hexadecimal representation of a UUID
     *     timestamp; a UUID timestamp is a count of 100-nanosecond intervals
     *     since UTC 00:00:00.00, 15 October 1582.
     *
     * @return Time An instance of {@see Time}
     *
     * @psalm-pure
     */
    public function convertTime(Hexadecimal $uuidTimestamp): Time;
}
uuid/src/Converter/Number/BigNumberConverter.php000064400000002442147361033650015765 0ustar00<?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\Converter\Number;

use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Math\BrickMathCalculator;

/**
 * Previously used to integrate moontoast/math as a bignum arithmetic library,
 * BigNumberConverter is deprecated in favor of GenericNumberConverter
 *
 * @deprecated Transition to {@see GenericNumberConverter}.
 *
 * @psalm-immutable
 */
class BigNumberConverter implements NumberConverterInterface
{
    /**
     * @var NumberConverterInterface
     */
    private $converter;

    public function __construct()
    {
        $this->converter = new GenericNumberConverter(new BrickMathCalculator());
    }

    /**
     * @inheritDoc
     * @psalm-pure
     */
    public function fromHex(string $hex): string
    {
        return $this->converter->fromHex($hex);
    }

    /**
     * @inheritDoc
     * @psalm-pure
     */
    public function toHex(string $number): string
    {
        return $this->converter->toHex($number);
    }
}
uuid/src/Converter/Number/DegradedNumberConverter.php000064400000001156147361033650016764 0ustar00<?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\Converter\Number;

/**
 * @deprecated DegradedNumberConverter is no longer necessary for converting
 *     numbers on 32-bit systems. Transition to {@see GenericNumberConverter}.
 *
 * @psalm-immutable
 */
class DegradedNumberConverter extends BigNumberConverter
{
}
uuid/src/Converter/Number/GenericNumberConverter.php000064400000003350147361033650016637 0ustar00<?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\Converter\Number;

use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Math\CalculatorInterface;
use Ramsey\Uuid\Type\Integer as IntegerObject;

/**
 * GenericNumberConverter uses the provided calculate to convert decimal
 * numbers to and from hexadecimal values
 *
 * @psalm-immutable
 */
class GenericNumberConverter implements NumberConverterInterface
{
    /**
     * @var CalculatorInterface
     */
    private $calculator;

    public function __construct(CalculatorInterface $calculator)
    {
        $this->calculator = $calculator;
    }

    /**
     * @inheritDoc
     * @psalm-pure
     * @psalm-return numeric-string
     * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
     * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
     */
    public function fromHex(string $hex): string
    {
        return $this->calculator->fromBase($hex, 16)->toString();
    }

    /**
     * @inheritDoc
     * @psalm-pure
     * @psalm-return non-empty-string
     * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
     * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
     */
    public function toHex(string $number): string
    {
        return $this->calculator->toBase(new IntegerObject($number), 16);
    }
}
uuid/src/Builder/UuidBuilderInterface.php000064400000002017147361033650014446 0ustar00<?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\Builder;

use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\UuidInterface;

/**
 * A UUID builder builds instances of UuidInterface
 *
 * @psalm-immutable
 */
interface UuidBuilderInterface
{
    /**
     * Builds and returns a UuidInterface
     *
     * @param CodecInterface $codec The codec to use for building this UuidInterface instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return UuidInterface Implementations may choose to return more specific
     *     instances of UUIDs that implement UuidInterface
     *
     * @psalm-pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface;
}
uuid/src/Builder/DefaultUuidBuilder.php000064400000001130147361033650014125 0ustar00<?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\Builder;

use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;

/**
 * @deprecated Transition to {@see Rfc4122UuidBuilder}.
 *
 * @psalm-immutable
 */
class DefaultUuidBuilder extends Rfc4122UuidBuilder implements UuidBuilderInterface
{
}
uuid/src/Builder/FallbackBuilder.php000064400000003776147361033650013433 0ustar00<?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\Builder;

use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Exception\BuilderNotFoundException;
use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\UuidInterface;

/**
 * FallbackBuilder builds a UUID by stepping through a list of UUID builders
 * until a UUID can be constructed without exceptions
 *
 * @psalm-immutable
 */
class FallbackBuilder implements UuidBuilderInterface
{
    /**
     * @var BuilderCollection
     */
    private $builders;

    /**
     * @param BuilderCollection $builders An array of UUID builders
     */
    public function __construct(BuilderCollection $builders)
    {
        $this->builders = $builders;
    }

    /**
     * Builds and returns a UuidInterface instance using the first builder that
     * succeeds
     *
     * @param CodecInterface $codec The codec to use for building this instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return UuidInterface an instance of a UUID object
     *
     * @psalm-pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        $lastBuilderException = null;

        /** @var UuidBuilderInterface $builder */
        foreach ($this->builders as $builder) {
            try {
                return $builder->build($codec, $bytes);
            } catch (UnableToBuildUuidException $exception) {
                $lastBuilderException = $exception;

                continue;
            }
        }

        throw new BuilderNotFoundException(
            'Could not find a suitable builder for the provided codec and fields',
            0,
            $lastBuilderException
        );
    }
}
uuid/src/Builder/DegradedUuidBuilder.php000064400000004347147361033650014255 0ustar00<?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\Builder;

use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\Time\DegradedTimeConverter;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\DegradedUuid;
use Ramsey\Uuid\Rfc4122\Fields as Rfc4122Fields;
use Ramsey\Uuid\UuidInterface;

/**
 * @deprecated DegradedUuid instances are no longer necessary to support 32-bit
 *     systems. Transition to {@see DefaultUuidBuilder}.
 *
 * @psalm-immutable
 */
class DegradedUuidBuilder implements UuidBuilderInterface
{
    /**
     * @var NumberConverterInterface
     */
    private $numberConverter;

    /**
     * @var TimeConverterInterface
     */
    private $timeConverter;

    /**
     * @param NumberConverterInterface $numberConverter The number converter to
     *     use when constructing the DegradedUuid
     * @param TimeConverterInterface|null $timeConverter The time converter to use
     *     for converting timestamps extracted from a UUID to Unix timestamps
     */
    public function __construct(
        NumberConverterInterface $numberConverter,
        ?TimeConverterInterface $timeConverter = null
    ) {
        $this->numberConverter = $numberConverter;
        $this->timeConverter = $timeConverter ?: new DegradedTimeConverter();
    }

    /**
     * Builds and returns a DegradedUuid
     *
     * @param CodecInterface $codec The codec to use for building this DegradedUuid instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return DegradedUuid The DegradedUuidBuild returns an instance of Ramsey\Uuid\DegradedUuid
     *
     * @psalm-pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        return new DegradedUuid(
            new Rfc4122Fields($bytes),
            $this->numberConverter,
            $codec,
            $this->timeConverter
        );
    }
}
uuid/src/Builder/BuilderCollection.php000064400000004114147361033650014012 0ustar00<?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\Builder;

use Ramsey\Collection\AbstractCollection;
use Ramsey\Collection\CollectionInterface;
use Ramsey\Uuid\Converter\Number\GenericNumberConverter;
use Ramsey\Uuid\Converter\Time\GenericTimeConverter;
use Ramsey\Uuid\Converter\Time\PhpTimeConverter;
use Ramsey\Uuid\Guid\GuidBuilder;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
use Traversable;

/**
 * A collection of UuidBuilderInterface objects
 */
class BuilderCollection extends AbstractCollection implements CollectionInterface
{
    public function getType(): string
    {
        return UuidBuilderInterface::class;
    }

    /**
     * @psalm-mutation-free
     * @psalm-suppress ImpureMethodCall
     * @psalm-suppress InvalidTemplateParam
     */
    public function getIterator(): Traversable
    {
        return parent::getIterator();
    }

    /**
     * Re-constructs the object from its serialized form
     *
     * @param string $serialized The serialized PHP string to unserialize into
     *     a UuidInterface instance
     *
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     */
    public function unserialize($serialized): void
    {
        /** @var mixed[] $data */
        $data = unserialize($serialized, [
            'allowed_classes' => [
                BrickMathCalculator::class,
                GenericNumberConverter::class,
                GenericTimeConverter::class,
                GuidBuilder::class,
                NonstandardUuidBuilder::class,
                PhpTimeConverter::class,
                Rfc4122UuidBuilder::class,
            ],
        ]);

        $this->data = $data;
    }
}
uuid/src/FeatureSet.php000064400000030720147361033650011073 0ustar00<?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;

use Ramsey\Uuid\Builder\BuilderCollection;
use Ramsey\Uuid\Builder\FallbackBuilder;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Codec\GuidStringCodec;
use Ramsey\Uuid\Codec\StringCodec;
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\TimeConverterInterface;
use Ramsey\Uuid\Generator\DceSecurityGenerator;
use Ramsey\Uuid\Generator\DceSecurityGeneratorInterface;
use Ramsey\Uuid\Generator\NameGeneratorFactory;
use Ramsey\Uuid\Generator\NameGeneratorInterface;
use Ramsey\Uuid\Generator\PeclUuidNameGenerator;
use Ramsey\Uuid\Generator\PeclUuidRandomGenerator;
use Ramsey\Uuid\Generator\PeclUuidTimeGenerator;
use Ramsey\Uuid\Generator\RandomGeneratorFactory;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Generator\TimeGeneratorFactory;
use Ramsey\Uuid\Generator\TimeGeneratorInterface;
use Ramsey\Uuid\Guid\GuidBuilder;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Math\CalculatorInterface;
use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
use Ramsey\Uuid\Provider\Dce\SystemDceSecurityProvider;
use Ramsey\Uuid\Provider\DceSecurityProviderInterface;
use Ramsey\Uuid\Provider\Node\FallbackNodeProvider;
use Ramsey\Uuid\Provider\Node\NodeProviderCollection;
use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
use Ramsey\Uuid\Provider\Node\SystemNodeProvider;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Provider\Time\SystemTimeProvider;
use Ramsey\Uuid\Provider\TimeProviderInterface;
use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
use Ramsey\Uuid\Validator\GenericValidator;
use Ramsey\Uuid\Validator\ValidatorInterface;

use const PHP_INT_SIZE;

/**
 * FeatureSet detects and exposes available features in the current environment
 *
 * A feature set is used by UuidFactory to determine the available features and
 * capabilities of the environment.
 */
class FeatureSet
{
    /**
     * @var bool
     */
    private $disableBigNumber = false;

    /**
     * @var bool
     */
    private $disable64Bit = false;

    /**
     * @var bool
     */
    private $ignoreSystemNode = false;

    /**
     * @var bool
     */
    private $enablePecl = false;

    /**
     * @var UuidBuilderInterface
     */
    private $builder;

    /**
     * @var CodecInterface
     */
    private $codec;

    /**
     * @var DceSecurityGeneratorInterface
     */
    private $dceSecurityGenerator;

    /**
     * @var NameGeneratorInterface
     */
    private $nameGenerator;

    /**
     * @var NodeProviderInterface
     */
    private $nodeProvider;

    /**
     * @var NumberConverterInterface
     */
    private $numberConverter;

    /**
     * @var TimeConverterInterface
     */
    private $timeConverter;

    /**
     * @var RandomGeneratorInterface
     */
    private $randomGenerator;

    /**
     * @var TimeGeneratorInterface
     */
    private $timeGenerator;

    /**
     * @var TimeProviderInterface
     */
    private $timeProvider;

    /**
     * @var ValidatorInterface
     */
    private $validator;

    /**
     * @var CalculatorInterface
     */
    private $calculator;

    /**
     * @param bool $useGuids True build UUIDs using the GuidStringCodec
     * @param bool $force32Bit True to force the use of 32-bit functionality
     *     (primarily for testing purposes)
     * @param bool $forceNoBigNumber True to disable the use of moontoast/math
     *     (primarily for testing purposes)
     * @param bool $ignoreSystemNode True to disable attempts to check for the
     *     system node ID (primarily for testing purposes)
     * @param bool $enablePecl True to enable the use of the PeclUuidTimeGenerator
     *     to generate version 1 UUIDs
     */
    public function __construct(
        bool $useGuids = false,
        bool $force32Bit = false,
        bool $forceNoBigNumber = false,
        bool $ignoreSystemNode = false,
        bool $enablePecl = false
    ) {
        $this->disableBigNumber = $forceNoBigNumber;
        $this->disable64Bit = $force32Bit;
        $this->ignoreSystemNode = $ignoreSystemNode;
        $this->enablePecl = $enablePecl;

        $this->setCalculator(new BrickMathCalculator());
        $this->builder = $this->buildUuidBuilder($useGuids);
        $this->codec = $this->buildCodec($useGuids);
        $this->nodeProvider = $this->buildNodeProvider();
        $this->nameGenerator = $this->buildNameGenerator();
        $this->randomGenerator = $this->buildRandomGenerator();
        $this->setTimeProvider(new SystemTimeProvider());
        $this->setDceSecurityProvider(new SystemDceSecurityProvider());
        $this->validator = new GenericValidator();
    }

    /**
     * Returns the builder configured for this environment
     */
    public function getBuilder(): UuidBuilderInterface
    {
        return $this->builder;
    }

    /**
     * Returns the calculator configured for this environment
     */
    public function getCalculator(): CalculatorInterface
    {
        return $this->calculator;
    }

    /**
     * Returns the codec configured for this environment
     */
    public function getCodec(): CodecInterface
    {
        return $this->codec;
    }

    /**
     * Returns the DCE Security generator configured for this environment
     */
    public function getDceSecurityGenerator(): DceSecurityGeneratorInterface
    {
        return $this->dceSecurityGenerator;
    }

    /**
     * Returns the name generator configured for this environment
     */
    public function getNameGenerator(): NameGeneratorInterface
    {
        return $this->nameGenerator;
    }

    /**
     * Returns the node provider configured for this environment
     */
    public function getNodeProvider(): NodeProviderInterface
    {
        return $this->nodeProvider;
    }

    /**
     * Returns the number converter configured for this environment
     */
    public function getNumberConverter(): NumberConverterInterface
    {
        return $this->numberConverter;
    }

    /**
     * Returns the random generator configured for this environment
     */
    public function getRandomGenerator(): RandomGeneratorInterface
    {
        return $this->randomGenerator;
    }

    /**
     * Returns the time converter configured for this environment
     */
    public function getTimeConverter(): TimeConverterInterface
    {
        return $this->timeConverter;
    }

    /**
     * Returns the time generator configured for this environment
     */
    public function getTimeGenerator(): TimeGeneratorInterface
    {
        return $this->timeGenerator;
    }

    /**
     * Returns the validator configured for this environment
     */
    public function getValidator(): ValidatorInterface
    {
        return $this->validator;
    }

    /**
     * Sets the calculator to use in this environment
     */
    public function setCalculator(CalculatorInterface $calculator): void
    {
        $this->calculator = $calculator;
        $this->numberConverter = $this->buildNumberConverter($calculator);
        $this->timeConverter = $this->buildTimeConverter($calculator);

        if (isset($this->timeProvider)) {
            $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
        }
    }

    /**
     * Sets the DCE Security provider to use in this environment
     */
    public function setDceSecurityProvider(DceSecurityProviderInterface $dceSecurityProvider): void
    {
        $this->dceSecurityGenerator = $this->buildDceSecurityGenerator($dceSecurityProvider);
    }

    /**
     * Sets the node provider to use in this environment
     */
    public function setNodeProvider(NodeProviderInterface $nodeProvider): void
    {
        $this->nodeProvider = $nodeProvider;
        $this->timeGenerator = $this->buildTimeGenerator($this->timeProvider);
    }

    /**
     * Sets the time provider to use in this environment
     */
    public function setTimeProvider(TimeProviderInterface $timeProvider): void
    {
        $this->timeProvider = $timeProvider;
        $this->timeGenerator = $this->buildTimeGenerator($timeProvider);
    }

    /**
     * Set the validator to use in this environment
     */
    public function setValidator(ValidatorInterface $validator): void
    {
        $this->validator = $validator;
    }

    /**
     * Returns a codec configured for this environment
     *
     * @param bool $useGuids Whether to build UUIDs using the GuidStringCodec
     */
    private function buildCodec(bool $useGuids = false): CodecInterface
    {
        if ($useGuids) {
            return new GuidStringCodec($this->builder);
        }

        return new StringCodec($this->builder);
    }

    /**
     * Returns a DCE Security generator configured for this environment
     */
    private function buildDceSecurityGenerator(
        DceSecurityProviderInterface $dceSecurityProvider
    ): DceSecurityGeneratorInterface {
        return new DceSecurityGenerator(
            $this->numberConverter,
            $this->timeGenerator,
            $dceSecurityProvider
        );
    }

    /**
     * Returns a node provider configured for this environment
     */
    private function buildNodeProvider(): NodeProviderInterface
    {
        if ($this->ignoreSystemNode) {
            return new RandomNodeProvider();
        }

        return new FallbackNodeProvider(new NodeProviderCollection([
            new SystemNodeProvider(),
            new RandomNodeProvider(),
        ]));
    }

    /**
     * Returns a number converter configured for this environment
     */
    private function buildNumberConverter(CalculatorInterface $calculator): NumberConverterInterface
    {
        return new GenericNumberConverter($calculator);
    }

    /**
     * Returns a random generator configured for this environment
     */
    private function buildRandomGenerator(): RandomGeneratorInterface
    {
        if ($this->enablePecl) {
            return new PeclUuidRandomGenerator();
        }

        return (new RandomGeneratorFactory())->getGenerator();
    }

    /**
     * Returns a time generator configured for this environment
     *
     * @param TimeProviderInterface $timeProvider The time provider to use with
     *     the time generator
     */
    private function buildTimeGenerator(TimeProviderInterface $timeProvider): TimeGeneratorInterface
    {
        if ($this->enablePecl) {
            return new PeclUuidTimeGenerator();
        }

        return (new TimeGeneratorFactory(
            $this->nodeProvider,
            $this->timeConverter,
            $timeProvider
        ))->getGenerator();
    }

    /**
     * Returns a name generator configured for this environment
     */
    private function buildNameGenerator(): NameGeneratorInterface
    {
        if ($this->enablePecl) {
            return new PeclUuidNameGenerator();
        }

        return (new NameGeneratorFactory())->getGenerator();
    }

    /**
     * Returns a time converter configured for this environment
     */
    private function buildTimeConverter(CalculatorInterface $calculator): TimeConverterInterface
    {
        $genericConverter = new GenericTimeConverter($calculator);

        if ($this->is64BitSystem()) {
            return new PhpTimeConverter($calculator, $genericConverter);
        }

        return $genericConverter;
    }

    /**
     * Returns a UUID builder configured for this environment
     *
     * @param bool $useGuids Whether to build UUIDs using the GuidStringCodec
     */
    private function buildUuidBuilder(bool $useGuids = false): UuidBuilderInterface
    {
        if ($useGuids) {
            return new GuidBuilder($this->numberConverter, $this->timeConverter);
        }

        /** @psalm-suppress ImpureArgument */
        return new FallbackBuilder(new BuilderCollection([
            new Rfc4122UuidBuilder($this->numberConverter, $this->timeConverter),
            new NonstandardUuidBuilder($this->numberConverter, $this->timeConverter),
        ]));
    }

    /**
     * Returns true if the PHP build is 64-bit
     */
    private function is64BitSystem(): bool
    {
        return PHP_INT_SIZE === 8 && !$this->disable64Bit;
    }
}
uuid/src/UuidInterface.php000064400000005243147361033650011555 0ustar00<?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;

use JsonSerializable;
use Ramsey\Uuid\Fields\FieldsInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Serializable;

/**
 * A UUID is a universally unique identifier adhering to an agreed-upon
 * representation format and standard for generation
 *
 * @psalm-immutable
 */
interface UuidInterface extends
    DeprecatedUuidInterface,
    JsonSerializable,
    Serializable
{
    /**
     * Returns -1, 0, or 1 if the UUID is less than, equal to, or greater than
     * the other UUID
     *
     * The first of two UUIDs is greater than the second if the most
     * significant field in which the UUIDs differ is greater for the first
     * UUID.
     *
     * * Q. What's the value of being able to sort UUIDs?
     * * A. Use them as keys in a B-Tree or similar mapping.
     *
     * @param UuidInterface $other The UUID to compare
     *
     * @return int -1, 0, or 1 if the UUID is less than, equal to, or greater than $other
     */
    public function compareTo(UuidInterface $other): int;

    /**
     * Returns true if the UUID is equal to the provided object
     *
     * The result is true if and only if the argument is not null, is a UUID
     * object, has the same variant, and contains the same value, bit for bit,
     * as the UUID.
     *
     * @param object|null $other An object to test for equality with this UUID
     *
     * @return bool True if the other object is equal to this UUID
     */
    public function equals(?object $other): bool;

    /**
     * Returns the binary string representation of the UUID
     *
     * @psalm-return non-empty-string
     */
    public function getBytes(): string;

    /**
     * Returns the fields that comprise this UUID
     */
    public function getFields(): FieldsInterface;

    /**
     * Returns the hexadecimal representation of the UUID
     */
    public function getHex(): Hexadecimal;

    /**
     * Returns the integer representation of the UUID
     */
    public function getInteger(): IntegerObject;

    /**
     * Returns the string standard representation of the UUID
     *
     * @psalm-return non-empty-string
     */
    public function toString(): string;

    /**
     * Casts the UUID to the string standard representation
     *
     * @psalm-return non-empty-string
     */
    public function __toString(): string;
}
uuid/src/DegradedUuid.php000064400000001066147361033650011353 0ustar00<?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;

/**
 * @deprecated DegradedUuid is no longer necessary to represent UUIDs on 32-bit
 *     systems. Transition typehints to {@see UuidInterface}.
 *
 * @psalm-immutable
 */
class DegradedUuid extends Uuid
{
}
uuid/src/Provider/Node/StaticNodeProvider.php000064400000003564147361033650015261 0ustar00<?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\Provider\Node;

use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;

use function dechex;
use function hexdec;
use function str_pad;
use function substr;

use const STR_PAD_LEFT;

/**
 * StaticNodeProvider provides a static node value with the multicast bit set
 *
 * @link http://tools.ietf.org/html/rfc4122#section-4.5 RFC 4122, § 4.5: Node IDs that Do Not Identify the Host
 */
class StaticNodeProvider implements NodeProviderInterface
{
    /**
     * @var Hexadecimal
     */
    private $node;

    /**
     * @param Hexadecimal $node The static node value to use
     */
    public function __construct(Hexadecimal $node)
    {
        if (strlen($node->toString()) > 12) {
            throw new InvalidArgumentException(
                'Static node value cannot be greater than 12 hexadecimal characters'
            );
        }

        $this->node = $this->setMulticastBit($node);
    }

    public function getNode(): Hexadecimal
    {
        return $this->node;
    }

    /**
     * Set the multicast bit for the static node value
     */
    private function setMulticastBit(Hexadecimal $node): Hexadecimal
    {
        $nodeHex = str_pad($node->toString(), 12, '0', STR_PAD_LEFT);
        $firstOctet = substr($nodeHex, 0, 2);

        $firstOctet = str_pad(
            dechex(hexdec($firstOctet) | 0x01),
            2,
            '0',
            STR_PAD_LEFT
        );

        return new Hexadecimal($firstOctet . substr($nodeHex, 2));
    }
}
uuid/src/Provider/Node/RandomNodeProvider.php000064400000003411147361033650015241 0ustar00<?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\Provider\Node;

use Ramsey\Uuid\Exception\RandomSourceException;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;

use function bin2hex;
use function dechex;
use function hex2bin;
use function hexdec;
use function str_pad;
use function substr;

use const STR_PAD_LEFT;

/**
 * RandomNodeProvider generates a random node ID
 *
 * @link http://tools.ietf.org/html/rfc4122#section-4.5 RFC 4122, § 4.5: Node IDs that Do Not Identify the Host
 */
class RandomNodeProvider implements NodeProviderInterface
{
    public function getNode(): Hexadecimal
    {
        try {
            $nodeBytes = random_bytes(6);
        } catch (\Throwable $exception) {
            throw new RandomSourceException(
                $exception->getMessage(),
                (int) $exception->getCode(),
                $exception
            );
        }

        // Split the node bytes for math on 32-bit systems.
        $nodeMsb = substr($nodeBytes, 0, 3);
        $nodeLsb = substr($nodeBytes, 3);

        // Set the multicast bit; see RFC 4122, section 4.5.
        $nodeMsb = hex2bin(
            str_pad(
                dechex(hexdec(bin2hex($nodeMsb)) | 0x010000),
                6,
                '0',
                STR_PAD_LEFT
            )
        );

        // Recombine the node bytes.
        $node = $nodeMsb . $nodeLsb;

        return new Hexadecimal(str_pad(bin2hex($node), 12, '0', STR_PAD_LEFT));
    }
}
uuid/src/Provider/Node/SystemNodeProvider.php000064400000010544147361033650015312 0ustar00<?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\Provider\Node;

use Ramsey\Uuid\Exception\NodeException;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;

use function array_filter;
use function array_map;
use function array_walk;
use function count;
use function ob_get_clean;
use function ob_start;
use function preg_match;
use function preg_match_all;
use function reset;
use function str_replace;
use function strpos;
use function strtolower;
use function strtoupper;
use function substr;

use const GLOB_NOSORT;
use const PREG_PATTERN_ORDER;

/**
 * SystemNodeProvider retrieves the system node ID, if possible
 *
 * The system node ID, or host ID, is often the same as the MAC address for a
 * network interface on the host.
 */
class SystemNodeProvider implements NodeProviderInterface
{
    /**
     * Pattern to match nodes in ifconfig and ipconfig output.
     */
    private const IFCONFIG_PATTERN = '/[^:]([0-9a-f]{2}([:-])[0-9a-f]{2}(\2[0-9a-f]{2}){4})[^:]/i';

    /**
     * Pattern to match nodes in sysfs stream output.
     */
    private const SYSFS_PATTERN = '/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i';

    public function getNode(): Hexadecimal
    {
        $node = $this->getNodeFromSystem();

        if ($node === '') {
            throw new NodeException(
                'Unable to fetch a node for this system'
            );
        }

        return new Hexadecimal($node);
    }

    /**
     * Returns the system node, if it can find it
     */
    protected function getNodeFromSystem(): string
    {
        static $node = null;

        if ($node !== null) {
            return (string) $node;
        }

        // First, try a Linux-specific approach.
        $node = $this->getSysfs();

        if ($node === '') {
            // Search ifconfig output for MAC addresses & return the first one.
            $node = $this->getIfconfig();
        }

        $node = str_replace([':', '-'], '', $node);

        return $node;
    }

    /**
     * Returns the network interface configuration for the system
     *
     * @codeCoverageIgnore
     */
    protected function getIfconfig(): string
    {
        $disabledFunctions = strtolower((string) ini_get('disable_functions'));

        if (strpos($disabledFunctions, 'passthru') !== false) {
            return '';
        }

        ob_start();
        switch (strtoupper(substr(constant('PHP_OS'), 0, 3))) {
            case 'WIN':
                passthru('ipconfig /all 2>&1');

                break;
            case 'DAR':
                passthru('ifconfig 2>&1');

                break;
            case 'FRE':
                passthru('netstat -i -f link 2>&1');

                break;
            case 'LIN':
            default:
                passthru('netstat -ie 2>&1');

                break;
        }

        $ifconfig = (string) ob_get_clean();

        $node = '';
        if (preg_match_all(self::IFCONFIG_PATTERN, $ifconfig, $matches, PREG_PATTERN_ORDER)) {
            $node = $matches[1][0] ?? '';
        }

        return (string) $node;
    }

    /**
     * Returns MAC address from the first system interface via the sysfs interface
     */
    protected function getSysfs(): string
    {
        $mac = '';

        if (strtoupper(constant('PHP_OS')) === 'LINUX') {
            $addressPaths = glob('/sys/class/net/*/address', GLOB_NOSORT);

            if ($addressPaths === false || count($addressPaths) === 0) {
                return '';
            }

            $macs = [];

            array_walk($addressPaths, function (string $addressPath) use (&$macs): void {
                if (is_readable($addressPath)) {
                    $macs[] = file_get_contents($addressPath);
                }
            });

            $macs = array_map('trim', $macs);

            // Remove invalid entries.
            $macs = array_filter($macs, function (string $address) {
                return $address !== '00:00:00:00:00:00'
                    && preg_match(self::SYSFS_PATTERN, $address);
            });

            $mac = reset($macs);
        }

        return (string) $mac;
    }
}
uuid/src/Provider/Node/FallbackNodeProvider.php000064400000003021147361033650015515 0ustar00<?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\Provider\Node;

use Ramsey\Uuid\Exception\NodeException;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;

/**
 * FallbackNodeProvider retrieves the system node ID by stepping through a list
 * of providers until a node ID can be obtained
 */
class FallbackNodeProvider implements NodeProviderInterface
{
    /**
     * @var NodeProviderCollection
     */
    private $nodeProviders;

    /**
     * @param NodeProviderCollection $providers Array of node providers
     */
    public function __construct(NodeProviderCollection $providers)
    {
        $this->nodeProviders = $providers;
    }

    public function getNode(): Hexadecimal
    {
        $lastProviderException = null;

        /** @var NodeProviderInterface $provider */
        foreach ($this->nodeProviders as $provider) {
            try {
                return $provider->getNode();
            } catch (NodeException $exception) {
                $lastProviderException = $exception;

                continue;
            }
        }

        throw new NodeException(
            'Unable to find a suitable node provider',
            0,
            $lastProviderException
        );
    }
}
uuid/src/Provider/Node/NodeProviderCollection.php000064400000002705147361033650016121 0ustar00<?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\Provider\Node;

use Ramsey\Collection\AbstractCollection;
use Ramsey\Collection\CollectionInterface;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;

/**
 * A collection of NodeProviderInterface objects
 */
class NodeProviderCollection extends AbstractCollection implements CollectionInterface
{
    public function getType(): string
    {
        return NodeProviderInterface::class;
    }

    /**
     * Re-constructs the object from its serialized form
     *
     * @param string $serialized The serialized PHP string to unserialize into
     *     a UuidInterface instance
     *
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     */
    public function unserialize($serialized): void
    {
        /** @var mixed[] $data */
        $data = unserialize($serialized, [
            'allowed_classes' => [
                Hexadecimal::class,
                RandomNodeProvider::class,
                StaticNodeProvider::class,
                SystemNodeProvider::class,
            ],
        ]);

        $this->data = $data;
    }
}
uuid/src/Provider/Time/SystemTimeProvider.php000064400000001366147361033650015336 0ustar00<?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\Provider\Time;

use Ramsey\Uuid\Provider\TimeProviderInterface;
use Ramsey\Uuid\Type\Time;

use function gettimeofday;

/**
 * SystemTimeProvider retrieves the current time using built-in PHP functions
 */
class SystemTimeProvider implements TimeProviderInterface
{
    public function getTime(): Time
    {
        $time = gettimeofday();

        return new Time($time['sec'], $time['usec']);
    }
}
uuid/src/Provider/Time/FixedTimeProvider.php000064400000002745147361033650015113 0ustar00<?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\Provider\Time;

use Ramsey\Uuid\Provider\TimeProviderInterface;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Type\Time;

/**
 * FixedTimeProvider uses an known time to provide the time
 *
 * This provider allows the use of a previously-generated, or known, time
 * when generating time-based UUIDs.
 */
class FixedTimeProvider implements TimeProviderInterface
{
    /**
     * @var Time
     */
    private $fixedTime;

    public function __construct(Time $time)
    {
        $this->fixedTime = $time;
    }

    /**
     * Sets the `usec` component of the time
     *
     * @param int|string|IntegerObject $value The `usec` value to set
     */
    public function setUsec($value): void
    {
        $this->fixedTime = new Time($this->fixedTime->getSeconds(), $value);
    }

    /**
     * Sets the `sec` component of the time
     *
     * @param int|string|IntegerObject $value The `sec` value to set
     */
    public function setSec($value): void
    {
        $this->fixedTime = new Time($value, $this->fixedTime->getMicroseconds());
    }

    public function getTime(): Time
    {
        return $this->fixedTime;
    }
}
uuid/src/Provider/NodeProviderInterface.php000064400000001214147361033650015033 0ustar00<?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\Provider;

use Ramsey\Uuid\Type\Hexadecimal;

/**
 * A node provider retrieves or generates a node ID
 */
interface NodeProviderInterface
{
    /**
     * Returns a node ID
     *
     * @return Hexadecimal The node ID as a hexadecimal string
     */
    public function getNode(): Hexadecimal;
}
uuid/src/Provider/Dce/SystemDceSecurityProvider.php000064400000014726147361033650016464 0ustar00<?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\Provider\Dce;

use Ramsey\Uuid\Exception\DceSecurityException;
use Ramsey\Uuid\Provider\DceSecurityProviderInterface;
use Ramsey\Uuid\Type\Integer as IntegerObject;

use function escapeshellarg;
use function preg_split;
use function str_getcsv;
use function strpos;
use function strrpos;
use function strtolower;
use function strtoupper;
use function substr;
use function trim;

use const PREG_SPLIT_NO_EMPTY;

/**
 * SystemDceSecurityProvider retrieves the user or group identifiers from the system
 */
class SystemDceSecurityProvider implements DceSecurityProviderInterface
{
    /**
     * @throws DceSecurityException if unable to get a user identifier
     *
     * @inheritDoc
     */
    public function getUid(): IntegerObject
    {
        static $uid = null;

        if ($uid instanceof IntegerObject) {
            return $uid;
        }

        if ($uid === null) {
            $uid = $this->getSystemUid();
        }

        if ($uid === '') {
            throw new DceSecurityException(
                'Unable to get a user identifier using the system DCE '
                . 'Security provider; please provide a custom identifier or '
                . 'use a different provider'
            );
        }

        $uid = new IntegerObject($uid);

        return $uid;
    }

    /**
     * @throws DceSecurityException if unable to get a group identifier
     *
     * @inheritDoc
     */
    public function getGid(): IntegerObject
    {
        static $gid = null;

        if ($gid instanceof IntegerObject) {
            return $gid;
        }

        if ($gid === null) {
            $gid = $this->getSystemGid();
        }

        if ($gid === '') {
            throw new DceSecurityException(
                'Unable to get a group identifier using the system DCE '
                . 'Security provider; please provide a custom identifier or '
                . 'use a different provider'
            );
        }

        $gid = new IntegerObject($gid);

        return $gid;
    }

    /**
     * Returns the UID from the system
     */
    private function getSystemUid(): string
    {
        if (!$this->hasShellExec()) {
            return '';
        }

        switch ($this->getOs()) {
            case 'WIN':
                return $this->getWindowsUid();
            case 'DAR':
            case 'FRE':
            case 'LIN':
            default:
                return trim((string) shell_exec('id -u'));
        }
    }

    /**
     * Returns the GID from the system
     */
    private function getSystemGid(): string
    {
        if (!$this->hasShellExec()) {
            return '';
        }

        switch ($this->getOs()) {
            case 'WIN':
                return $this->getWindowsGid();
            case 'DAR':
            case 'FRE':
            case 'LIN':
            default:
                return trim((string) shell_exec('id -g'));
        }
    }

    /**
     * Returns true if shell_exec() is available for use
     */
    private function hasShellExec(): bool
    {
        $disabledFunctions = strtolower((string) ini_get('disable_functions'));

        return strpos($disabledFunctions, 'shell_exec') === false;
    }

    /**
     * Returns the PHP_OS string
     */
    private function getOs(): string
    {
        return strtoupper(substr(constant('PHP_OS'), 0, 3));
    }

    /**
     * Returns the user identifier for a user on a Windows system
     *
     * Windows does not have the same concept as an effective POSIX UID for the
     * running script. Instead, each user is uniquely identified by an SID
     * (security identifier). The SID includes three 32-bit unsigned integers
     * that make up a unique domain identifier, followed by an RID (relative
     * identifier) that we will use as the UID. The primary caveat is that this
     * UID may not be unique to the system, since it is, instead, unique to the
     * domain.
     *
     * @link https://www.lifewire.com/what-is-an-sid-number-2626005 What Is an SID Number?
     * @link https://bit.ly/30vE7NM Well-known SID Structures
     * @link https://bit.ly/2FWcYKJ Well-known security identifiers in Windows operating systems
     * @link https://www.windows-commandline.com/get-sid-of-user/ Get SID of user
     */
    private function getWindowsUid(): string
    {
        $response = shell_exec('whoami /user /fo csv /nh');

        if ($response === null) {
            return '';
        }

        /** @var string $sid */
        $sid = str_getcsv(trim($response))[1] ?? '';

        if (($lastHyphen = strrpos($sid, '-')) === false) {
            return '';
        }

        return trim(substr($sid, $lastHyphen + 1));
    }

    /**
     * Returns a group identifier for a user on a Windows system
     *
     * Since Windows does not have the same concept as an effective POSIX GID
     * for the running script, we will get the local group memberships for the
     * user running the script. Then, we will get the SID (security identifier)
     * for the first group that appears in that list. Finally, we will return
     * the RID (relative identifier) for the group and use that as the GID.
     *
     * @link https://www.windows-commandline.com/list-of-user-groups-command-line/ List of user groups command line
     */
    private function getWindowsGid(): string
    {
        $response = shell_exec('net user %username% | findstr /b /i "Local Group Memberships"');

        if ($response === null) {
            return '';
        }

        /** @var string[] $userGroups */
        $userGroups = preg_split('/\s{2,}/', $response, -1, PREG_SPLIT_NO_EMPTY);

        $firstGroup = trim($userGroups[1] ?? '', "* \t\n\r\0\x0B");

        if ($firstGroup === '') {
            return '';
        }

        $response = shell_exec('wmic group get name,sid | findstr /b /i ' . escapeshellarg($firstGroup));

        if ($response === null) {
            return '';
        }

        /** @var string[] $userGroup */
        $userGroup = preg_split('/\s{2,}/', $response, -1, PREG_SPLIT_NO_EMPTY);

        $sid = $userGroup[1] ?? '';

        if (($lastHyphen = strrpos($sid, '-')) === false) {
            return '';
        }

        return trim((string) substr($sid, $lastHyphen + 1));
    }
}
uuid/src/Provider/TimeProviderInterface.php000064400000001066147361033650015051 0ustar00<?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\Provider;

use Ramsey\Uuid\Type\Time;

/**
 * A time provider retrieves the current time
 */
interface TimeProviderInterface
{
    /**
     * Returns a time object
     */
    public function getTime(): Time;
}
uuid/src/Provider/DceSecurityProviderInterface.php000064400000001751147361033650016377 0ustar00<?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\Provider;

use Ramsey\Uuid\Rfc4122\UuidV2;
use Ramsey\Uuid\Type\Integer as IntegerObject;

/**
 * A DCE provider provides access to local domain identifiers for version 2,
 * DCE Security, UUIDs
 *
 * @see UuidV2
 */
interface DceSecurityProviderInterface
{
    /**
     * Returns a user identifier for the system
     *
     * @link https://en.wikipedia.org/wiki/User_identifier User identifier
     */
    public function getUid(): IntegerObject;

    /**
     * Returns a group identifier for the system
     *
     * @link https://en.wikipedia.org/wiki/Group_identifier Group identifier
     */
    public function getGid(): IntegerObject;
}
uuid/src/Rfc4122/NilUuid.php000064400000001077147361033650011423 0ustar00<?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\Uuid;

/**
 * The nil UUID is special form of UUID that is specified to have all 128 bits
 * set to zero
 *
 * @psalm-immutable
 */
final class NilUuid extends Uuid implements UuidInterface
{
}
uuid/src/Rfc4122/VariantTrait.php000064400000004646147361033650012467 0ustar00<?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\Exception\InvalidBytesException;
use Ramsey\Uuid\Uuid;

use function decbin;
use function str_pad;
use function strlen;
use function strpos;
use function substr;
use function unpack;

use const STR_PAD_LEFT;

/**
 * Provides common functionality for handling the variant, as defined by RFC 4122
 *
 * @psalm-immutable
 */
trait VariantTrait
{
    /**
     * Returns the bytes that comprise the fields
     */
    abstract public function getBytes(): string;

    /**
     * Returns the variant identifier, according to RFC 4122, for the given bytes
     *
     * The following values may be returned:
     *
     * - `0` -- Reserved, NCS backward compatibility.
     * - `2` -- The variant specified in RFC 4122.
     * - `6` -- Reserved, Microsoft Corporation backward compatibility.
     * - `7` -- Reserved for future definition.
     *
     * @link https://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
     *
     * @return int The variant identifier, according to RFC 4122
     */
    public function getVariant(): int
    {
        if (strlen($this->getBytes()) !== 16) {
            throw new InvalidBytesException('Invalid number of bytes');
        }

        $parts = unpack('n*', $this->getBytes());

        // $parts[5] is a 16-bit, unsigned integer containing the variant bits
        // of the UUID. We convert this integer into a string containing a
        // binary representation, padded to 16 characters. We analyze the first
        // three characters (three most-significant bits) to determine the
        // variant.
        $binary = str_pad(
            decbin((int) $parts[5]),
            16,
            '0',
            STR_PAD_LEFT
        );

        $msb = substr($binary, 0, 3);

        if ($msb === '111') {
            $variant = Uuid::RESERVED_FUTURE;
        } elseif ($msb === '110') {
            $variant = Uuid::RESERVED_MICROSOFT;
        } elseif (strpos($msb, '10') === 0) {
            $variant = Uuid::RFC_4122;
        } else {
            $variant = Uuid::RESERVED_NCS;
        }

        return $variant;
    }
}
uuid/src/Rfc4122/Validator.php000064400000002537147361033650012001 0ustar00<?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\Uuid;
use Ramsey\Uuid\Validator\ValidatorInterface;

use function preg_match;
use function str_replace;

/**
 * Rfc4122\Validator validates strings as UUIDs of the RFC 4122 variant
 *
 * @psalm-immutable
 */
final class Validator implements ValidatorInterface
{
    private const VALID_PATTERN = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-'
        . '[1-5]{1}[0-9A-Fa-f]{3}-[ABab89]{1}[0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$';

    /**
     * @psalm-return non-empty-string
     * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
     * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
     */
    public function getPattern(): string
    {
        return self::VALID_PATTERN;
    }

    public function validate(string $uuid): bool
    {
        $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid);

        return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/D', $uuid);
    }
}
uuid/src/Rfc4122/Fields.php000064400000012724147361033650011261 0ustar00<?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\Exception\InvalidArgumentException;
use Ramsey\Uuid\Fields\SerializableFieldsTrait;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Uuid;

use function bin2hex;
use function dechex;
use function hexdec;
use function sprintf;
use function str_pad;
use function strlen;
use function substr;
use function unpack;

use const STR_PAD_LEFT;

/**
 * RFC 4122 variant UUIDs are comprised of a set of named fields
 *
 * Internally, this class represents the fields together as a 16-byte binary
 * string.
 *
 * @psalm-immutable
 */
final class Fields implements FieldsInterface
{
    use NilTrait;
    use SerializableFieldsTrait;
    use VariantTrait;
    use VersionTrait;

    /**
     * @var string
     */
    private $bytes;

    /**
     * @param string $bytes A 16-byte binary string representation of a UUID
     *
     * @throws InvalidArgumentException if the byte string is not exactly 16 bytes
     * @throws InvalidArgumentException if the byte string does not represent an RFC 4122 UUID
     * @throws InvalidArgumentException if the byte string does not contain a valid version
     */
    public function __construct(string $bytes)
    {
        if (strlen($bytes) !== 16) {
            throw new InvalidArgumentException(
                'The byte string must be 16 bytes long; '
                . 'received ' . strlen($bytes) . ' bytes'
            );
        }

        $this->bytes = $bytes;

        if (!$this->isCorrectVariant()) {
            throw new InvalidArgumentException(
                'The byte string received does not conform to the RFC 4122 variant'
            );
        }

        if (!$this->isCorrectVersion()) {
            throw new InvalidArgumentException(
                'The byte string received does not contain a valid RFC 4122 version'
            );
        }
    }

    public function getBytes(): string
    {
        return $this->bytes;
    }

    public function getClockSeq(): Hexadecimal
    {
        $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;

        return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
    }

    public function getClockSeqHiAndReserved(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1)));
    }

    public function getClockSeqLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1)));
    }

    public function getNode(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 10)));
    }

    public function getTimeHiAndVersion(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 6, 2)));
    }

    public function getTimeLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 0, 4)));
    }

    public function getTimeMid(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 4, 2)));
    }

    /**
     * Returns the full 60-bit timestamp, without the version
     *
     * For version 2 UUIDs, the time_low field is the local identifier and
     * should not be returned as part of the time. For this reason, we set the
     * bottom 32 bits of the timestamp to 0's. As a result, there is some loss
     * of fidelity of the timestamp, for version 2 UUIDs. The timestamp can be
     * off by a range of 0 to 429.4967295 seconds (or 7 minutes, 9 seconds, and
     * 496730 microseconds).
     *
     * For version 6 UUIDs, the timestamp order is reversed from the typical RFC
     * 4122 order (the time bits are in the correct bit order, so that it is
     * monotonically increasing). In returning the timestamp value, we put the
     * bits in the order: time_low + time_mid + time_hi.
     */
    public function getTimestamp(): Hexadecimal
    {
        switch ($this->getVersion()) {
            case Uuid::UUID_TYPE_DCE_SECURITY:
                $timestamp = sprintf(
                    '%03x%04s%08s',
                    hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
                    $this->getTimeMid()->toString(),
                    ''
                );

                break;
            case Uuid::UUID_TYPE_PEABODY:
                $timestamp = sprintf(
                    '%08s%04s%03x',
                    $this->getTimeLow()->toString(),
                    $this->getTimeMid()->toString(),
                    hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff
                );

                break;
            default:
                $timestamp = sprintf(
                    '%03x%04s%08s',
                    hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
                    $this->getTimeMid()->toString(),
                    $this->getTimeLow()->toString()
                );
        }

        return new Hexadecimal($timestamp);
    }

    public function getVersion(): ?int
    {
        if ($this->isNil()) {
            return null;
        }

        $parts = unpack('n*', $this->bytes);

        return (int) $parts[4] >> 12;
    }

    private function isCorrectVariant(): bool
    {
        if ($this->isNil()) {
            return true;
        }

        return $this->getVariant() === Uuid::RFC_4122;
    }
}
uuid/src/Rfc4122/UuidV2.php000064400000012202147361033650011160 0ustar00<?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 DateTimeImmutable;
use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Uuid;
use Throwable;

use function hexdec;
use function str_pad;

use const STR_PAD_LEFT;

/**
 * DCE Security version, or version 2, UUIDs include local domain identifier,
 * local ID for the specified domain, and node values that are combined into a
 * 128-bit unsigned integer
 *
 * @link https://publications.opengroup.org/c311 DCE 1.1: Authentication and Security Services
 * @link https://publications.opengroup.org/c706 DCE 1.1: Remote Procedure Call
 * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01 DCE 1.1: Auth & Sec, §5.2.1.1
 * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1: Auth & Sec, §11.5.1.1
 * @link https://pubs.opengroup.org/onlinepubs/9629399/apdxa.htm DCE 1.1: RPC, Appendix A
 * @link https://github.com/google/uuid Go package for UUIDs (includes DCE implementation)
 *
 * @psalm-immutable
 */
final class UuidV2 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 2 (DCE Security) 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_DCE_SECURITY) {
            throw new InvalidArgumentException(
                'Fields used to create a UuidV2 must represent a '
                . 'version 2 (DCE Security) UUID'
            );
        }

        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }

    /**
     * Returns a DateTimeInterface object representing the timestamp associated
     * with the UUID
     *
     * It is important to note that a version 2 UUID suffers from some loss of
     * fidelity of the timestamp, due to replacing the time_low field with the
     * local identifier. When constructing the timestamp value for date
     * purposes, we replace the local identifier bits with zeros. As a result,
     * the timestamp can be off by a range of 0 to 429.4967295 seconds (or 7
     * minutes, 9 seconds, and 496730 microseconds).
     *
     * Astute observers might note this value directly corresponds to 2^32 - 1,
     * or 0xffffffff. The local identifier is 32-bits, and we have set each of
     * these bits to 0, so the maximum range of timestamp drift is 0x00000000
     * to 0xffffffff (counted in 100-nanosecond intervals).
     *
     * @return DateTimeImmutable A PHP DateTimeImmutable instance representing
     *     the timestamp of a version 2 UUID
     */
    public function getDateTime(): DateTimeInterface
    {
        $time = $this->timeConverter->convertTime($this->fields->getTimestamp());

        try {
            return new DateTimeImmutable(
                '@'
                . $time->getSeconds()->toString()
                . '.'
                . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
            );
        } catch (Throwable $e) {
            throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }

    /**
     * Returns the local domain used to create this version 2 UUID
     */
    public function getLocalDomain(): int
    {
        /** @var Rfc4122FieldsInterface $fields */
        $fields = $this->getFields();

        return (int) hexdec($fields->getClockSeqLow()->toString());
    }

    /**
     * Returns the string name of the local domain
     */
    public function getLocalDomainName(): string
    {
        return Uuid::DCE_DOMAIN_NAMES[$this->getLocalDomain()];
    }

    /**
     * Returns the local identifier for the domain used to create this version 2 UUID
     */
    public function getLocalIdentifier(): IntegerObject
    {
        /** @var Rfc4122FieldsInterface $fields */
        $fields = $this->getFields();

        return new IntegerObject(
            $this->numberConverter->fromHex($fields->getTimeLow()->toString())
        );
    }
}
uuid/src/Rfc4122/NilTrait.php000064400000001703147361033650011574 0ustar00<?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;

/**
 * Provides common functionality for nil UUIDs
 *
 * The nil UUID is special form of UUID that is specified to have all 128 bits
 * set to zero.
 *
 * @link https://tools.ietf.org/html/rfc4122#section-4.1.7 RFC 4122, § 4.1.7: Nil UUID
 *
 * @psalm-immutable
 */
trait NilTrait
{
    /**
     * Returns the bytes that comprise the fields
     */
    abstract public function getBytes(): string;

    /**
     * Returns true if the byte string represents a nil UUID
     */
    public function isNil(): bool
    {
        return $this->getBytes() === "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    }
}
uuid/src/Rfc4122/UuidInterface.php000064400000001764147361033650012604 0ustar00<?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\UuidInterface as BaseUuidInterface;

/**
 * Also known as a Leach-Salz variant UUID, an RFC 4122 variant UUID is a
 * universally unique identifier defined by RFC 4122
 *
 * @link https://tools.ietf.org/html/rfc4122 RFC 4122
 *
 * @psalm-immutable
 */
interface UuidInterface extends BaseUuidInterface
{
    /**
     * Returns the string standard representation of the UUID as a URN
     *
     * @link http://en.wikipedia.org/wiki/Uniform_Resource_Name Uniform Resource Name
     * @link https://tools.ietf.org/html/rfc4122#section-3 RFC 4122, § 3: Namespace Registration Template
     */
    public function getUrn(): string;
}
uuid/src/Rfc4122/FieldsInterface.php000064400000007342147361033650013102 0ustar00<?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\Fields\FieldsInterface as BaseFieldsInterface;
use Ramsey\Uuid\Type\Hexadecimal;

/**
 * RFC 4122 defines fields for a specific variant of UUID
 *
 * The fields of an RFC 4122 variant UUID are:
 *
 * * **time_low**: The low field of the timestamp, an unsigned 32-bit integer
 * * **time_mid**: The middle field of the timestamp, an unsigned 16-bit integer
 * * **time_hi_and_version**: The high field of the timestamp multiplexed with
 *   the version number, an unsigned 16-bit integer
 * * **clock_seq_hi_and_reserved**: The high field of the clock sequence
 *   multiplexed with the variant, an unsigned 8-bit integer
 * * **clock_seq_low**: The low field of the clock sequence, an unsigned
 *   8-bit integer
 * * **node**: The spatially unique node identifier, an unsigned 48-bit
 *   integer
 *
 * @link http://tools.ietf.org/html/rfc4122#section-4.1 RFC 4122, § 4.1: Format
 *
 * @psalm-immutable
 */
interface FieldsInterface extends BaseFieldsInterface
{
    /**
     * Returns the full 16-bit clock sequence, with the variant bits (two most
     * significant bits) masked out
     */
    public function getClockSeq(): Hexadecimal;

    /**
     * Returns the high field of the clock sequence multiplexed with the variant
     */
    public function getClockSeqHiAndReserved(): Hexadecimal;

    /**
     * Returns the low field of the clock sequence
     */
    public function getClockSeqLow(): Hexadecimal;

    /**
     * Returns the node field
     */
    public function getNode(): Hexadecimal;

    /**
     * Returns the high field of the timestamp multiplexed with the version
     */
    public function getTimeHiAndVersion(): Hexadecimal;

    /**
     * Returns the low field of the timestamp
     */
    public function getTimeLow(): Hexadecimal;

    /**
     * Returns the middle field of the timestamp
     */
    public function getTimeMid(): Hexadecimal;

    /**
     * Returns the full 60-bit timestamp, without the version
     */
    public function getTimestamp(): Hexadecimal;

    /**
     * Returns the variant
     *
     * The variant number describes the layout of the UUID. The variant
     * number has the following meaning:
     *
     * - 0 - Reserved for NCS backward compatibility
     * - 2 - The RFC 4122 variant
     * - 6 - Reserved, Microsoft Corporation backward compatibility
     * - 7 - Reserved for future definition
     *
     * For RFC 4122 variant UUIDs, this value should always be the integer `2`.
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
     */
    public function getVariant(): int;

    /**
     * Returns the version
     *
     * The version number describes how the UUID was generated and has the
     * following meaning:
     *
     * 1. Time-based UUID
     * 2. DCE security UUID
     * 3. Name-based UUID hashed with MD5
     * 4. Randomly generated UUID
     * 5. Name-based UUID hashed with SHA-1
     *
     * This returns `null` if the UUID is not an RFC 4122 variant, since version
     * is only meaningful for this variant.
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
     */
    public function getVersion(): ?int;

    /**
     * Returns true if these fields represent a nil UUID
     *
     * The nil UUID is special form of UUID that is specified to have all 128
     * bits set to zero.
     */
    public function isNil(): bool;
}
uuid/src/Rfc4122/UuidBuilder.php000064400000007115147361033650012266 0ustar00<?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\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Nonstandard\UuidV6;
use Ramsey\Uuid\Rfc4122\UuidInterface as Rfc4122UuidInterface;
use Ramsey\Uuid\UuidInterface;
use Throwable;

/**
 * UuidBuilder builds instances of RFC 4122 UUIDs
 *
 * @psalm-immutable
 */
class UuidBuilder implements UuidBuilderInterface
{
    /**
     * @var NumberConverterInterface
     */
    private $numberConverter;

    /**
     * @var TimeConverterInterface
     */
    private $timeConverter;

    /**
     * Constructs the DefaultUuidBuilder
     *
     * @param NumberConverterInterface $numberConverter The number converter to
     *     use when constructing the Uuid
     * @param TimeConverterInterface $timeConverter The time converter to use
     *     for converting timestamps extracted from a UUID to Unix timestamps
     */
    public function __construct(
        NumberConverterInterface $numberConverter,
        TimeConverterInterface $timeConverter
    ) {
        $this->numberConverter = $numberConverter;
        $this->timeConverter = $timeConverter;
    }

    /**
     * Builds and returns a Uuid
     *
     * @param CodecInterface $codec The codec to use for building this Uuid instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return Rfc4122UuidInterface UuidBuilder returns instances of Rfc4122UuidInterface
     *
     * @psalm-pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        try {
            $fields = $this->buildFields($bytes);

            if ($fields->isNil()) {
                return new NilUuid($fields, $this->numberConverter, $codec, $this->timeConverter);
            }

            switch ($fields->getVersion()) {
                case 1:
                    return new UuidV1($fields, $this->numberConverter, $codec, $this->timeConverter);
                case 2:
                    return new UuidV2($fields, $this->numberConverter, $codec, $this->timeConverter);
                case 3:
                    return new UuidV3($fields, $this->numberConverter, $codec, $this->timeConverter);
                case 4:
                    return new UuidV4($fields, $this->numberConverter, $codec, $this->timeConverter);
                case 5:
                    return new UuidV5($fields, $this->numberConverter, $codec, $this->timeConverter);
                case 6:
                    return new UuidV6($fields, $this->numberConverter, $codec, $this->timeConverter);
            }

            throw new UnsupportedOperationException(
                'The UUID version in the given fields is not supported '
                . 'by this UUID builder'
            );
        } catch (Throwable $e) {
            throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }

    /**
     * Proxy method to allow injecting a mock, for testing
     */
    protected function buildFields(string $bytes): FieldsInterface
    {
        return new Fields($bytes);
    }
}
uuid/src/Rfc4122/UuidV4.php000064400000003604147361033650011170 0ustar00<?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;

/**
 * Random, or version 4, UUIDs are randomly or pseudo-randomly generated 128-bit
 * integers
 *
 * @psalm-immutable
 */
final class UuidV4 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 4 (random) 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_RANDOM) {
            throw new InvalidArgumentException(
                'Fields used to create a UuidV4 must represent a '
                . 'version 4 (random) UUID'
            );
        }

        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
uuid/src/Rfc4122/UuidV5.php000064400000003731147361033650011172 0ustar00<?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 5 UUIDs are named-based, using combination of a namespace and name
 * that are hashed into a 128-bit unsigned integer using SHA1
 *
 * @psalm-immutable
 */
final class UuidV5 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 5 (name-based, SHA1-hashed) 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_HASH_SHA1) {
            throw new InvalidArgumentException(
                'Fields used to create a UuidV5 must represent a '
                . 'version 5 (named-based, SHA1-hashed) UUID'
            );
        }

        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
uuid/src/Rfc4122/UuidV1.php000064400000005703147361033650011167 0ustar00<?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 DateTimeImmutable;
use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Uuid;
use Throwable;

use function str_pad;

use const STR_PAD_LEFT;

/**
 * Time-based, or version 1, UUIDs include timestamp, clock sequence, and node
 * values that are combined into a 128-bit unsigned integer
 *
 * @psalm-immutable
 */
final class UuidV1 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 1 (time-based) 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_TIME) {
            throw new InvalidArgumentException(
                'Fields used to create a UuidV1 must represent a '
                . 'version 1 (time-based) UUID'
            );
        }

        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }

    /**
     * Returns a DateTimeInterface object representing the timestamp associated
     * with the UUID
     *
     * The timestamp value is only meaningful in a time-based UUID, which
     * has version type 1.
     *
     * @return DateTimeImmutable A PHP DateTimeImmutable instance representing
     *     the timestamp of a version 1 UUID
     */
    public function getDateTime(): DateTimeInterface
    {
        $time = $this->timeConverter->convertTime($this->fields->getTimestamp());

        try {
            return new DateTimeImmutable(
                '@'
                . $time->getSeconds()->toString()
                . '.'
                . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
            );
        } catch (Throwable $e) {
            throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }
}
uuid/src/Rfc4122/UuidV3.php000064400000003724147361033650011172 0ustar00<?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 3 UUIDs are named-based, using combination of a namespace and name
 * that are hashed into a 128-bit unsigned integer using MD5
 *
 * @psalm-immutable
 */
final class UuidV3 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 3 (name-based, MD5-hashed) 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_HASH_MD5) {
            throw new InvalidArgumentException(
                'Fields used to create a UuidV3 must represent a '
                . 'version 3 (name-based, MD5-hashed) UUID'
            );
        }

        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
uuid/src/Rfc4122/VersionTrait.php000064400000002313147361033650012475 0ustar00<?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;

/**
 * Provides common functionality for handling the version, as defined by RFC 4122
 *
 * @psalm-immutable
 */
trait VersionTrait
{
    /**
     * Returns the version
     */
    abstract public function getVersion(): ?int;

    /**
     * Returns true if these fields represent a nil UUID
     */
    abstract public function isNil(): bool;

    /**
     * Returns true if the version matches one of those defined by RFC 4122
     *
     * @return bool True if the UUID version is valid, false otherwise
     */
    private function isCorrectVersion(): bool
    {
        if ($this->isNil()) {
            return true;
        }

        switch ($this->getVersion()) {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
                return true;
        }

        return false;
    }
}
uuid/src/Guid/Fields.php000064400000011450147361033650011121 0ustar00<?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\Guid;

use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Fields\SerializableFieldsTrait;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Rfc4122\NilTrait;
use Ramsey\Uuid\Rfc4122\VariantTrait;
use Ramsey\Uuid\Rfc4122\VersionTrait;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Uuid;

use function bin2hex;
use function dechex;
use function hexdec;
use function pack;
use function sprintf;
use function str_pad;
use function strlen;
use function substr;
use function unpack;

use const STR_PAD_LEFT;

/**
 * GUIDs are comprised of a set of named fields, according to RFC 4122
 *
 * @see Guid
 *
 * @psalm-immutable
 */
final class Fields implements FieldsInterface
{
    use NilTrait;
    use SerializableFieldsTrait;
    use VariantTrait;
    use VersionTrait;

    /**
     * @var string
     */
    private $bytes;

    /**
     * @param string $bytes A 16-byte binary string representation of a UUID
     *
     * @throws InvalidArgumentException if the byte string is not exactly 16 bytes
     * @throws InvalidArgumentException if the byte string does not represent a GUID
     * @throws InvalidArgumentException if the byte string does not contain a valid version
     */
    public function __construct(string $bytes)
    {
        if (strlen($bytes) !== 16) {
            throw new InvalidArgumentException(
                'The byte string must be 16 bytes long; '
                . 'received ' . strlen($bytes) . ' bytes'
            );
        }

        $this->bytes = $bytes;

        if (!$this->isCorrectVariant()) {
            throw new InvalidArgumentException(
                'The byte string received does not conform to the RFC '
                . '4122 or Microsoft Corporation variants'
            );
        }

        if (!$this->isCorrectVersion()) {
            throw new InvalidArgumentException(
                'The byte string received does not contain a valid version'
            );
        }
    }

    public function getBytes(): string
    {
        return $this->bytes;
    }

    public function getTimeLow(): Hexadecimal
    {
        // Swap the bytes from little endian to network byte order.
        $hex = unpack(
            'H*',
            pack(
                'v*',
                hexdec(bin2hex(substr($this->bytes, 2, 2))),
                hexdec(bin2hex(substr($this->bytes, 0, 2)))
            )
        );

        return new Hexadecimal((string) ($hex[1] ?? ''));
    }

    public function getTimeMid(): Hexadecimal
    {
        // Swap the bytes from little endian to network byte order.
        $hex = unpack(
            'H*',
            pack(
                'v',
                hexdec(bin2hex(substr($this->bytes, 4, 2)))
            )
        );

        return new Hexadecimal((string) ($hex[1] ?? ''));
    }

    public function getTimeHiAndVersion(): Hexadecimal
    {
        // Swap the bytes from little endian to network byte order.
        $hex = unpack(
            'H*',
            pack(
                'v',
                hexdec(bin2hex(substr($this->bytes, 6, 2)))
            )
        );

        return new Hexadecimal((string) ($hex[1] ?? ''));
    }

    public function getTimestamp(): Hexadecimal
    {
        return new Hexadecimal(sprintf(
            '%03x%04s%08s',
            hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
            $this->getTimeMid()->toString(),
            $this->getTimeLow()->toString()
        ));
    }

    public function getClockSeq(): Hexadecimal
    {
        $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;

        return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
    }

    public function getClockSeqHiAndReserved(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1)));
    }

    public function getClockSeqLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1)));
    }

    public function getNode(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 10)));
    }

    public function getVersion(): ?int
    {
        if ($this->isNil()) {
            return null;
        }

        $parts = unpack('n*', $this->bytes);

        return ((int) $parts[4] >> 4) & 0x00f;
    }

    private function isCorrectVariant(): bool
    {
        if ($this->isNil()) {
            return true;
        }

        $variant = $this->getVariant();

        return $variant === Uuid::RFC_4122 || $variant === Uuid::RESERVED_MICROSOFT;
    }
}
uuid/src/Guid/GuidBuilder.php000064400000004600147361033650012111 0ustar00<?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\Guid;

use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\UuidInterface;
use Throwable;

/**
 * GuidBuilder builds instances of Guid
 *
 * @see Guid
 *
 * @psalm-immutable
 */
class GuidBuilder implements UuidBuilderInterface
{
    /**
     * @var NumberConverterInterface
     */
    private $numberConverter;

    /**
     * @var TimeConverterInterface
     */
    private $timeConverter;

    /**
     * @param NumberConverterInterface $numberConverter The number converter to
     *     use when constructing the Guid
     * @param TimeConverterInterface $timeConverter The time converter to use
     *     for converting timestamps extracted from a UUID to Unix timestamps
     */
    public function __construct(
        NumberConverterInterface $numberConverter,
        TimeConverterInterface $timeConverter
    ) {
        $this->numberConverter = $numberConverter;
        $this->timeConverter = $timeConverter;
    }

    /**
     * Builds and returns a Guid
     *
     * @param CodecInterface $codec The codec to use for building this Guid instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return Guid The GuidBuilder returns an instance of Ramsey\Uuid\Guid\Guid
     *
     * @psalm-pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        try {
            return new Guid(
                $this->buildFields($bytes),
                $this->numberConverter,
                $codec,
                $this->timeConverter
            );
        } catch (Throwable $e) {
            throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }

    /**
     * Proxy method to allow injecting a mock, for testing
     */
    protected function buildFields(string $bytes): Fields
    {
        return new Fields($bytes);
    }
}
uuid/src/Guid/Guid.php000064400000004467147361033650010615 0ustar00<?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\Guid;

use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;

/**
 * Guid represents a UUID with "native" (little-endian) byte order
 *
 * From Wikipedia:
 *
 * > The first three fields are unsigned 32- and 16-bit integers and are subject
 * > to swapping, while the last two fields consist of uninterpreted bytes, not
 * > subject to swapping. This byte swapping applies even for versions 3, 4, and
 * > 5, where the canonical fields do not correspond to the content of the UUID.
 *
 * The first three fields of a GUID are encoded in little-endian byte order,
 * while the last three fields are in network (big-endian) byte order. This is
 * according to the history of the Microsoft definition of a GUID.
 *
 * According to the .NET Guid.ToByteArray method documentation:
 *
 * > Note that the order of bytes in the returned byte array is different from
 * > the string representation of a Guid value. The order of the beginning
 * > four-byte group and the next two two-byte groups is reversed, whereas the
 * > order of the last two-byte group and the closing six-byte group is the
 * > same.
 *
 * @link https://en.wikipedia.org/wiki/Universally_unique_identifier#Variants UUID Variants on Wikipedia
 * @link https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid Windows GUID structure
 * @link https://docs.microsoft.com/en-us/dotnet/api/system.guid .NET Guid Struct
 * @link https://docs.microsoft.com/en-us/dotnet/api/system.guid.tobytearray .NET Guid.ToByteArray Method
 *
 * @psalm-immutable
 */
final class Guid extends Uuid implements UuidInterface
{
    public function __construct(
        Fields $fields,
        NumberConverterInterface $numberConverter,
        CodecInterface $codec,
        TimeConverterInterface $timeConverter
    ) {
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
uuid/src/Codec/OrderedTimeCodec.php000064400000007056147361033650013210 0ustar00<?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\Codec;

use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;

use function strlen;
use function substr;

/**
 * OrderedTimeCodec encodes and decodes a UUID, optimizing the byte order for
 * more efficient storage
 *
 * For binary representations of version 1 UUID, this codec may be used to
 * reorganize the time fields, making the UUID closer to sequential when storing
 * the bytes. According to Percona, this optimization can improve database
 * INSERTs and SELECTs using the UUID column as a key.
 *
 * The string representation of the UUID will remain unchanged. Only the binary
 * representation is reordered.
 *
 * **PLEASE NOTE:** Binary representations of UUIDs encoded with this codec must
 * be decoded with this codec. Decoding using another codec can result in
 * malformed UUIDs.
 *
 * @link https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ Storing UUID Values in MySQL
 *
 * @psalm-immutable
 */
class OrderedTimeCodec extends StringCodec
{
    /**
     * Returns a binary string representation of a UUID, with the timestamp
     * fields rearranged for optimized storage
     *
     * @inheritDoc
     * @psalm-return non-empty-string
     * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
     * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
     */
    public function encodeBinary(UuidInterface $uuid): string
    {
        if (
            !($uuid->getFields() instanceof Rfc4122FieldsInterface)
            || $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
        ) {
            throw new InvalidArgumentException(
                'Expected RFC 4122 version 1 (time-based) UUID'
            );
        }

        $bytes = $uuid->getFields()->getBytes();

        return $bytes[6] . $bytes[7]
            . $bytes[4] . $bytes[5]
            . $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3]
            . substr($bytes, 8);
    }

    /**
     * Returns a UuidInterface derived from an ordered-time binary string
     * representation
     *
     * @throws InvalidArgumentException if $bytes is an invalid length
     *
     * @inheritDoc
     */
    public function decodeBytes(string $bytes): UuidInterface
    {
        if (strlen($bytes) !== 16) {
            throw new InvalidArgumentException(
                '$bytes string should contain 16 characters.'
            );
        }

        // Rearrange the bytes to their original order.
        $rearrangedBytes = $bytes[4] . $bytes[5] . $bytes[6] . $bytes[7]
            . $bytes[2] . $bytes[3]
            . $bytes[0] . $bytes[1]
            . substr($bytes, 8);

        $uuid = parent::decodeBytes($rearrangedBytes);

        if (
            !($uuid->getFields() instanceof Rfc4122FieldsInterface)
            || $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
        ) {
            throw new UnsupportedOperationException(
                'Attempting to decode a non-time-based UUID using '
                . 'OrderedTimeCodec'
            );
        }

        return $uuid;
    }
}
uuid/src/Codec/GuidStringCodec.php000064400000002457147361033650013064 0ustar00<?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\Codec;

use Ramsey\Uuid\Guid\Guid;
use Ramsey\Uuid\UuidInterface;

use function bin2hex;
use function substr;

/**
 * GuidStringCodec encodes and decodes globally unique identifiers (GUID)
 *
 * @see Guid
 *
 * @psalm-immutable
 */
class GuidStringCodec extends StringCodec
{
    public function decode(string $encodedUuid): UuidInterface
    {
        $bytes = $this->getBytes($encodedUuid);

        return $this->getBuilder()->build($this, $this->swapBytes($bytes));
    }

    public function decodeBytes(string $bytes): UuidInterface
    {
        // Specifically call parent::decode to preserve correct byte order
        return parent::decode(bin2hex($bytes));
    }

    /**
     * Swaps bytes according to the GUID rules
     */
    private function swapBytes(string $bytes): string
    {
        return $bytes[3] . $bytes[2] . $bytes[1] . $bytes[0]
            . $bytes[5] . $bytes[4]
            . $bytes[7] . $bytes[6]
            . substr($bytes, 8);
    }
}
uuid/src/Codec/CodecInterface.php000064400000004022147361033650012673 0ustar00<?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\Codec;

use Ramsey\Uuid\UuidInterface;

/**
 * A codec encodes and decodes a UUID according to defined rules
 *
 * @psalm-immutable
 */
interface CodecInterface
{
    /**
     * Returns a hexadecimal string representation of a UuidInterface
     *
     * @param UuidInterface $uuid The UUID for which to create a hexadecimal
     *     string representation
     *
     * @return string Hexadecimal string representation of a UUID
     *
     * @psalm-return non-empty-string
     */
    public function encode(UuidInterface $uuid): string;

    /**
     * Returns a binary string representation of a UuidInterface
     *
     * @param UuidInterface $uuid The UUID for which to create a binary string
     *     representation
     *
     * @return string Binary string representation of a UUID
     *
     * @psalm-return non-empty-string
     */
    public function encodeBinary(UuidInterface $uuid): string;

    /**
     * Returns a UuidInterface derived from a hexadecimal string representation
     *
     * @param string $encodedUuid The hexadecimal string representation to
     *     convert into a UuidInterface instance
     *
     * @return UuidInterface An instance of a UUID decoded from a hexadecimal
     *     string representation
     */
    public function decode(string $encodedUuid): UuidInterface;

    /**
     * Returns a UuidInterface derived from a binary string representation
     *
     * @param string $bytes The binary string representation to convert into a
     *     UuidInterface instance
     *
     * @return UuidInterface An instance of a UUID decoded from a binary string
     *     representation
     */
    public function decodeBytes(string $bytes): UuidInterface;
}
uuid/src/Codec/StringCodec.php000064400000006756147361033650012261 0ustar00<?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\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 hex2bin;
use function implode;
use function str_replace;
use function strlen;
use function substr;

/**
 * StringCodec encodes and decodes RFC 4122 UUIDs
 *
 * @link http://tools.ietf.org/html/rfc4122
 *
 * @psalm-immutable
 */
class StringCodec implements CodecInterface
{
    /**
     * @var UuidBuilderInterface
     */
    private $builder;

    /**
     * Constructs a StringCodec
     *
     * @param UuidBuilderInterface $builder The builder to use when encoding UUIDs
     */
    public function __construct(UuidBuilderInterface $builder)
    {
        $this->builder = $builder;
    }

    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();
    }

    /**
     * @psalm-return non-empty-string
     * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
     * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
     */
    public function encodeBinary(UuidInterface $uuid): string
    {
        return $uuid->getFields()->getBytes();
    }

    /**
     * @throws InvalidUuidStringException
     *
     * @inheritDoc
     */
    public function decode(string $encodedUuid): UuidInterface
    {
        return $this->builder->build($this, $this->getBytes($encodedUuid));
    }

    public function decodeBytes(string $bytes): UuidInterface
    {
        if (strlen($bytes) !== 16) {
            throw new InvalidArgumentException(
                '$bytes string should contain 16 characters.'
            );
        }

        return $this->builder->build($this, $bytes);
    }

    /**
     * Returns the UUID builder
     */
    protected function getBuilder(): UuidBuilderInterface
    {
        return $this->builder;
    }

    /**
     * Returns a byte string of the UUID
     */
    protected function getBytes(string $encodedUuid): string
    {
        $parsedUuid = str_replace(
            ['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}', '-'],
            '',
            $encodedUuid
        );

        $components = [
            substr($parsedUuid, 0, 8),
            substr($parsedUuid, 8, 4),
            substr($parsedUuid, 12, 4),
            substr($parsedUuid, 16, 4),
            substr($parsedUuid, 20),
        ];

        if (!Uuid::isValid(implode('-', $components))) {
            throw new InvalidUuidStringException(
                'Invalid UUID string: ' . $encodedUuid
            );
        }

        return (string) hex2bin($parsedUuid);
    }
}
uuid/src/Codec/TimestampLastCombCodec.php000064400000003116147361033650014366 0ustar00<?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\Codec;

/**
 * TimestampLastCombCodec encodes and decodes COMBs, with the timestamp as the
 * last 48 bits
 *
 * The CombGenerator when used with the StringCodec (and, by proxy, the
 * TimestampLastCombCodec) adds the timestamp to the last 48 bits of the COMB.
 * The TimestampLastCombCodec is provided for the sake of consistency. In
 * practice, it is identical to the standard StringCodec but, it may be used
 * with the CombGenerator for additional context when reading code.
 *
 * Consider the following code. By default, the codec used by UuidFactory is the
 * StringCodec, but here, we explicitly set the TimestampLastCombCodec. It is
 * redundant, but it is clear that we intend this COMB to be generated with the
 * timestamp appearing at the end.
 *
 * ``` php
 * $factory = new UuidFactory();
 *
 * $factory->setCodec(new TimestampLastCombCodec($factory->getUuidBuilder()));
 *
 * $factory->setRandomGenerator(new CombGenerator(
 *     $factory->getRandomGenerator(),
 *     $factory->getNumberConverter()
 * ));
 *
 * $timestampLastComb = $factory->uuid4();
 * ```
 *
 * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
 *
 * @psalm-immutable
 */
class TimestampLastCombCodec extends StringCodec
{
}
uuid/src/Codec/TimestampFirstCombCodec.php000064400000006356147361033650014563 0ustar00<?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\Codec;

use Ramsey\Uuid\Exception\InvalidUuidStringException;
use Ramsey\Uuid\UuidInterface;

use function bin2hex;
use function sprintf;
use function substr;
use function substr_replace;

/**
 * TimestampFirstCombCodec encodes and decodes COMBs, with the timestamp as the
 * first 48 bits
 *
 * In contrast with the TimestampLastCombCodec, the TimestampFirstCombCodec
 * adds the timestamp to the first 48 bits of the COMB. To generate a
 * timestamp-first COMB, set the TimestampFirstCombCodec as the codec, along
 * with the CombGenerator as the random generator.
 *
 * ``` php
 * $factory = new UuidFactory();
 *
 * $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder()));
 *
 * $factory->setRandomGenerator(new CombGenerator(
 *     $factory->getRandomGenerator(),
 *     $factory->getNumberConverter()
 * ));
 *
 * $timestampFirstComb = $factory->uuid4();
 * ```
 *
 * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
 *
 * @psalm-immutable
 */
class TimestampFirstCombCodec extends StringCodec
{
    /**
     * @psalm-return non-empty-string
     * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
     * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
     */
    public function encode(UuidInterface $uuid): string
    {
        $bytes = $this->swapBytes($uuid->getFields()->getBytes());

        return sprintf(
            '%08s-%04s-%04s-%04s-%012s',
            bin2hex(substr($bytes, 0, 4)),
            bin2hex(substr($bytes, 4, 2)),
            bin2hex(substr($bytes, 6, 2)),
            bin2hex(substr($bytes, 8, 2)),
            bin2hex(substr($bytes, 10))
        );
    }

    /**
     * @psalm-return non-empty-string
     * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
     * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
     */
    public function encodeBinary(UuidInterface $uuid): string
    {
        return $this->swapBytes($uuid->getFields()->getBytes());
    }

    /**
     * @throws InvalidUuidStringException
     *
     * @inheritDoc
     */
    public function decode(string $encodedUuid): UuidInterface
    {
        $bytes = $this->getBytes($encodedUuid);

        return $this->getBuilder()->build($this, $this->swapBytes($bytes));
    }

    public function decodeBytes(string $bytes): UuidInterface
    {
        return $this->getBuilder()->build($this, $this->swapBytes($bytes));
    }

    /**
     * Swaps bytes according to the timestamp-first COMB rules
     */
    private function swapBytes(string $bytes): string
    {
        $first48Bits = substr($bytes, 0, 6);
        $last48Bits = substr($bytes, -6);

        $bytes = substr_replace($bytes, $last48Bits, 0, 6);
        $bytes = substr_replace($bytes, $first48Bits, -6);

        return $bytes;
    }
}
uuid/src/Type/Time.php000064400000005205147361033650010643 0ustar00<?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\Type;

use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use stdClass;

use function json_decode;
use function json_encode;

/**
 * A value object representing a timestamp
 *
 * This class exists for type-safety purposes, to ensure that timestamps used
 * by ramsey/uuid are truly timestamp integers and not some other kind of string
 * or integer.
 *
 * @psalm-immutable
 */
final class Time implements TypeInterface
{
    /**
     * @var IntegerObject
     */
    private $seconds;

    /**
     * @var IntegerObject
     */
    private $microseconds;

    /**
     * @param mixed $seconds
     * @param mixed $microseconds
     */
    public function __construct($seconds, $microseconds = 0)
    {
        $this->seconds = new IntegerObject($seconds);
        $this->microseconds = new IntegerObject($microseconds);
    }

    public function getSeconds(): IntegerObject
    {
        return $this->seconds;
    }

    public function getMicroseconds(): IntegerObject
    {
        return $this->microseconds;
    }

    public function toString(): string
    {
        return $this->seconds->toString() . '.' . $this->microseconds->toString();
    }

    public function __toString(): string
    {
        return $this->toString();
    }

    /**
     * @return string[]
     */
    public function jsonSerialize(): array
    {
        return [
            'seconds' => $this->getSeconds()->toString(),
            'microseconds' => $this->getMicroseconds()->toString(),
        ];
    }

    public function serialize(): string
    {
        return (string) json_encode($this);
    }

    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $serialized The serialized string representation of the object
     *
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     */
    public function unserialize($serialized): void
    {
        /** @var stdClass $time */
        $time = json_decode($serialized);

        if (!isset($time->seconds) || !isset($time->microseconds)) {
            throw new UnsupportedOperationException(
                'Attempted to unserialize an invalid value'
            );
        }

        $this->__construct($time->seconds, $time->microseconds);
    }
}
uuid/src/Type/Decimal.php000064400000005073147361033650011306 0ustar00<?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\Type;

use Ramsey\Uuid\Exception\InvalidArgumentException;

use function is_numeric;

/**
 * A value object representing a decimal
 *
 * This class exists for type-safety purposes, to ensure that decimals
 * returned from ramsey/uuid methods as strings are truly decimals and not some
 * other kind of string.
 *
 * To support values as true decimals and not as floats or doubles, we store the
 * decimals as strings.
 *
 * @psalm-immutable
 */
final class Decimal implements NumberInterface
{
    /**
     * @var string
     */
    private $value;

    /**
     * @var bool
     */
    private $isNegative = false;

    /**
     * @param mixed $value The decimal value to store
     */
    public function __construct($value)
    {
        $value = (string) $value;

        if (!is_numeric($value)) {
            throw new InvalidArgumentException(
                'Value must be a signed decimal or a string containing only '
                . 'digits 0-9 and, optionally, a decimal point or sign (+ or -)'
            );
        }

        // Remove the leading +-symbol.
        if (strpos($value, '+') === 0) {
            $value = substr($value, 1);
        }

        // For cases like `-0` or `-0.0000`, convert the value to `0`.
        if (abs((float) $value) === 0.0) {
            $value = '0';
        }

        if (strpos($value, '-') === 0) {
            $this->isNegative = true;
        }

        $this->value = $value;
    }

    public function isNegative(): bool
    {
        return $this->isNegative;
    }

    public function toString(): string
    {
        return $this->value;
    }

    public function __toString(): string
    {
        return $this->toString();
    }

    public function jsonSerialize(): string
    {
        return $this->toString();
    }

    public function serialize(): string
    {
        return $this->toString();
    }

    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $serialized The serialized string representation of the object
     *
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     */
    public function unserialize($serialized): void
    {
        $this->__construct($serialized);
    }
}
uuid/src/Type/NumberInterface.php000064400000001173147361033650013016 0ustar00<?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\Type;

/**
 * NumberInterface ensures consistency in numeric values returned by ramsey/uuid
 *
 * @psalm-immutable
 */
interface NumberInterface extends TypeInterface
{
    /**
     * Returns true if this number is less than zero
     */
    public function isNegative(): bool;
}
uuid/src/Type/Integer.php000064400000005641147361033650011346 0ustar00<?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\Type;

use Ramsey\Uuid\Exception\InvalidArgumentException;

use function ctype_digit;
use function ltrim;
use function strpos;
use function substr;

/**
 * A value object representing an integer
 *
 * This class exists for type-safety purposes, to ensure that integers
 * returned from ramsey/uuid methods as strings are truly integers and not some
 * other kind of string.
 *
 * To support large integers beyond PHP_INT_MAX and PHP_INT_MIN on both 64-bit
 * and 32-bit systems, we store the integers as strings.
 *
 * @psalm-immutable
 */
final class Integer implements NumberInterface
{
    /**
     * @var string
     */
    private $value;

    /**
     * @var bool
     */
    private $isNegative = false;

    /**
     * @param mixed $value The integer value to store
     */
    public function __construct($value)
    {
        $value = (string) $value;
        $sign = '+';

        // If the value contains a sign, remove it for ctype_digit() check.
        if (strpos($value, '-') === 0 || strpos($value, '+') === 0) {
            $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;
        }

        $this->value = $value;
    }

    public function isNegative(): bool
    {
        return $this->isNegative;
    }

    public function toString(): string
    {
        return $this->value;
    }

    public function __toString(): string
    {
        return $this->toString();
    }

    public function jsonSerialize(): string
    {
        return $this->toString();
    }

    public function serialize(): string
    {
        return $this->toString();
    }

    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $serialized The serialized string representation of the object
     *
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     */
    public function unserialize($serialized): void
    {
        $this->__construct($serialized);
    }
}
uuid/src/Type/Hexadecimal.php000064400000004045147361033650012152 0ustar00<?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\Type;

use Ramsey\Uuid\Exception\InvalidArgumentException;

use function ctype_xdigit;
use function strpos;
use function strtolower;
use function substr;

/**
 * A value object representing a hexadecimal number
 *
 * This class exists for type-safety purposes, to ensure that hexadecimal numbers
 * returned from ramsey/uuid methods as strings are truly hexadecimal and not some
 * other kind of string.
 *
 * @psalm-immutable
 */
final class Hexadecimal implements TypeInterface
{
    /**
     * @var string
     */
    private $value;

    /**
     * @param string $value The hexadecimal value to store
     */
    public function __construct(string $value)
    {
        $value = strtolower($value);

        if (strpos($value, '0x') === 0) {
            $value = substr($value, 2);
        }

        if (!ctype_xdigit($value)) {
            throw new InvalidArgumentException(
                'Value must be a hexadecimal number'
            );
        }

        $this->value = $value;
    }

    public function toString(): string
    {
        return $this->value;
    }

    public function __toString(): string
    {
        return $this->toString();
    }

    public function jsonSerialize(): string
    {
        return $this->toString();
    }

    public function serialize(): string
    {
        return $this->toString();
    }

    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $serialized The serialized string representation of the object
     *
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     */
    public function unserialize($serialized): void
    {
        $this->__construct($serialized);
    }
}
uuid/src/Type/TypeInterface.php000064400000001225147361033650012505 0ustar00<?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\Type;

use JsonSerializable;
use Serializable;

/**
 * TypeInterface ensures consistency in typed values returned by ramsey/uuid
 *
 * @psalm-immutable
 */
interface TypeInterface extends JsonSerializable, Serializable
{
    public function toString(): string;

    public function __toString(): string;
}
uuid/src/DeprecatedUuidMethodsTrait.php000064400000032061147361033650014243 0ustar00<?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;

use DateTimeImmutable;
use DateTimeInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Throwable;

use function str_pad;
use function substr;

use const STR_PAD_LEFT;

/**
 * This trait encapsulates deprecated methods for ramsey/uuid; this trait and
 * its methods will be removed in ramsey/uuid 5.0.0.
 *
 * @psalm-immutable
 */
trait DeprecatedUuidMethodsTrait
{
    /**
     * @var Rfc4122FieldsInterface
     */
    protected $fields;

    /**
     * @var NumberConverterInterface
     */
    protected $numberConverter;

    /**
     * @var TimeConverterInterface
     */
    protected $timeConverter;

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
     *     and use the arbitrary-precision math library of your choice to
     *     convert it to a string integer.
     */
    public function getClockSeqHiAndReserved(): string
    {
        return $this->numberConverter->fromHex($this->fields->getClockSeqHiAndReserved()->toString());
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}.
     */
    public function getClockSeqHiAndReservedHex(): string
    {
        return $this->fields->getClockSeqHiAndReserved()->toString();
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}
     *     and use the arbitrary-precision math library of your choice to
     *     convert it to a string integer.
     */
    public function getClockSeqLow(): string
    {
        return $this->numberConverter->fromHex($this->fields->getClockSeqLow()->toString());
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}.
     */
    public function getClockSeqLowHex(): string
    {
        return $this->fields->getClockSeqLow()->toString();
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}
     *     and use the arbitrary-precision math library of your choice to
     *     convert it to a string integer.
     */
    public function getClockSequence(): string
    {
        return $this->numberConverter->fromHex($this->fields->getClockSeq()->toString());
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}.
     */
    public function getClockSequenceHex(): string
    {
        return $this->fields->getClockSeq()->toString();
    }

    /**
     * @deprecated This method will be removed in 5.0.0. There is no alternative
     *     recommendation, so plan accordingly.
     */
    public function getNumberConverter(): NumberConverterInterface
    {
        return $this->numberConverter;
    }

    /**
     * @deprecated In ramsey/uuid version 5.0.0, this will be removed.
     *     It is available at {@see UuidV1::getDateTime()}.
     *
     * @return DateTimeImmutable An immutable instance of DateTimeInterface
     *
     * @throws UnsupportedOperationException if UUID is not time-based
     * @throws DateTimeException if DateTime throws an exception/error
     */
    public function getDateTime(): DateTimeInterface
    {
        if ($this->fields->getVersion() !== 1) {
            throw new UnsupportedOperationException('Not a time-based UUID');
        }

        $time = $this->timeConverter->convertTime($this->fields->getTimestamp());

        try {
            return new DateTimeImmutable(
                '@'
                . $time->getSeconds()->toString()
                . '.'
                . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
            );
        } catch (Throwable $e) {
            throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance.
     *
     * @return string[]
     */
    public function getFieldsHex(): array
    {
        return [
            'time_low' => $this->fields->getTimeLow()->toString(),
            'time_mid' => $this->fields->getTimeMid()->toString(),
            'time_hi_and_version' => $this->fields->getTimeHiAndVersion()->toString(),
            'clock_seq_hi_and_reserved' => $this->fields->getClockSeqHiAndReserved()->toString(),
            'clock_seq_low' => $this->fields->getClockSeqLow()->toString(),
            'node' => $this->fields->getNode()->toString(),
        ];
    }

    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct
     *     alternative, but the same information may be obtained by splitting
     *     in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getLeastSignificantBits(): string
    {
        $leastSignificantHex = substr($this->getHex()->toString(), 16);

        return $this->numberConverter->fromHex($leastSignificantHex);
    }

    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct
     *     alternative, but the same information may be obtained by splitting
     *     in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getLeastSignificantBitsHex(): string
    {
        return substr($this->getHex()->toString(), 16);
    }

    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct
     *     alternative, but the same information may be obtained by splitting
     *     in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getMostSignificantBits(): string
    {
        $mostSignificantHex = substr($this->getHex()->toString(), 0, 16);

        return $this->numberConverter->fromHex($mostSignificantHex);
    }

    /**
     * @deprecated This method will be removed in 5.0.0. There is no direct
     *     alternative, but the same information may be obtained by splitting
     *     in half the value returned by {@see UuidInterface::getHex()}.
     */
    public function getMostSignificantBitsHex(): string
    {
        return substr($this->getHex()->toString(), 0, 16);
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getNode()}
     *     and use the arbitrary-precision math library of your choice to
     *     convert it to a string integer.
     */
    public function getNode(): string
    {
        return $this->numberConverter->fromHex($this->fields->getNode()->toString());
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getNode()}.
     */
    public function getNodeHex(): string
    {
        return $this->fields->getNode()->toString();
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}
     *     and use the arbitrary-precision math library of your choice to
     *     convert it to a string integer.
     */
    public function getTimeHiAndVersion(): string
    {
        return $this->numberConverter->fromHex($this->fields->getTimeHiAndVersion()->toString());
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}.
     */
    public function getTimeHiAndVersionHex(): string
    {
        return $this->fields->getTimeHiAndVersion()->toString();
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}
     *     and use the arbitrary-precision math library of your choice to
     *     convert it to a string integer.
     */
    public function getTimeLow(): string
    {
        return $this->numberConverter->fromHex($this->fields->getTimeLow()->toString());
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}.
     */
    public function getTimeLowHex(): string
    {
        return $this->fields->getTimeLow()->toString();
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}
     *     and use the arbitrary-precision math library of your choice to
     *     convert it to a string integer.
     */
    public function getTimeMid(): string
    {
        return $this->numberConverter->fromHex($this->fields->getTimeMid()->toString());
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}.
     */
    public function getTimeMidHex(): string
    {
        return $this->fields->getTimeMid()->toString();
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}
     *     and use the arbitrary-precision math library of your choice to
     *     convert it to a string integer.
     */
    public function getTimestamp(): string
    {
        if ($this->fields->getVersion() !== 1) {
            throw new UnsupportedOperationException('Not a time-based UUID');
        }

        return $this->numberConverter->fromHex($this->fields->getTimestamp()->toString());
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
     *     instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}.
     */
    public function getTimestampHex(): string
    {
        if ($this->fields->getVersion() !== 1) {
            throw new UnsupportedOperationException('Not a time-based UUID');
        }

        return $this->fields->getTimestamp()->toString();
    }

    /**
     * @deprecated This has moved to {@see Rfc4122FieldsInterface::getUrn()} and
     *     is available on {@see \Ramsey\Uuid\Rfc4122\UuidV1},
     *     {@see \Ramsey\Uuid\Rfc4122\UuidV3}, {@see \Ramsey\Uuid\Rfc4122\UuidV4},
     *     and {@see \Ramsey\Uuid\Rfc4122\UuidV5}.
     */
    public function getUrn(): string
    {
        return 'urn:uuid:' . $this->toString();
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
     */
    public function getVariant(): ?int
    {
        return $this->fields->getVariant();
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a
     *     {@see FieldsInterface} instance. If it is a
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
     *     {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
     */
    public function getVersion(): ?int
    {
        return $this->fields->getVersion();
    }
}
uuid/src/Generator/RandomGeneratorInterface.php000064400000001327147361033650015663 0ustar00<?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\Generator;

/**
 * A random generator generates strings of random binary data
 */
interface RandomGeneratorInterface
{
    /**
     * Generates a string of randomized binary data
     *
     * @param int $length The number of bytes of random binary data to generate
     *
     * @return string A binary string
     */
    public function generate(int $length): string;
}
uuid/src/Generator/TimeGeneratorFactory.php000064400000002746147361033650015056 0ustar00<?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\Generator;

use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Provider\TimeProviderInterface;

/**
 * TimeGeneratorFactory retrieves a default time generator, based on the
 * environment
 */
class TimeGeneratorFactory
{
    /**
     * @var NodeProviderInterface
     */
    private $nodeProvider;

    /**
     * @var TimeConverterInterface
     */
    private $timeConverter;

    /**
     * @var TimeProviderInterface
     */
    private $timeProvider;

    public function __construct(
        NodeProviderInterface $nodeProvider,
        TimeConverterInterface $timeConverter,
        TimeProviderInterface $timeProvider
    ) {
        $this->nodeProvider = $nodeProvider;
        $this->timeConverter = $timeConverter;
        $this->timeProvider = $timeProvider;
    }

    /**
     * Returns a default time generator, based on the current environment
     */
    public function getGenerator(): TimeGeneratorInterface
    {
        return new DefaultTimeGenerator(
            $this->nodeProvider,
            $this->timeConverter,
            $this->timeProvider
        );
    }
}
uuid/src/Generator/NameGeneratorFactory.php000064400000001272147361033650015031 0ustar00<?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\Generator;

/**
 * NameGeneratorFactory retrieves a default name generator, based on the
 * environment
 */
class NameGeneratorFactory
{
    /**
     * Returns a default name generator, based on the current environment
     */
    public function getGenerator(): NameGeneratorInterface
    {
        return new DefaultNameGenerator();
    }
}
uuid/src/Generator/PeclUuidRandomGenerator.php000064400000001363147361033650015475 0ustar00<?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\Generator;

use const UUID_TYPE_RANDOM;

/**
 * PeclUuidRandomGenerator generates strings of random binary data using ext-uuid
 *
 * @link https://pecl.php.net/package/uuid ext-uuid
 */
class PeclUuidRandomGenerator implements RandomGeneratorInterface
{
    public function generate(int $length): string
    {
        $uuid = uuid_create(UUID_TYPE_RANDOM);

        return uuid_parse($uuid);
    }
}
uuid/src/Generator/RandomLibAdapter.php000064400000002576147361033650014132 0ustar00<?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\Generator;

use RandomLib\Factory;
use RandomLib\Generator;

/**
 * RandomLibAdapter generates strings of random binary data using the
 * paragonie/random-lib library
 *
 * @link https://packagist.org/packages/paragonie/random-lib paragonie/random-lib
 */
class RandomLibAdapter implements RandomGeneratorInterface
{
    /**
     * @var Generator
     */
    private $generator;

    /**
     * Constructs a RandomLibAdapter
     *
     * By default, if no Generator is passed in, this creates a high-strength
     * generator to use when generating random binary data.
     *
     * @param Generator|null $generator The generator to use when generating binary data
     */
    public function __construct(?Generator $generator = null)
    {
        if ($generator === null) {
            $factory = new Factory();
            $generator = $factory->getHighStrengthGenerator();
        }

        $this->generator = $generator;
    }

    public function generate(int $length): string
    {
        return $this->generator->generate($length);
    }
}
uuid/src/Generator/CombGenerator.php000064400000006577147361033650013516 0ustar00<?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\Generator;

use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Exception\InvalidArgumentException;

use function bin2hex;
use function explode;
use function hex2bin;
use function microtime;
use function str_pad;
use function substr;

use const STR_PAD_LEFT;

/**
 * CombGenerator generates COMBs (combined UUID/timestamp)
 *
 * The CombGenerator, when used with the StringCodec (and, by proxy, the
 * TimestampLastCombCodec) or the TimestampFirstCombCodec, combines the current
 * timestamp with a UUID (hence the name "COMB"). The timestamp either appears
 * as the first or last 48 bits of the COMB, depending on the codec used.
 *
 * By default, COMBs will have the timestamp set as the last 48 bits of the
 * identifier.
 *
 * ``` php
 * $factory = new UuidFactory();
 *
 * $factory->setRandomGenerator(new CombGenerator(
 *     $factory->getRandomGenerator(),
 *     $factory->getNumberConverter()
 * ));
 *
 * $comb = $factory->uuid4();
 * ```
 *
 * To generate a COMB with the timestamp as the first 48 bits, set the
 * TimestampFirstCombCodec as the codec.
 *
 * ``` php
 * $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder()));
 * ```
 *
 * @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
 */
class CombGenerator implements RandomGeneratorInterface
{
    public const TIMESTAMP_BYTES = 6;

    /**
     * @var RandomGeneratorInterface
     */
    private $randomGenerator;

    /**
     * @var NumberConverterInterface
     */
    private $converter;

    public function __construct(
        RandomGeneratorInterface $generator,
        NumberConverterInterface $numberConverter
    ) {
        $this->converter = $numberConverter;
        $this->randomGenerator = $generator;
    }

    /**
     * @throws InvalidArgumentException if $length is not a positive integer
     *     greater than or equal to CombGenerator::TIMESTAMP_BYTES
     *
     * @inheritDoc
     */
    public function generate(int $length): string
    {
        if ($length < self::TIMESTAMP_BYTES || $length < 0) {
            throw new InvalidArgumentException(
                'Length must be a positive integer greater than or equal to ' . self::TIMESTAMP_BYTES
            );
        }

        $hash = '';
        if (self::TIMESTAMP_BYTES > 0 && $length > self::TIMESTAMP_BYTES) {
            $hash = $this->randomGenerator->generate($length - self::TIMESTAMP_BYTES);
        }

        $lsbTime = str_pad(
            $this->converter->toHex($this->timestamp()),
            self::TIMESTAMP_BYTES * 2,
            '0',
            STR_PAD_LEFT
        );

        return (string) hex2bin(
            str_pad(
                bin2hex((string) $hash),
                $length - self::TIMESTAMP_BYTES,
                '0'
            )
            . $lsbTime
        );
    }

    /**
     * Returns current timestamp a string integer, precise to 0.00001 seconds
     */
    private function timestamp(): string
    {
        $time = explode(' ', microtime(false));

        return $time[1] . substr($time[0], 2, 5);
    }
}
uuid/src/Generator/RandomGeneratorFactory.php000064400000001304147361033650015365 0ustar00<?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\Generator;

/**
 * RandomGeneratorFactory retrieves a default random generator, based on the
 * environment
 */
class RandomGeneratorFactory
{
    /**
     * Returns a default random generator, based on the current environment
     */
    public function getGenerator(): RandomGeneratorInterface
    {
        return new RandomBytesGenerator();
    }
}
uuid/src/Generator/MtRandGenerator.php000064400000002220147361033650014000 0ustar00<?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
 * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
 * @link https://packagist.org/packages/ramsey/uuid Packagist
 * @link https://github.com/ramsey/uuid GitHub
 */

namespace Ramsey\Uuid\Generator;

/**
 * MtRandRandomGenerator provides functionality to generate strings of random
 * binary data using the `mt_rand()` PHP function
 *
 * @link http://php.net/mt_rand
 */
class MtRandGenerator implements RandomGeneratorInterface
{
    /**
     * Generates a string of random binary data of the specified length
     *
     * @param integer $length The number of bytes of random binary data to generate
     * @return string A binary string
     */
    public function generate($length)
    {
        $bytes = '';

        for ($i = 1; $i <= $length; $i++) {
            $bytes = chr(mt_rand(0, 255)) . $bytes;
        }

        return $bytes;
    }
}
uuid/src/Generator/DefaultNameGenerator.php000064400000002144147361033650015005 0ustar00<?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\Generator;

use Ramsey\Uuid\Exception\NameException;
use Ramsey\Uuid\UuidInterface;

use function hash;

/**
 * DefaultNameGenerator generates strings of binary data based on a namespace,
 * name, and hashing algorithm
 */
class DefaultNameGenerator implements NameGeneratorInterface
{
    /** @psalm-pure */
    public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string
    {
        /** @var string|bool $bytes */
        $bytes = @hash($hashAlgorithm, $ns->getBytes() . $name, true);

        if ($bytes === false) {
            throw new NameException(sprintf(
                'Unable to hash namespace and name with algorithm \'%s\'',
                $hashAlgorithm
            ));
        }

        return (string) $bytes;
    }
}
uuid/src/Generator/DceSecurityGeneratorInterface.php000064400000003324147361033650016665 0ustar00<?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\Generator;

use Ramsey\Uuid\Rfc4122\UuidV2;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;

/**
 * A DCE Security generator generates strings of binary data based on a local
 * domain, local identifier, node ID, clock sequence, and the current time
 *
 * @see UuidV2
 */
interface DceSecurityGeneratorInterface
{
    /**
     * Generate a binary string from a local domain, local identifier, node ID,
     * clock sequence, and current time
     *
     * @param int $localDomain The local domain to use when generating bytes,
     *     according to DCE Security
     * @param IntegerObject|null $localIdentifier The local identifier for the
     *     given domain; this may be a UID or GID on POSIX systems, if the local
     *     domain is person or group, or it may be a site-defined identifier
     *     if the local domain is org
     * @param Hexadecimal|null $node A 48-bit number representing the hardware
     *     address
     * @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
     *
     * @return string A binary string
     */
    public function generate(
        int $localDomain,
        ?IntegerObject $localIdentifier = null,
        ?Hexadecimal $node = null,
        ?int $clockSeq = null
    ): string;
}
uuid/src/Generator/SodiumRandomGenerator.php000064400000002161147361033650015220 0ustar00<?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
 * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
 * @link https://packagist.org/packages/ramsey/uuid Packagist
 * @link https://github.com/ramsey/uuid GitHub
 */

namespace Ramsey\Uuid\Generator;

/**
 * SodiumRandomGenerator provides functionality to generate strings of random
 * binary data using the PECL libsodium extension
 *
 * @link http://pecl.php.net/package/libsodium
 * @link https://paragonie.com/book/pecl-libsodium
 */
class SodiumRandomGenerator implements RandomGeneratorInterface
{
    /**
     * Generates a string of random binary data of the specified length
     *
     * @param integer $length The number of bytes of random binary data to generate
     * @return string A binary string
     */
    public function generate($length)
    {
        return \Sodium\randombytes_buf($length);
    }
}
uuid/src/Generator/RandomBytesGenerator.php000064400000002152147361033650015046 0ustar00<?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\Generator;

use Ramsey\Uuid\Exception\RandomSourceException;

/**
 * RandomBytesGenerator generates strings of random binary data using the
 * built-in `random_bytes()` PHP function
 *
 * @link http://php.net/random_bytes random_bytes()
 */
class RandomBytesGenerator implements RandomGeneratorInterface
{
    /**
     * @throws RandomSourceException if random_bytes() throws an exception/error
     *
     * @inheritDoc
     */
    public function generate(int $length): string
    {
        try {
            return random_bytes($length);
        } catch (\Throwable $exception) {
            throw new RandomSourceException(
                $exception->getMessage(),
                (int) $exception->getCode(),
                $exception
            );
        }
    }
}
uuid/src/Generator/DceSecurityGenerator.php000064400000011427147361033650015047 0ustar00<?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\Generator;

use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Exception\DceSecurityException;
use Ramsey\Uuid\Provider\DceSecurityProviderInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Uuid;

use function hex2bin;
use function in_array;
use function pack;
use function str_pad;
use function strlen;
use function substr_replace;

use const STR_PAD_LEFT;

/**
 * DceSecurityGenerator generates strings of binary data based on a local
 * domain, local identifier, node ID, clock sequence, and the current time
 */
class DceSecurityGenerator implements DceSecurityGeneratorInterface
{
    private const DOMAINS = [
        Uuid::DCE_DOMAIN_PERSON,
        Uuid::DCE_DOMAIN_GROUP,
        Uuid::DCE_DOMAIN_ORG,
    ];

    /**
     * Upper bounds for the clock sequence in DCE Security UUIDs.
     */
    private const CLOCK_SEQ_HIGH = 63;

    /**
     * Lower bounds for the clock sequence in DCE Security UUIDs.
     */
    private const CLOCK_SEQ_LOW = 0;

    /**
     * @var NumberConverterInterface
     */
    private $numberConverter;

    /**
     * @var TimeGeneratorInterface
     */
    private $timeGenerator;

    /**
     * @var DceSecurityProviderInterface
     */
    private $dceSecurityProvider;

    public function __construct(
        NumberConverterInterface $numberConverter,
        TimeGeneratorInterface $timeGenerator,
        DceSecurityProviderInterface $dceSecurityProvider
    ) {
        $this->numberConverter = $numberConverter;
        $this->timeGenerator = $timeGenerator;
        $this->dceSecurityProvider = $dceSecurityProvider;
    }

    public function generate(
        int $localDomain,
        ?IntegerObject $localIdentifier = null,
        ?Hexadecimal $node = null,
        ?int $clockSeq = null
    ): string {
        if (!in_array($localDomain, self::DOMAINS)) {
            throw new DceSecurityException(
                'Local domain must be a valid DCE Security domain'
            );
        }

        if ($localIdentifier && $localIdentifier->isNegative()) {
            throw new DceSecurityException(
                'Local identifier out of bounds; it must be a value between 0 and 4294967295'
            );
        }

        if ($clockSeq > self::CLOCK_SEQ_HIGH || $clockSeq < self::CLOCK_SEQ_LOW) {
            throw new DceSecurityException(
                'Clock sequence out of bounds; it must be a value between 0 and 63'
            );
        }

        switch ($localDomain) {
            case Uuid::DCE_DOMAIN_ORG:
                if ($localIdentifier === null) {
                    throw new DceSecurityException(
                        'A local identifier must be provided for the org domain'
                    );
                }

                break;
            case Uuid::DCE_DOMAIN_PERSON:
                if ($localIdentifier === null) {
                    $localIdentifier = $this->dceSecurityProvider->getUid();
                }

                break;
            case Uuid::DCE_DOMAIN_GROUP:
            default:
                if ($localIdentifier === null) {
                    $localIdentifier = $this->dceSecurityProvider->getGid();
                }

                break;
        }

        $identifierHex = $this->numberConverter->toHex($localIdentifier->toString());

        // The maximum value for the local identifier is 0xffffffff, or
        // 4294967295. This is 8 hexadecimal digits, so if the length of
        // hexadecimal digits is greater than 8, we know the value is greater
        // than 0xffffffff.
        if (strlen($identifierHex) > 8) {
            throw new DceSecurityException(
                'Local identifier out of bounds; it must be a value between 0 and 4294967295'
            );
        }

        $domainByte = pack('n', $localDomain)[1];
        $identifierBytes = hex2bin(str_pad($identifierHex, 8, '0', STR_PAD_LEFT));

        if ($node instanceof Hexadecimal) {
            $node = $node->toString();
        }

        // Shift the clock sequence 8 bits to the left, so it matches 0x3f00.
        if ($clockSeq !== null) {
            $clockSeq = $clockSeq << 8;
        }

        /** @var string $bytes */
        $bytes = $this->timeGenerator->generate($node, $clockSeq);

        // Replace bytes in the time-based UUID with DCE Security values.
        $bytes = substr_replace($bytes, $identifierBytes, 0, 4);
        $bytes = substr_replace($bytes, $domainByte, 9, 1);

        return $bytes;
    }
}
uuid/src/Generator/PeclUuidNameGenerator.php000064400000002661147361033650015137 0ustar00<?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\Generator;

use Ramsey\Uuid\Exception\NameException;
use Ramsey\Uuid\UuidInterface;

use function sprintf;
use function uuid_generate_md5;
use function uuid_generate_sha1;
use function uuid_parse;

/**
 * PeclUuidNameGenerator generates strings of binary data from a namespace and a
 * name, using ext-uuid
 *
 * @link https://pecl.php.net/package/uuid ext-uuid
 */
class PeclUuidNameGenerator implements NameGeneratorInterface
{
    /** @psalm-pure */
    public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string
    {
        switch ($hashAlgorithm) {
            case 'md5':
                $uuid = (string) uuid_generate_md5($ns->toString(), $name);

                break;
            case 'sha1':
                $uuid = (string) uuid_generate_sha1($ns->toString(), $name);

                break;
            default:
                throw new NameException(sprintf(
                    'Unable to hash namespace and name with algorithm \'%s\'',
                    $hashAlgorithm
                ));
        }

        return (string) uuid_parse($uuid);
    }
}
uuid/src/Generator/NameGeneratorInterface.php000064400000002052147361033650015317 0ustar00<?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\Generator;

use Ramsey\Uuid\UuidInterface;

/**
 * A name generator generates strings of binary data created by hashing together
 * a namespace with a name, according to a hashing algorithm
 */
interface NameGeneratorInterface
{
    /**
     * Generate a binary string from a namespace and name hashed together with
     * the specified hashing algorithm
     *
     * @param UuidInterface $ns The namespace
     * @param string $name The name to use for creating a UUID
     * @param string $hashAlgorithm The hashing algorithm to use
     *
     * @return string A binary string
     *
     * @psalm-pure
     */
    public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string;
}
uuid/src/Generator/TimeGeneratorInterface.php000064400000002206147361033650015336 0ustar00<?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\Generator;

use Ramsey\Uuid\Type\Hexadecimal;

/**
 * A time generator generates strings of binary data based on a node ID,
 * clock sequence, and the current time
 */
interface TimeGeneratorInterface
{
    /**
     * Generate a binary string from a node ID, clock sequence, and current time
     *
     * @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|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
     *
     * @return string A binary string
     */
    public function generate($node = null, ?int $clockSeq = null): string;
}
uuid/src/Generator/PeclUuidTimeGenerator.php000064400000001465147361033650015156 0ustar00<?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\Generator;

use const UUID_TYPE_TIME;

/**
 * PeclUuidTimeGenerator generates strings of binary data for time-base UUIDs,
 * using ext-uuid
 *
 * @link https://pecl.php.net/package/uuid ext-uuid
 */
class PeclUuidTimeGenerator implements TimeGeneratorInterface
{
    /**
     * @inheritDoc
     */
    public function generate($node = null, ?int $clockSeq = null): string
    {
        $uuid = uuid_create(UUID_TYPE_TIME);

        return uuid_parse($uuid);
    }
}
uuid/src/Generator/OpenSslGenerator.php000064400000002271147361033650014204 0ustar00<?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
 * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
 * @link https://packagist.org/packages/ramsey/uuid Packagist
 * @link https://github.com/ramsey/uuid GitHub
 */

namespace Ramsey\Uuid\Generator;

/**
 * OpenSslRandomGenerator provides functionality to generate strings of random
 * binary data using the `openssl_random_pseudo_bytes()` PHP function
 *
 * The use of this generator requires PHP to be compiled using the
 * `--with-openssl` option.
 *
 * @link http://php.net/openssl_random_pseudo_bytes
 */
class OpenSslGenerator implements RandomGeneratorInterface
{
    /**
     * Generates a string of random binary data of the specified length
     *
     * @param integer $length The number of bytes of random binary data to generate
     * @return string A binary string
     */
    public function generate($length)
    {
        return openssl_random_pseudo_bytes($length);
    }
}
uuid/src/Generator/DefaultTimeGenerator.php000064400000010154147361033650015023 0ustar00<?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\Generator;

use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Exception\RandomSourceException;
use Ramsey\Uuid\Exception\TimeSourceException;
use Ramsey\Uuid\Provider\NodeProviderInterface;
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 sprintf;
use function str_pad;
use function strlen;

use const STR_PAD_LEFT;

/**
 * DefaultTimeGenerator generates strings of binary data based on a node ID,
 * clock sequence, and the current time
 */
class DefaultTimeGenerator implements TimeGeneratorInterface
{
    /**
     * @var NodeProviderInterface
     */
    private $nodeProvider;

    /**
     * @var TimeConverterInterface
     */
    private $timeConverter;

    /**
     * @var TimeProviderInterface
     */
    private $timeProvider;

    public function __construct(
        NodeProviderInterface $nodeProvider,
        TimeConverterInterface $timeConverter,
        TimeProviderInterface $timeProvider
    ) {
        $this->nodeProvider = $nodeProvider;
        $this->timeConverter = $timeConverter;
        $this->timeProvider = $timeProvider;
    }

    /**
     * @throws InvalidArgumentException if the parameters contain invalid values
     * @throws RandomSourceException if random_int() throws an exception/error
     *
     * @inheritDoc
     */
    public function generate($node = null, ?int $clockSeq = null): string
    {
        if ($node instanceof Hexadecimal) {
            $node = $node->toString();
        }

        $node = $this->getValidNode($node);

        if ($clockSeq === null) {
            try {
                // This does not use "stable storage"; see RFC 4122, Section 4.2.1.1.
                $clockSeq = random_int(0, 0x3fff);
            } catch (Throwable $exception) {
                throw new RandomSourceException(
                    $exception->getMessage(),
                    (int) $exception->getCode(),
                    $exception
                );
            }
        }

        $time = $this->timeProvider->getTime();

        $uuidTime = $this->timeConverter->calculateTime(
            $time->getSeconds()->toString(),
            $time->getMicroseconds()->toString()
        );

        $timeHex = str_pad($uuidTime->toString(), 16, '0', STR_PAD_LEFT);

        if (strlen($timeHex) !== 16) {
            throw new TimeSourceException(sprintf(
                'The generated time of \'%s\' is larger than expected',
                $timeHex
            ));
        }

        $timeBytes = (string) hex2bin($timeHex);

        return $timeBytes[4] . $timeBytes[5] . $timeBytes[6] . $timeBytes[7]
            . $timeBytes[2] . $timeBytes[3]
            . $timeBytes[0] . $timeBytes[1]
            . pack('n*', $clockSeq)
            . $node;
    }

    /**
     * Uses the node provider given when constructing this instance to get
     * the node ID (usually a MAC address)
     *
     * @param string|int|null $node A node value that may be used to override the node provider
     *
     * @return string 6-byte binary string representation of the node
     *
     * @throws InvalidArgumentException
     */
    private function getValidNode($node): string
    {
        if ($node === null) {
            $node = $this->nodeProvider->getNode();
        }

        // Convert the node to hex, if it is still an integer.
        if (is_int($node)) {
            $node = dechex($node);
        }

        if (!ctype_xdigit((string) $node) || strlen((string) $node) > 12) {
            throw new InvalidArgumentException('Invalid node value');
        }

        return (string) hex2bin(str_pad((string) $node, 12, '0', STR_PAD_LEFT));
    }
}
uuid/src/Validator/ValidatorInterface.php000064400000001760147361033650014521 0ustar00<?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\Validator;

/**
 * A validator validates a string as a proper UUID
 *
 * @psalm-immutable
 */
interface ValidatorInterface
{
    /**
     * Returns the regular expression pattern used by this validator
     *
     * @return string The regular expression pattern this validator uses
     *
     * @psalm-return non-empty-string
     */
    public function getPattern(): string;

    /**
     * Returns true if the provided string represents a UUID
     *
     * @param string $uuid The string to validate as a UUID
     *
     * @return bool True if the string is a valid UUID, false otherwise
     */
    public function validate(string $uuid): bool;
}
uuid/src/Validator/GenericValidator.php000064400000002546147361033650014200 0ustar00<?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\Validator;

use Ramsey\Uuid\Uuid;

use function preg_match;
use function str_replace;

/**
 * GenericValidator validates strings as UUIDs of any variant
 *
 * @psalm-immutable
 */
final class GenericValidator implements ValidatorInterface
{
    /**
     * Regular expression pattern for matching a UUID of any variant.
     */
    private const VALID_PATTERN = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$';

    /**
     * @psalm-return non-empty-string
     * @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
     * @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
     */
    public function getPattern(): string
    {
        return self::VALID_PATTERN;
    }

    public function validate(string $uuid): bool
    {
        $uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid);

        return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/D', $uuid);
    }
}
uuid/src/Exception/UnableToBuildUuidException.php000064400000001040147361033650016152 0ustar00<?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\Exception;

use RuntimeException as PhpRuntimeException;

/**
 * Thrown to indicate a builder is unable to build a UUID
 */
class UnableToBuildUuidException extends PhpRuntimeException
{
}
uuid/src/Exception/UnsupportedOperationException.php000064400000001047147361033650017052 0ustar00<?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\Exception;

use LogicException as PhpLogicException;

/**
 * Thrown to indicate that the requested operation is not supported
 */
class UnsupportedOperationException extends PhpLogicException
{
}
uuid/src/Exception/DceSecurityException.php000064400000001101147361033650015053 0ustar00<?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\Exception;

use RuntimeException as PhpRuntimeException;

/**
 * Thrown to indicate an exception occurred while dealing with DCE Security
 * (version 2) UUIDs
 */
class DceSecurityException extends PhpRuntimeException
{
}
uuid/src/Exception/NodeException.php000064400000001061147361033650013522 0ustar00<?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\Exception;

use RuntimeException as PhpRuntimeException;

/**
 * Thrown to indicate that attempting to fetch or create a node ID encountered an error
 */
class NodeException extends PhpRuntimeException
{
}
uuid/src/Exception/InvalidUuidStringException.php000064400000001225147361033650016243 0ustar00<?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\Exception;

/**
 * Thrown to indicate that the string received is not a valid UUID
 *
 * The InvalidArgumentException that this extends is the ramsey/uuid version
 * of this exception. It exists in the same namespace as this class.
 */
class InvalidUuidStringException extends InvalidArgumentException
{
}
uuid/src/Exception/UnsatisfiedDependencyException.php000064400000001264147361033650017117 0ustar00<?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
 * @link https://benramsey.com/projects/ramsey-uuid/ Documentation
 * @link https://packagist.org/packages/ramsey/uuid Packagist
 * @link https://github.com/ramsey/uuid GitHub
 */

namespace Ramsey\Uuid\Exception;

/**
 * Thrown to indicate that the requested operation has dependencies that have not
 * been satisfied.
 */
class UnsatisfiedDependencyException extends \RuntimeException
{
}
uuid/src/Exception/InvalidArgumentException.php000064400000001072147361033650015730 0ustar00<?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\Exception;

use InvalidArgumentException as PhpInvalidArgumentException;

/**
 * Thrown to indicate that the argument received is not valid
 */
class InvalidArgumentException extends PhpInvalidArgumentException
{
}
uuid/src/Exception/BuilderNotFoundException.php000064400000001042147361033650015677 0ustar00<?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\Exception;

use RuntimeException as PhpRuntimeException;

/**
 * Thrown to indicate that no suitable builder could be found
 */
class BuilderNotFoundException extends PhpRuntimeException
{
}
uuid/src/Exception/NameException.php000064400000001067147361033650013523 0ustar00<?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\Exception;

use RuntimeException as PhpRuntimeException;

/**
 * Thrown to indicate that an error occurred while attempting to hash a
 * namespace and name
 */
class NameException extends PhpRuntimeException
{
}
uuid/src/Exception/DateTimeException.php000064400000001062147361033650014332 0ustar00<?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\Exception;

use RuntimeException as PhpRuntimeException;

/**
 * Thrown to indicate that the PHP DateTime extension encountered an exception/error
 */
class DateTimeException extends PhpRuntimeException
{
}
uuid/src/Exception/RandomSourceException.php000064400000001320147361033650015234 0ustar00<?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\Exception;

use RuntimeException as PhpRuntimeException;

/**
 * Thrown to indicate that the source of random data encountered an error
 *
 * This exception is used mostly to indicate that random_bytes() or random_int()
 * threw an exception. However, it may be used for other sources of random data.
 */
class RandomSourceException extends PhpRuntimeException
{
}
uuid/src/Exception/InvalidBytesException.php000064400000001060147361033650015231 0ustar00<?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\Exception;

use RuntimeException as PhpRuntimeException;

/**
 * Thrown to indicate that the bytes being operated on are invalid in some way
 */
class InvalidBytesException extends PhpRuntimeException
{
}
uuid/src/Exception/TimeSourceException.php000064400000001042147361033650014713 0ustar00<?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\Exception;

use RuntimeException as PhpRuntimeException;

/**
 * Thrown to indicate that the source of time encountered an error
 */
class TimeSourceException extends PhpRuntimeException
{
}
uuid/src/UuidFactoryInterface.php000064400000013740147361033650013106 0ustar00<?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;

use DateTimeInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Validator\ValidatorInterface;

/**
 * UuidFactoryInterface defines common functionality all `UuidFactory` instances
 * must implement
 */
interface UuidFactoryInterface
{
    /**
     * Returns the validator to use for the factory
     *
     * @psalm-mutation-free
     */
    public function getValidator(): ValidatorInterface;

    /**
     * Returns a version 1 (time-based) UUID from a host ID, sequence number,
     * and the current time
     *
     * @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|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
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 1 UUID
     */
    public function uuid1($node = null, ?int $clockSeq = null): UuidInterface;

    /**
     * Returns a version 2 (DCE Security) UUID from a local domain, local
     * identifier, host ID, clock sequence, and the current time
     *
     * @param int $localDomain The local domain to use when generating bytes,
     *     according to DCE Security
     * @param IntegerObject|null $localIdentifier The local identifier for the
     *     given domain; this may be a UID or GID on POSIX systems, if the local
     *     domain is person or group, or it may be a site-defined identifier
     *     if the local domain is org
     * @param Hexadecimal|null $node A 48-bit number representing the hardware
     *     address
     * @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
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 2 UUID
     */
    public function uuid2(
        int $localDomain,
        ?IntegerObject $localIdentifier = null,
        ?Hexadecimal $node = null,
        ?int $clockSeq = null
    ): UuidInterface;

    /**
     * Returns a version 3 (name-based) UUID based on the MD5 hash of a
     * namespace ID and a name
     *
     * @param string|UuidInterface $ns The namespace (must be a valid UUID)
     * @param string $name The name to use for creating a UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 3 UUID
     *
     * @psalm-pure
     */
    public function uuid3($ns, string $name): UuidInterface;

    /**
     * Returns a version 4 (random) UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 4 UUID
     */
    public function uuid4(): UuidInterface;

    /**
     * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a
     * namespace ID and a name
     *
     * @param string|UuidInterface $ns The namespace (must be a valid UUID)
     * @param string $name The name to use for creating a UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 5 UUID
     *
     * @psalm-pure
     */
    public function uuid5($ns, string $name): UuidInterface;

    /**
     * Returns a version 6 (ordered-time) UUID from a host ID, sequence number,
     * and the current time
     *
     * @param Hexadecimal|null $node A 48-bit number representing the hardware
     *     address
     * @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
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 6 UUID
     */
    public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface;

    /**
     * Creates a UUID from a byte string
     *
     * @param string $bytes A binary string
     *
     * @return UuidInterface A UuidInterface instance created from a binary
     *     string representation
     *
     * @psalm-pure
     */
    public function fromBytes(string $bytes): UuidInterface;

    /**
     * Creates a UUID from the string standard representation
     *
     * @param string $uuid A hexadecimal string
     *
     * @return UuidInterface A UuidInterface instance created from a hexadecimal
     *     string representation
     *
     * @psalm-pure
     */
    public function fromString(string $uuid): UuidInterface;

    /**
     * Creates a UUID from a 128-bit integer string
     *
     * @param string $integer String representation of 128-bit integer
     *
     * @return UuidInterface A UuidInterface instance created from the string
     *     representation of a 128-bit integer
     *
     * @psalm-pure
     */
    public function fromInteger(string $integer): UuidInterface;

    /**
     * Creates a UUID from a DateTimeInterface instance
     *
     * @param DateTimeInterface $dateTime The date and time
     * @param Hexadecimal|null $node A 48-bit number representing the hardware
     *     address
     * @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
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 1 UUID created from a DateTimeInterface instance
     */
    public function fromDateTime(
        DateTimeInterface $dateTime,
        ?Hexadecimal $node = null,
        ?int $clockSeq = null
    ): UuidInterface;
}
uuid/src/Nonstandard/Fields.php000064400000006456147361033650012516 0ustar00<?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\Nonstandard;

use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Fields\SerializableFieldsTrait;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Rfc4122\VariantTrait;
use Ramsey\Uuid\Type\Hexadecimal;

use function bin2hex;
use function dechex;
use function hexdec;
use function sprintf;
use function str_pad;
use function strlen;
use function substr;

use const STR_PAD_LEFT;

/**
 * Nonstandard UUID fields do not conform to the RFC 4122 standard
 *
 * Since some systems may create nonstandard UUIDs, this implements the
 * Rfc4122\FieldsInterface, so that functionality of a nonstandard UUID is not
 * degraded, in the event these UUIDs are expected to contain RFC 4122 fields.
 *
 * Internally, this class represents the fields together as a 16-byte binary
 * string.
 *
 * @psalm-immutable
 */
final class Fields implements FieldsInterface
{
    use SerializableFieldsTrait;
    use VariantTrait;

    /**
     * @var string
     */
    private $bytes;

    /**
     * @param string $bytes A 16-byte binary string representation of a UUID
     *
     * @throws InvalidArgumentException if the byte string is not exactly 16 bytes
     */
    public function __construct(string $bytes)
    {
        if (strlen($bytes) !== 16) {
            throw new InvalidArgumentException(
                'The byte string must be 16 bytes long; '
                . 'received ' . strlen($bytes) . ' bytes'
            );
        }

        $this->bytes = $bytes;
    }

    public function getBytes(): string
    {
        return $this->bytes;
    }

    public function getClockSeq(): Hexadecimal
    {
        $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;

        return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
    }

    public function getClockSeqHiAndReserved(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1)));
    }

    public function getClockSeqLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1)));
    }

    public function getNode(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 10)));
    }

    public function getTimeHiAndVersion(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 6, 2)));
    }

    public function getTimeLow(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 0, 4)));
    }

    public function getTimeMid(): Hexadecimal
    {
        return new Hexadecimal(bin2hex(substr($this->bytes, 4, 2)));
    }

    public function getTimestamp(): Hexadecimal
    {
        return new Hexadecimal(sprintf(
            '%03x%04s%08s',
            hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
            $this->getTimeMid()->toString(),
            $this->getTimeLow()->toString()
        ));
    }

    public function getVersion(): ?int
    {
        return null;
    }

    public function isNil(): bool
    {
        return false;
    }
}
uuid/src/Nonstandard/UuidBuilder.php000064400000004664147361033650013524 0ustar00<?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\Nonstandard;

use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\UuidInterface;
use Throwable;

/**
 * Nonstandard\UuidBuilder builds instances of Nonstandard\Uuid
 *
 * @psalm-immutable
 */
class UuidBuilder implements UuidBuilderInterface
{
    /**
     * @var NumberConverterInterface
     */
    private $numberConverter;

    /**
     * @var TimeConverterInterface
     */
    private $timeConverter;

    /**
     * @param NumberConverterInterface $numberConverter The number converter to
     *     use when constructing the Nonstandard\Uuid
     * @param TimeConverterInterface $timeConverter The time converter to use
     *     for converting timestamps extracted from a UUID to Unix timestamps
     */
    public function __construct(
        NumberConverterInterface $numberConverter,
        TimeConverterInterface $timeConverter
    ) {
        $this->numberConverter = $numberConverter;
        $this->timeConverter = $timeConverter;
    }

    /**
     * Builds and returns a Nonstandard\Uuid
     *
     * @param CodecInterface $codec The codec to use for building this instance
     * @param string $bytes The byte string from which to construct a UUID
     *
     * @return Uuid The Nonstandard\UuidBuilder returns an instance of
     *     Nonstandard\Uuid
     *
     * @psalm-pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        try {
            return new Uuid(
                $this->buildFields($bytes),
                $this->numberConverter,
                $codec,
                $this->timeConverter
            );
        } catch (Throwable $e) {
            throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }

    /**
     * Proxy method to allow injecting a mock, for testing
     */
    protected function buildFields(string $bytes): Fields
    {
        return new Fields($bytes);
    }
}
uuid/src/Nonstandard/UuidV6.php000064400000010026147361033650012416 0ustar00<?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\Nonstandard;

use DateTimeImmutable;
use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Rfc4122\UuidInterface;
use Ramsey\Uuid\Rfc4122\UuidV1;
use Ramsey\Uuid\Uuid;
use Throwable;

use function hex2bin;
use function str_pad;
use function substr;

use const STR_PAD_LEFT;

/**
 * Ordered-time, or version 6, UUIDs include timestamp, clock sequence, and node
 * values that are combined into a 128-bit unsigned integer
 *
 * @link https://github.com/uuid6/uuid6-ietf-draft UUID version 6 IETF draft
 * @link http://gh.peabody.io/uuidv6/ "Version 6" UUIDs
 *
 * @psalm-immutable
 */
final class UuidV6 extends Uuid implements UuidInterface
{
    /**
     * Creates a version 6 (time-based) 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_PEABODY) {
            throw new InvalidArgumentException(
                'Fields used to create a UuidV6 must represent a '
                . 'version 6 (ordered-time) UUID'
            );
        }

        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }

    /**
     * Returns a DateTimeInterface object representing the timestamp associated
     * with the UUID
     *
     * @return DateTimeImmutable A PHP DateTimeImmutable instance representing
     *     the timestamp of a version 6 UUID
     */
    public function getDateTime(): DateTimeInterface
    {
        $time = $this->timeConverter->convertTime($this->fields->getTimestamp());

        try {
            return new DateTimeImmutable(
                '@'
                . $time->getSeconds()->toString()
                . '.'
                . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
            );
        } catch (Throwable $e) {
            throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
        }
    }

    /**
     * Converts this UUID into an instance of a version 1 UUID
     */
    public function toUuidV1(): UuidV1
    {
        $hex = $this->getHex()->toString();
        $hex = substr($hex, 7, 5)
            . substr($hex, 13, 3)
            . substr($hex, 3, 4)
            . '1' . substr($hex, 0, 3)
            . substr($hex, 16);

        /** @var UuidV1 $uuid */
        $uuid = Uuid::fromBytes((string) hex2bin($hex));

        return $uuid;
    }

    /**
     * Converts a version 1 UUID into an instance of a version 6 UUID
     */
    public static function fromUuidV1(UuidV1 $uuidV1): UuidV6
    {
        $hex = $uuidV1->getHex()->toString();
        $hex = substr($hex, 13, 3)
            . substr($hex, 8, 4)
            . substr($hex, 0, 5)
            . '6' . substr($hex, 5, 3)
            . substr($hex, 16);

        /** @var UuidV6 $uuid */
        $uuid = Uuid::fromBytes((string) hex2bin($hex));

        return $uuid;
    }
}
uuid/src/Nonstandard/Uuid.php000064400000001763147361033650012212 0ustar00<?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\Nonstandard;

use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Uuid as BaseUuid;
use Ramsey\Uuid\UuidInterface;

/**
 * Nonstandard\Uuid is a UUID that doesn't conform to RFC 4122
 *
 * @psalm-immutable
 */
final class Uuid extends BaseUuid implements UuidInterface
{
    public function __construct(
        Fields $fields,
        NumberConverterInterface $numberConverter,
        CodecInterface $codec,
        TimeConverterInterface $timeConverter
    ) {
        parent::__construct($fields, $numberConverter, $codec, $timeConverter);
    }
}
uuid/src/Uuid.php000064400000043723147361033650007741 0ustar00<?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;

use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Fields\FieldsInterface;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;

use function str_replace;
use function strcmp;

/**
 * Uuid provides constants and static methods for working with and generating UUIDs
 *
 * @psalm-immutable
 */
class Uuid implements UuidInterface
{
    use DeprecatedUuidMethodsTrait;

    /**
     * When this namespace is specified, the name string is a fully-qualified
     * domain name
     *
     * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs
     */
    public const NAMESPACE_DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';

    /**
     * When this namespace is specified, the name string is a URL
     *
     * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs
     */
    public const NAMESPACE_URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';

    /**
     * When this namespace is specified, the name string is an ISO OID
     *
     * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs
     */
    public const NAMESPACE_OID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8';

    /**
     * When this namespace is specified, the name string is an X.500 DN in DER
     * or a text output format
     *
     * @link http://tools.ietf.org/html/rfc4122#appendix-C RFC 4122, Appendix C: Some Name Space IDs
     */
    public const NAMESPACE_X500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8';

    /**
     * The nil UUID is a special form of UUID that is specified to have all 128
     * bits set to zero
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.1.7 RFC 4122, § 4.1.7: Nil UUID
     */
    public const NIL = '00000000-0000-0000-0000-000000000000';

    /**
     * Variant: reserved, NCS backward compatibility
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
     */
    public const RESERVED_NCS = 0;

    /**
     * Variant: the UUID layout specified in RFC 4122
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
     */
    public const RFC_4122 = 2;

    /**
     * Variant: reserved, Microsoft Corporation backward compatibility
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
     */
    public const RESERVED_MICROSOFT = 6;

    /**
     * Variant: reserved for future definition
     *
     * @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
     */
    public const RESERVED_FUTURE = 7;

    /**
     * @deprecated Use {@see ValidatorInterface::getPattern()} instead.
     */
    public const VALID_PATTERN = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$';

    /**
     * Version 1 (time-based) UUID
     *
     * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
     */
    public const UUID_TYPE_TIME = 1;

    /**
     * Version 2 (DCE Security) UUID
     *
     * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
     */
    public const UUID_TYPE_DCE_SECURITY = 2;

    /**
     * @deprecated Use {@see Uuid::UUID_TYPE_DCE_SECURITY} instead.
     */
    public const UUID_TYPE_IDENTIFIER = 2;

    /**
     * Version 3 (name-based and hashed with MD5) UUID
     *
     * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
     */
    public const UUID_TYPE_HASH_MD5 = 3;

    /**
     * Version 4 (random) UUID
     *
     * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
     */
    public const UUID_TYPE_RANDOM = 4;

    /**
     * Version 5 (name-based and hashed with SHA1) UUID
     *
     * @link https://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
     */
    public const UUID_TYPE_HASH_SHA1 = 5;

    /**
     * Version 6 (ordered-time) UUID
     *
     * This is named `UUID_TYPE_PEABODY`, since the specification is still in
     * draft form, and the primary author/editor's name is Brad Peabody.
     *
     * @link https://github.com/uuid6/uuid6-ietf-draft UUID version 6 IETF draft
     * @link http://gh.peabody.io/uuidv6/ "Version 6" UUIDs
     */
    public const UUID_TYPE_PEABODY = 6;

    /**
     * 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
     */
    public const DCE_DOMAIN_PERSON = 0;

    /**
     * DCE Security group domain
     *
     * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1
     */
    public const DCE_DOMAIN_GROUP = 1;

    /**
     * DCE Security organization domain
     *
     * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1
     */
    public const DCE_DOMAIN_ORG = 2;

    /**
     * DCE Security domain string names
     *
     * @link https://pubs.opengroup.org/onlinepubs/9696989899/chap11.htm#tagcjh_14_05_01_01 DCE 1.1, §11.5.1.1
     */
    public const DCE_DOMAIN_NAMES = [
        self::DCE_DOMAIN_PERSON => 'person',
        self::DCE_DOMAIN_GROUP => 'group',
        self::DCE_DOMAIN_ORG => 'org',
    ];

    /**
     * @var UuidFactoryInterface|null
     */
    private static $factory = null;

    /**
     * @var CodecInterface
     */
    protected $codec;

    /**
     * The fields that make up this UUID
     *
     * @var Rfc4122FieldsInterface
     */
    protected $fields;

    /**
     * @var NumberConverterInterface
     */
    protected $numberConverter;

    /**
     * @var TimeConverterInterface
     */
    protected $timeConverter;

    /**
     * Creates a universally unique identifier (UUID) from an array of fields
     *
     * Unless you're making advanced use of this library to generate identifiers
     * that deviate from RFC 4122, you probably do not want to instantiate a
     * UUID directly. Use the static methods, instead:
     *
     * ```
     * use Ramsey\Uuid\Uuid;
     *
     * $timeBasedUuid     = Uuid::uuid1();
     * $namespaceMd5Uuid  = Uuid::uuid3(Uuid::NAMESPACE_URL, 'http://php.net/');
     * $randomUuid        = Uuid::uuid4();
     * $namespaceSha1Uuid = Uuid::uuid5(Uuid::NAMESPACE_URL, 'http://php.net/');
     * ```
     *
     * @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
    ) {
        $this->fields = $fields;
        $this->codec = $codec;
        $this->numberConverter = $numberConverter;
        $this->timeConverter = $timeConverter;
    }

    /**
     * @psalm-return non-empty-string
     */
    public function __toString(): string
    {
        return $this->toString();
    }

    /**
     * Converts the UUID to a string for JSON serialization
     */
    public function jsonSerialize(): string
    {
        return $this->toString();
    }

    /**
     * Converts the UUID to a string for PHP serialization
     */
    public function serialize(): string
    {
        return $this->toString();
    }

    /**
     * Re-constructs the object from its serialized form
     *
     * @param string $serialized The serialized PHP string to unserialize into
     *     a UuidInterface instance
     *
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     */
    public function unserialize($serialized): void
    {
        /** @var \Ramsey\Uuid\Uuid $uuid */
        $uuid = self::fromString($serialized);
        $this->codec = $uuid->codec;
        $this->numberConverter = $uuid->numberConverter;
        $this->fields = $uuid->fields;
        $this->timeConverter = $uuid->timeConverter;
    }

    public function compareTo(UuidInterface $other): int
    {
        $compare = strcmp($this->toString(), $other->toString());

        if ($compare < 0) {
            return -1;
        }

        if ($compare > 0) {
            return 1;
        }

        return 0;
    }

    public function equals(?object $other): bool
    {
        if (!$other instanceof UuidInterface) {
            return false;
        }

        return $this->compareTo($other) === 0;
    }

    /**
     * @psalm-return non-empty-string
     */
    public function getBytes(): string
    {
        return $this->codec->encodeBinary($this);
    }

    public function getFields(): FieldsInterface
    {
        return $this->fields;
    }

    public function getHex(): Hexadecimal
    {
        return new Hexadecimal(str_replace('-', '', $this->toString()));
    }

    public function getInteger(): IntegerObject
    {
        return new IntegerObject($this->numberConverter->fromHex($this->getHex()->toString()));
    }

    /**
     * @psalm-return non-empty-string
     */
    public function toString(): string
    {
        return $this->codec->encode($this);
    }

    /**
     * Returns the factory used to create UUIDs
     */
    public static function getFactory(): UuidFactoryInterface
    {
        if (self::$factory === null) {
            self::$factory = new UuidFactory();
        }

        return self::$factory;
    }

    /**
     * Sets the factory used to create UUIDs
     *
     * @param UuidFactoryInterface $factory A factory that will be used by this
     *     class to create UUIDs
     */
    public static function setFactory(UuidFactoryInterface $factory): void
    {
        self::$factory = $factory;
    }

    /**
     * Creates a UUID from a byte string
     *
     * @param string $bytes A binary string
     *
     * @return UuidInterface A UuidInterface instance created from a binary
     *     string representation
     *
     * @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
     */
    public static function fromBytes(string $bytes): UuidInterface
    {
        return self::getFactory()->fromBytes($bytes);
    }

    /**
     * Creates a UUID from the string standard representation
     *
     * @param string $uuid A hexadecimal string
     *
     * @return UuidInterface A UuidInterface instance created from a hexadecimal
     *     string representation
     *
     * @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
     */
    public static function fromString(string $uuid): UuidInterface
    {
        return self::getFactory()->fromString($uuid);
    }

    /**
     * Creates a UUID from a DateTimeInterface instance
     *
     * @param DateTimeInterface $dateTime The date and time
     * @param Hexadecimal|null $node A 48-bit number representing the hardware
     *     address
     * @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
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 1 UUID created from a DateTimeInterface instance
     */
    public static function fromDateTime(
        DateTimeInterface $dateTime,
        ?Hexadecimal $node = null,
        ?int $clockSeq = null
    ): UuidInterface {
        return self::getFactory()->fromDateTime($dateTime, $node, $clockSeq);
    }

    /**
     * Creates a UUID from a 128-bit integer string
     *
     * @param string $integer String representation of 128-bit integer
     *
     * @return UuidInterface A UuidInterface instance created from the string
     *     representation of a 128-bit integer
     *
     * @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
     */
    public static function fromInteger(string $integer): UuidInterface
    {
        return self::getFactory()->fromInteger($integer);
    }

    /**
     * Returns true if the provided string is a valid UUID
     *
     * @param string $uuid A string to validate as a UUID
     *
     * @return bool True if the string is a valid UUID, false otherwise
     *
     * @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
     */
    public static function isValid(string $uuid): bool
    {
        return self::getFactory()->getValidator()->validate($uuid);
    }

    /**
     * Returns a version 1 (time-based) UUID from a host ID, sequence number,
     * and the current time
     *
     * @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
     *     could arise when the clock is set backwards in time or if the node ID
     *     changes
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 1 UUID
     */
    public static function uuid1($node = null, ?int $clockSeq = null): UuidInterface
    {
        return self::getFactory()->uuid1($node, $clockSeq);
    }

    /**
     * Returns a version 2 (DCE Security) UUID from a local domain, local
     * identifier, host ID, clock sequence, and the current time
     *
     * @param int $localDomain The local domain to use when generating bytes,
     *     according to DCE Security
     * @param IntegerObject|null $localIdentifier The local identifier for the
     *     given domain; this may be a UID or GID on POSIX systems, if the local
     *     domain is person or group, or it may be a site-defined identifier
     *     if the local domain is org
     * @param Hexadecimal|null $node A 48-bit number representing the hardware
     *     address
     * @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 (in a version 2 UUID, the lower 8 bits of this number
     *     are replaced with the domain).
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 2 UUID
     */
    public static function uuid2(
        int $localDomain,
        ?IntegerObject $localIdentifier = null,
        ?Hexadecimal $node = null,
        ?int $clockSeq = null
    ): UuidInterface {
        return self::getFactory()->uuid2($localDomain, $localIdentifier, $node, $clockSeq);
    }

    /**
     * Returns a version 3 (name-based) UUID based on the MD5 hash of a
     * namespace ID and a name
     *
     * @param string|UuidInterface $ns The namespace (must be a valid UUID)
     * @param string $name The name to use for creating a UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 3 UUID
     *
     * @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
     */
    public static function uuid3($ns, string $name): UuidInterface
    {
        return self::getFactory()->uuid3($ns, $name);
    }

    /**
     * Returns a version 4 (random) UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 4 UUID
     */
    public static function uuid4(): UuidInterface
    {
        return self::getFactory()->uuid4();
    }

    /**
     * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a
     * namespace ID and a name
     *
     * @param string|UuidInterface $ns The namespace (must be a valid UUID)
     * @param string $name The name to use for creating a UUID
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 5 UUID
     *
     * @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
     */
    public static function uuid5($ns, string $name): UuidInterface
    {
        return self::getFactory()->uuid5($ns, $name);
    }

    /**
     * Returns a version 6 (ordered-time) UUID from a host ID, sequence number,
     * and the current time
     *
     * @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
     *     could arise when the clock is set backwards in time or if the node ID
     *     changes
     *
     * @return UuidInterface A UuidInterface instance that represents a
     *     version 6 UUID
     */
    public static function uuid6(
        ?Hexadecimal $node = null,
        ?int $clockSeq = null
    ): UuidInterface {
        return self::getFactory()->uuid6($node, $clockSeq);
    }
}
uuid/src/Fields/FieldsInterface.php000064400000001354147361033650013262 0ustar00<?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\Fields;

use Serializable;

/**
 * UUIDs are comprised of unsigned integers, the bytes of which are separated
 * into fields and arranged in a particular layout defined by the specification
 * for the variant
 *
 * @psalm-immutable
 */
interface FieldsInterface extends Serializable
{
    /**
     * Returns the bytes that comprise the fields
     */
    public function getBytes(): string;
}
uuid/src/Fields/SerializableFieldsTrait.php000064400000002520147361033650014770 0ustar00<?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\Fields;

use function base64_decode;
use function base64_encode;

/**
 * Provides common serialization functionality to fields
 *
 * @psalm-immutable
 */
trait SerializableFieldsTrait
{
    /**
     * @param string $bytes The bytes that comprise the fields
     */
    abstract public function __construct(string $bytes);

    /**
     * Returns the bytes that comprise the fields
     */
    abstract public function getBytes(): string;

    /**
     * Returns a string representation of object
     */
    public function serialize(): string
    {
        return base64_encode($this->getBytes());
    }

    /**
     * Constructs the object from a serialized string representation
     *
     * @param string $serialized The serialized string representation of the object
     *
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     */
    public function unserialize($serialized): void
    {
        $this->__construct(base64_decode($serialized));
    }
}
uuid/src/Math/BrickMathCalculator.php000064400000010745147361033650013600 0ustar00<?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\Math;

use Brick\Math\BigDecimal;
use Brick\Math\BigInteger;
use Brick\Math\Exception\MathException;
use Brick\Math\RoundingMode as BrickMathRounding;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Type\Decimal;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Type\NumberInterface;

/**
 * A calculator using the brick/math library for arbitrary-precision arithmetic
 *
 * @psalm-immutable
 */
final class BrickMathCalculator implements CalculatorInterface
{
    private const ROUNDING_MODE_MAP = [
        RoundingMode::UNNECESSARY => BrickMathRounding::UNNECESSARY,
        RoundingMode::UP => BrickMathRounding::UP,
        RoundingMode::DOWN => BrickMathRounding::DOWN,
        RoundingMode::CEILING => BrickMathRounding::CEILING,
        RoundingMode::FLOOR => BrickMathRounding::FLOOR,
        RoundingMode::HALF_UP => BrickMathRounding::HALF_UP,
        RoundingMode::HALF_DOWN => BrickMathRounding::HALF_DOWN,
        RoundingMode::HALF_CEILING => BrickMathRounding::HALF_CEILING,
        RoundingMode::HALF_FLOOR => BrickMathRounding::HALF_FLOOR,
        RoundingMode::HALF_EVEN => BrickMathRounding::HALF_EVEN,
    ];

    public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface
    {
        $sum = BigInteger::of($augend->toString());

        foreach ($addends as $addend) {
            $sum = $sum->plus($addend->toString());
        }

        return new IntegerObject((string) $sum);
    }

    public function subtract(NumberInterface $minuend, NumberInterface ...$subtrahends): NumberInterface
    {
        $difference = BigInteger::of($minuend->toString());

        foreach ($subtrahends as $subtrahend) {
            $difference = $difference->minus($subtrahend->toString());
        }

        return new IntegerObject((string) $difference);
    }

    public function multiply(NumberInterface $multiplicand, NumberInterface ...$multipliers): NumberInterface
    {
        $product = BigInteger::of($multiplicand->toString());

        foreach ($multipliers as $multiplier) {
            $product = $product->multipliedBy($multiplier->toString());
        }

        return new IntegerObject((string) $product);
    }

    public function divide(
        int $roundingMode,
        int $scale,
        NumberInterface $dividend,
        NumberInterface ...$divisors
    ): NumberInterface {
        $brickRounding = $this->getBrickRoundingMode($roundingMode);

        $quotient = BigDecimal::of($dividend->toString());

        foreach ($divisors as $divisor) {
            $quotient = $quotient->dividedBy($divisor->toString(), $scale, $brickRounding);
        }

        if ($scale === 0) {
            return new IntegerObject((string) $quotient->toBigInteger());
        }

        return new Decimal((string) $quotient);
    }

    public function fromBase(string $value, int $base): IntegerObject
    {
        try {
            return new IntegerObject((string) BigInteger::fromBase($value, $base));
        } catch (MathException | \InvalidArgumentException $exception) {
            throw new InvalidArgumentException(
                $exception->getMessage(),
                (int) $exception->getCode(),
                $exception
            );
        }
    }

    public function toBase(IntegerObject $value, int $base): string
    {
        try {
            return BigInteger::of($value->toString())->toBase($base);
        } catch (MathException | \InvalidArgumentException $exception) {
            throw new InvalidArgumentException(
                $exception->getMessage(),
                (int) $exception->getCode(),
                $exception
            );
        }
    }

    public function toHexadecimal(IntegerObject $value): Hexadecimal
    {
        return new Hexadecimal($this->toBase($value, 16));
    }

    public function toInteger(Hexadecimal $value): IntegerObject
    {
        return $this->fromBase($value->toString(), 16);
    }

    /**
     * Maps ramsey/uuid rounding modes to those used by brick/math
     */
    private function getBrickRoundingMode(int $roundingMode): int
    {
        return self::ROUNDING_MODE_MAP[$roundingMode] ?? 0;
    }
}
uuid/src/Math/RoundingMode.php000064400000011637147361033650012315 0ustar00<?php

/**
 * This file was originally part of brick/math
 *
 * Copyright (c) 2013-present Benjamin Morel
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * @link https://github.com/brick/math brick/math at GitHub
 */

declare(strict_types=1);

namespace Ramsey\Uuid\Math;

/**
 * Specifies a rounding behavior for numerical operations capable of discarding
 * precision.
 *
 * Each rounding mode indicates how the least significant returned digit of a
 * rounded result is to be calculated. If fewer digits are returned than the
 * digits needed to represent the exact numerical result, the discarded digits
 * will be referred to as the discarded fraction regardless the digits'
 * contribution to the value of the number. In other words, considered as a
 * numerical value, the discarded fraction could have an absolute value greater
 * than one.
 */
final class RoundingMode
{
    /**
     * Private constructor. This class is not instantiable.
     *
     * @codeCoverageIgnore
     */
    private function __construct()
    {
    }

    /**
     * Asserts that the requested operation has an exact result, hence no
     * rounding is necessary.
     */
    public const UNNECESSARY = 0;

    /**
     * Rounds away from zero.
     *
     * Always increments the digit prior to a nonzero discarded fraction.
     * Note that this rounding mode never decreases the magnitude of the
     * calculated value.
     */
    public const UP = 1;

    /**
     * Rounds towards zero.
     *
     * Never increments the digit prior to a discarded fraction (i.e.,
     * truncates). Note that this rounding mode never increases the magnitude of
     * the calculated value.
     */
    public const DOWN = 2;

    /**
     * Rounds towards positive infinity.
     *
     * If the result is positive, behaves as for UP; if negative, behaves as for
     * DOWN. Note that this rounding mode never decreases the calculated value.
     */
    public const CEILING = 3;

    /**
     * Rounds towards negative infinity.
     *
     * If the result is positive, behave as for DOWN; if negative, behave as for
     * UP. Note that this rounding mode never increases the calculated value.
     */
    public const FLOOR = 4;

    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
     * in which case round up.
     *
     * Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves
     * as for DOWN. Note that this is the rounding mode commonly taught at
     * school.
     */
    public const HALF_UP = 5;

    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
     * in which case round down.
     *
     * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves
     * as for DOWN.
     */
    public const HALF_DOWN = 6;

    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
     * in which case round towards positive infinity.
     *
     * If the result is positive, behaves as for HALF_UP; if negative, behaves
     * as for HALF_DOWN.
     */
    public const HALF_CEILING = 7;

    /**
     * Rounds towards "nearest neighbor" unless both neighbors are equidistant,
     * in which case round towards negative infinity.
     *
     * If the result is positive, behaves as for HALF_DOWN; if negative, behaves
     * as for HALF_UP.
     */
    public const HALF_FLOOR = 8;

    /**
     * Rounds towards the "nearest neighbor" unless both neighbors are
     * equidistant, in which case rounds towards the even neighbor.
     *
     * Behaves as for HALF_UP if the digit to the left of the discarded fraction
     * is odd; behaves as for HALF_DOWN if it's even.
     *
     * Note that this is the rounding mode that statistically minimizes
     * cumulative error when applied repeatedly over a sequence of calculations.
     * It is sometimes known as "Banker's rounding", and is chiefly used in the
     * USA.
     */
    public const HALF_EVEN = 9;
}
uuid/src/Math/CalculatorInterface.php000064400000007176147361033650013640 0ustar00<?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\Math;

use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Type\NumberInterface;

/**
 * A calculator performs arithmetic operations on numbers
 *
 * @psalm-immutable
 */
interface CalculatorInterface
{
    /**
     * Returns the sum of all the provided parameters
     *
     * @param NumberInterface $augend The first addend (the integer being added to)
     * @param NumberInterface ...$addends The additional integers to a add to the augend
     *
     * @return NumberInterface The sum of all the parameters
     */
    public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface;

    /**
     * Returns the difference of all the provided parameters
     *
     * @param NumberInterface $minuend The integer being subtracted from
     * @param NumberInterface ...$subtrahends The integers to subtract from the minuend
     *
     * @return NumberInterface The difference after subtracting all parameters
     */
    public function subtract(NumberInterface $minuend, NumberInterface ...$subtrahends): NumberInterface;

    /**
     * Returns the product of all the provided parameters
     *
     * @param NumberInterface $multiplicand The integer to be multiplied
     * @param NumberInterface ...$multipliers The factors by which to multiply the multiplicand
     *
     * @return NumberInterface The product of multiplying all the provided parameters
     */
    public function multiply(NumberInterface $multiplicand, NumberInterface ...$multipliers): NumberInterface;

    /**
     * Returns the quotient of the provided parameters divided left-to-right
     *
     * @param int $roundingMode The RoundingMode constant to use for this operation
     * @param int $scale The scale to use for this operation
     * @param NumberInterface $dividend The integer to be divided
     * @param NumberInterface ...$divisors The integers to divide $dividend by, in
     *     the order in which the division operations should take place
     *     (left-to-right)
     *
     * @return NumberInterface The quotient of dividing the provided parameters left-to-right
     */
    public function divide(
        int $roundingMode,
        int $scale,
        NumberInterface $dividend,
        NumberInterface ...$divisors
    ): NumberInterface;

    /**
     * Converts a value from an arbitrary base to a base-10 integer value
     *
     * @param string $value The value to convert
     * @param int $base The base to convert from (i.e., 2, 16, 32, etc.)
     *
     * @return IntegerObject The base-10 integer value of the converted value
     */
    public function fromBase(string $value, int $base): IntegerObject;

    /**
     * Converts a base-10 integer value to an arbitrary base
     *
     * @param IntegerObject $value The integer value to convert
     * @param int $base The base to convert to (i.e., 2, 16, 32, etc.)
     *
     * @return string The value represented in the specified base
     */
    public function toBase(IntegerObject $value, int $base): string;

    /**
     * Converts an Integer instance to a Hexadecimal instance
     */
    public function toHexadecimal(IntegerObject $value): Hexadecimal;

    /**
     * Converts a Hexadecimal instance to an Integer instance
     */
    public function toInteger(Hexadecimal $value): IntegerObject;
}
uuid/src/functions.php000064400000006654147361033650011045 0ustar00<?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
 * phpcs:disable Squiz.Functions.GlobalFunction
 */

declare(strict_types=1);

namespace Ramsey\Uuid;

use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;

/**
 * Returns a version 1 (time-based) UUID from a host ID, sequence number,
 * and the current time
 *
 * @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
 *     could arise when the clock is set backwards in time or if the node ID
 *     changes
 *
 * @return string Version 1 UUID as a string
 */
function v1($node = null, ?int $clockSeq = null): string
{
    return Uuid::uuid1($node, $clockSeq)->toString();
}

/**
 * Returns a version 2 (DCE Security) UUID from a local domain, local
 * identifier, host ID, clock sequence, and the current time
 *
 * @param int $localDomain The local domain to use when generating bytes,
 *     according to DCE Security
 * @param IntegerObject|null $localIdentifier The local identifier for the
 *     given domain; this may be a UID or GID on POSIX systems, if the local
 *     domain is person or group, or it may be a site-defined identifier
 *     if the local domain is org
 * @param Hexadecimal|null $node A 48-bit number representing the hardware
 *     address
 * @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
 *
 * @return string Version 2 UUID as a string
 */
function v2(
    int $localDomain,
    ?IntegerObject $localIdentifier = null,
    ?Hexadecimal $node = null,
    ?int $clockSeq = null
): string {
    return Uuid::uuid2($localDomain, $localIdentifier, $node, $clockSeq)->toString();
}

/**
 * Returns a version 3 (name-based) UUID based on the MD5 hash of a
 * namespace ID and a name
 *
 * @param string|UuidInterface $ns The namespace (must be a valid UUID)
 *
 * @return string Version 3 UUID as a string
 */
function v3($ns, string $name): string
{
    return Uuid::uuid3($ns, $name)->toString();
}

/**
 * Returns a version 4 (random) UUID
 *
 * @return string Version 4 UUID as a string
 */
function v4(): string
{
    return Uuid::uuid4()->toString();
}

/**
 * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a
 * namespace ID and a name
 *
 * @param string|UuidInterface $ns The namespace (must be a valid UUID)
 *
 * @return string Version 5 UUID as a string
 */
function v5($ns, string $name): string
{
    return Uuid::uuid5($ns, $name)->toString();
}

/**
 * Returns a version 6 (ordered-time) UUID from a host ID, sequence number,
 * and the current time
 *
 * @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
 *     could arise when the clock is set backwards in time or if the node ID
 *     changes
 *
 * @return string Version 6 UUID as a string
 */
function v6(?Hexadecimal $node = null, ?int $clockSeq = null): string
{
    return Uuid::uuid6($node, $clockSeq)->toString();
}
uuid/README.md000064400000005503147361033650007004 0ustar00# ramsey/uuid

[![Source Code][badge-source]][source]
[![Latest Version][badge-release]][release]
[![Software License][badge-license]][license]
[![PHP Version][badge-php]][php]
[![Build Status][badge-build]][build]
[![Coverage Status][badge-coverage]][coverage]
[![Total Downloads][badge-downloads]][downloads]

ramsey/uuid is a PHP library for generating and working with universally unique
identifiers (UUIDs).

This project adheres to a [Contributor Code of Conduct][conduct]. By
participating in this project and its community, you are expected to uphold this
code.

Much inspiration for this library came from the [Java][javauuid] and
[Python][pyuuid] UUID libraries.


## Installation

The preferred method of installation is via [Composer][]. Run the following
command to install the package and add it as a requirement to your project's
`composer.json`:

```bash
composer require ramsey/uuid
```


## Upgrading to Version 4

See the documentation for a thorough upgrade guide:

* [Upgrading ramsey/uuid Version 3 to 4](https://uuid.ramsey.dev/en/latest/upgrading/3-to-4.html)


## Documentation

Please see <https://uuid.ramsey.dev> for documentation, tips, examples, and
frequently asked questions.


## Contributing

Contributions are welcome! Please read [CONTRIBUTING.md][] for details.


## Copyright and License

The ramsey/uuid library is copyright © [Ben Ramsey](https://benramsey.com/) and
licensed for use under the MIT License (MIT). Please see [LICENSE][] for more
information.


[rfc4122]: http://tools.ietf.org/html/rfc4122
[conduct]: https://github.com/ramsey/uuid/blob/master/.github/CODE_OF_CONDUCT.md
[javauuid]: http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html
[pyuuid]: http://docs.python.org/3/library/uuid.html
[composer]: http://getcomposer.org/
[contributing.md]: https://github.com/ramsey/uuid/blob/master/.github/CONTRIBUTING.md

[badge-source]: https://img.shields.io/badge/source-ramsey/uuid-blue.svg?style=flat-square
[badge-release]: https://img.shields.io/packagist/v/ramsey/uuid.svg?style=flat-square&label=release
[badge-license]: https://img.shields.io/packagist/l/ramsey/uuid.svg?style=flat-square
[badge-php]: https://img.shields.io/packagist/php-v/ramsey/uuid.svg?style=flat-square
[badge-build]: https://img.shields.io/travis/ramsey/uuid/master.svg?style=flat-square
[badge-coverage]: https://img.shields.io/coveralls/github/ramsey/uuid/master.svg?style=flat-square
[badge-downloads]: https://img.shields.io/packagist/dt/ramsey/uuid.svg?style=flat-square&colorB=mediumvioletred

[source]: https://github.com/ramsey/uuid
[release]: https://packagist.org/packages/ramsey/uuid
[license]: https://github.com/ramsey/uuid/blob/master/LICENSE
[php]: https://php.net
[build]: https://travis-ci.org/ramsey/uuid
[coverage]: https://coveralls.io/github/ramsey/uuid?branch=master
[downloads]: https://packagist.org/packages/ramsey/uuid
uuid/CHANGELOG.md000064400000135536147361033650007350 0ustar00# ramsey/uuid Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).


## [Unreleased]

### Added

### Changed

### Deprecated

### Removed

### Fixed

### Security


## [4.0.1] - 2020-03-29

### Fixed

* Fix collection deserialization errors due to upstream `allowed_classes` being
  set to `false`. For details, see [ramsey/uuid#303](https://github.com/ramsey/uuid/issues/303)
  and [ramsey/collection#47](https://github.com/ramsey/collection/issues/47).


## [4.0.0] - 2020-03-22

### Added

* Add support for version 6 UUIDs, as defined by <http://gh.peabody.io/uuidv6/>,
  including the static method `Uuid::uuid6()`, which returns a
  `Nonstandard\UuidV6` instance.
* Add ability to generate version 2 (DCE Security) UUIDs, including the static
  method `Uuid::uuid2()`, which returns an `Rfc4122\UuidV2` instance.
* Add classes to represent each version of RFC 4122 UUID. When generating new
  UUIDs or creating UUIDs from existing strings, bytes, or integers, if the UUID
  is an RFC 4122 variant, one of these instances will be returned:
  * `Rfc4122\UuidV1`
  * `Rfc4122\UuidV2`
  * `Rfc4122\UuidV3`
  * `Rfc4122\UuidV4`
  * `Rfc4122\UuidV5`
  * `Rfc4122\NilUuid`
* Add classes to represent version 6 UUIDs, GUIDs, and nonstandard
  (non-RFC 4122 variant) UUIDs:
  * `Nonstandard\UuidV6`
  * `Guid\Guid`
  * `Nonstandard\Uuid`
* Add `Uuid::fromDateTime()` to create version 1 UUIDs from instances of
  `\DateTimeInterface`.
* The `\DateTimeInterface` instance returned by `UuidInterface::getDateTime()`
  (and now `Rfc4122\UuidV1::getDateTime()`) now includes microseconds, as
  specified by the version 1 UUID.
* Add `Validator\ValidatorInterface` and `Validator\GenericValidator` to allow
  flexibility in validating UUIDs/GUIDs.
  * The default validator continues to validate UUID strings using the same
    relaxed validation pattern found in the 3.x series of ramsey/uuid.
  * Introduce `Rfc4122\Validator` that may be used for strict validation of
    RFC 4122 UUID strings.
  * Add ability to change the default validator used by `Uuid` through
    `FeatureSet::setValidator()`.
  * Add `getValidator()` and `setValidator()` to `UuidFactory`.
* Add `Provider\Node\StaticNodeProvider` to assist in setting a custom static
  node value with the multicast bit set for version 1 UUIDs.
* Add the following new exceptions:
  * `Exception\BuilderNotFoundException` -
    Thrown to indicate that no suitable UUID builder could be found.
  * `Exception\DateTimeException` -
    Thrown to indicate that the PHP DateTime extension encountered an
    exception/error.
  * `Exception\DceSecurityException` -
    Thrown to indicate an exception occurred while dealing with DCE Security
    (version 2) UUIDs.
  * `Exception\InvalidArgumentException` -
    Thrown to indicate that the argument received is not valid. This extends the
    built-in PHP `\InvalidArgumentException`, so there should be no BC breaks
    with ramsey/uuid throwing this exception, if you are catching the PHP
    exception.
  * `Exception\InvalidBytesException` -
    Thrown to indicate that the bytes being operated on are invalid in some way.
  * `Exception\NameException` -
    Thrown to indicate that an error occurred while attempting to hash a
    namespace and name.
  * `Exception\NodeException` -
    Throw to indicate that attempting to fetch or create a node ID encountered
    an error.
  * `Exception\RandomSourceException` -
    Thrown to indicate that the source of random data encountered an error.
  * `Exception\TimeSourceException` -
    Thrown to indicate that the source of time encountered an error.
  * `Exception\UnableToBuildUuidException` -
    Thrown to indicate a builder is unable to build a UUID.
* Introduce a `Builder\FallbackBuilder`, used by `FeatureSet` to help decide
  whether to return a `Uuid` or `Nonstandard\Uuid` when decoding a
  UUID string or bytes.
* Add `Rfc4122\UuidInterface` to specifically represent RFC 4122 variant UUIDs.
* Add `Rfc4122\UuidBuilder` to build RFC 4122 variant UUIDs. This replaces the
  existing `Builder\DefaultUuidBuilder`, which is now deprecated.
* Introduce `Math\CalculatorInterface` for representing calculators to perform
  arithmetic operations on integers.
* Depend on [brick/math](https://github.com/brick/math) for the
  `Math\BrickMathCalculator`, which is the default calculator used by this
  library when math cannot be performed in native PHP due to integer size
  limitations. The calculator is configurable and may be changed, if desired.
* Add `Converter\Number\GenericNumberConverter` and
  `Converter\Time\GenericTimeConverter` which will use the calculator provided
  to convert numbers and time to values for UUIDs.
* Introduce `Type\Hexadecimal`, `Type\Integer`, `Type\Decimal`, and `Type\Time`
  for improved type-safety when dealing with arbitrary string values.
* Add a `Type\TypeInterface` that each of the ramsey/uuid types implements.
* Add `Fields\FieldsInterface` and `Rfc4122\FieldsInterface` to define
  field layouts for UUID variants. The implementations `Rfc4122\Fields`,
  `Guid\Fields`, and `Nonstandard\Fields` store the 16-byte,
  binary string representation of the UUID internally, and these manage
  conversion of the binary string into the hexadecimal field values.
* Introduce `Builder\BuilderCollection` and `Provider\Node\NodeProviderCollection`.
  These are typed collections for providing builders and node providers to
  `Builder\FallbackBuilder` and `Provider\Node\FallbackNodeProvider`, respectively.
* Add `Generator\NameGeneratorInterface` to support alternate methods of
  generating bytes for version 3 and version 5 name-based UUID. By default,
  ramsey/uuid uses the `Generator\DefaultNameGenerator`, which uses the standard
  algorithm this library has used since the beginning. You may choose to use the
  new `Generator\PeclUuidNameGenerator` to make use of the new
  `uuid_generate_md5()` and `uuid_generate_sha1()` functions in
  [ext-uuid version 1.1.0](https://pecl.php.net/package/uuid).

### Changed

* Set minimum required PHP version to 7.2.
* This library now works on 32-bit and 64-bit systems, with no degradation in
  functionality.
* By default, the following static methods will now return specific instance
  types. This should not cause any BC breaks if typehints target `UuidInterface`:
  * `Uuid::uuid1` returns `Rfc4122\UuidV1`
  * `Uuid::uuid3` returns `Rfc4122\UuidV3`
  * `Uuid::uuid4` returns `Rfc4122\UuidV4`
  * `Uuid::uuid5` returns `Rfc4122\UuidV5`
* Accept `Type\Hexadecimal` for the `$node` parameter for
  `UuidFactoryInterface::uuid1()`. This is in addition to the `int|string` types
  already accepted, so there are no BC breaks. `Type\Hexadecimal` is now the
  recommended type to pass for `$node`.
* Out of the box, `Uuid::fromString()`, `Uuid::fromBytes()`, and
  `Uuid::fromInteger()` will now return either an `Rfc4122\UuidInterface`
  instance or an instance of `Nonstandard\Uuid`, depending on whether the input
  contains an RFC 4122 variant UUID with a valid version identifier. Both
  implement `UuidInterface`, so BC breaks should not occur if typehints use the
  interface.
* Change `Uuid::getFields()` to return an instance of `Fields\FieldsInterface`.
  Previously, it returned an array of integer values (on 64-bit systems only).
* `Uuid::getDateTime()` now returns an instance of `\DateTimeImmutable` instead
  of `\DateTime`.
* Make the following changes to `UuidInterface`:
  * `getHex()` now returns a `Type\Hexadecimal` instance.
  * `getInteger()` now returns a `Type\Integer` instance. The `Type\Integer`
    instance holds a string representation of a 128-bit integer. You may then
    use a math library of your choice (bcmath, gmp, etc.) to operate on the
    string integer.
  * `getDateTime()` now returns `\DateTimeInterface` instead of `\DateTime`.
  * Add `__toString()` method.
  * Add `getFields()` method. It returns an instance of `Fields\FieldsInterface`.
* Add the following new methods to `UuidFactoryInterface`:
  * `uuid2()`
  * `uuid6()`
  * `fromDateTime()`
  * `fromInteger()`
  * `getValidator()`
* This library no longer throws generic exceptions. However, this should not
  result in BC breaks, since the new exceptions extend from built-in PHP
  exceptions that this library previously threw.
  * `Exception\UnsupportedOperationException` is now descended from
    `\LogicException`. Previously, it descended from `\RuntimeException`.
* Change required constructor parameters for `Uuid`:
  * Change the first required constructor parameter for `Uuid` from
    `array $fields` to `Rfc4122\FieldsInterface $fields`.
  * Add `Converter\TimeConverterInterface $timeConverter` as the fourth
    required constructor parameter for `Uuid`.
* Change the second required parameter of `Builder\UuidBuilderInterface::build()`
  from `array $fields` to `string $bytes`. Rather than accepting an array of
  hexadecimal strings as UUID fields, the `build()` method now expects a byte
  string.
* Add `Converter\TimeConverterInterface $timeConverter` as the second required
  constructor parameter for `Rfc4122\UuidBuilder`. This also affects the
  now-deprecated `Builder\DefaultUuidBuilder`, since this class now inherits
  from `Rfc4122\UuidBuilder`.
* Add `convertTime()` method to `Converter\TimeConverterInterface`.
* Add `getTime()` method to `Provider\TimeProviderInterface`. It replaces the
  `currentTime()` method.
* `Provider\Node\FallbackNodeProvider` now accepts only a
  `Provider\Node\NodeProviderCollection` as its constructor parameter.
* `Provider\Time\FixedTimeProvider` no longer accepts an array but accepts only
  `Type\Time` instances.
* `Provider\NodeProviderInterface::getNode()` now returns `Type\Hexadecimal`
  instead of `string|false|null`.
* `Converter/TimeConverterInterface::calculateTime()` now returns
  `Type\Hexadecimal` instead of `array`. The value is the full UUID timestamp
  value (count of 100-nanosecond intervals since the Gregorian calendar epoch)
  in hexadecimal format.
* Change methods in `NumberConverterInterface` to accept and return string values
  instead of `mixed`; this simplifies the interface and makes it consistent.
* `Generator\DefaultTimeGenerator` no longer adds the variant and version bits
  to the bytes it returns. These must be applied to the bytes afterwards.
* When encoding to bytes or decoding from bytes, `OrderedTimeCodec` now checks
  whether the UUID is an RFC 4122 variant, version 1 UUID. If not, it will throw
  an exception—`InvalidArgumentException` when using
  `OrderedTimeCodec::encodeBinary()` and `UnsupportedOperationException` when
  using `OrderedTimeCodec::decodeBytes()`.

### Deprecated

The following functionality is deprecated and will be removed in ramsey/uuid
5.0.0.

* The following methods from `UuidInterface` and `Uuid` are deprecated. Use their
  counterparts on the `Rfc4122\FieldsInterface` returned by `Uuid::getFields()`.
  * `getClockSeqHiAndReservedHex()`
  * `getClockSeqLowHex()`
  * `getClockSequenceHex()`
  * `getFieldsHex()`
  * `getNodeHex()`
  * `getTimeHiAndVersionHex()`
  * `getTimeLowHex()`
  * `getTimeMidHex()`
  * `getTimestampHex()`
  * `getVariant()`
  * `getVersion()`
* The following methods from `Uuid` are deprecated. Use the `Rfc4122\FieldsInterface`
  instance returned by `Uuid::getFields()` to get the `Type\Hexadecimal` value
  for these fields. You may use the new `Math\CalculatorInterface::toIntegerValue()`
  method to convert the `Type\Hexadecimal` instances to instances of
  `Type\Integer`. This library provides `Math\BrickMathCalculator`, which may be
  used for this purpose, or you may use the arbitrary-precision arithemetic
  library of your choice.
  * `getClockSeqHiAndReserved()`
  * `getClockSeqLow()`
  * `getClockSequence()`
  * `getNode()`
  * `getTimeHiAndVersion()`
  * `getTimeLow()`
  * `getTimeMid()`
  * `getTimestamp()`
* `getDateTime()` on `UuidInterface` and `Uuid` is deprecated. Use this method
  only on instances of `Rfc4122\UuidV1` or `Nonstandard\UuidV6`.
* `getUrn()` on `UuidInterface` and `Uuid` is deprecated. It is available on
  `Rfc4122\UuidInterface` and classes that implement it.
* The following methods are deprecated and have no direct replacements. However,
  you may obtain the same information by calling `UuidInterface::getHex()` and
  splitting the return value in half.
  * `UuidInterface::getLeastSignificantBitsHex()`
  * `UuidInterface::getMostSignificantBitsHex()`
  * `Uuid::getLeastSignificantBitsHex()`
  * `Uuid::getMostSignificantBitsHex()`
  * `Uuid::getLeastSignificantBits()`
  * `Uuid::getMostSignificantBits()`
* `UuidInterface::getNumberConverter()` and `Uuid::getNumberConverter()` are
  deprecated. There is no alternative recommendation, so plan accordingly.
* `Builder\DefaultUuidBuilder` is deprecated; transition to `Rfc4122\UuidBuilder`.
* `Converter\Number\BigNumberConverter` is deprecated; transition to
  `Converter\Number\GenericNumberConverter`.
* `Converter\Time\BigNumberTimeConverter` is deprecated; transition to
  `Converter\Time\GenericTimeConverter`.
* The classes for representing and generating *degraded* UUIDs are deprecated.
  These are no longer necessary; this library now behaves the same on 32-bit and
  64-bit systems.
  * `Builder\DegradedUuidBuilder`
  * `Converter\Number\DegradedNumberConverter`
  * `Converter\Time\DegradedTimeConverter`
  * `DegradedUuid`
* The `Uuid::UUID_TYPE_IDENTIFIER` constant is deprecated. Use
  `Uuid::UUID_TYPE_DCE_SECURITY` instead.
* The `Uuid::VALID_PATTERN` constant is deprecated. Use
  `Validator\GenericValidator::getPattern()` or `Rfc4122\Validator::getPattern()`
  instead.

### Removed

* Remove the following bytes generators and recommend
  `Generator\RandomBytesGenerator` as a suitable replacement:
  * `Generator\MtRandGenerator`
  * `Generator\OpenSslGenerator`
  * `Generator\SodiumRandomGenerator`
* Remove `Exception\UnsatisfiedDependencyException`. This library no longer
  throws this exception.
* Remove the method `Provider\TimeProviderInterface::currentTime()`. Use
  `Provider\TimeProviderInterface::getTime()` instead.


## [4.0.0-beta2] - 2020-03-01

## Added

* Add missing convenience methods for `Rfc4122\UuidV2`.
* Add `Provider\Node\StaticNodeProvider` to assist in setting a custom static
  node value with the multicast bit set for version 1 UUIDs.

## Changed

* `Provider\NodeProviderInterface::getNode()` now returns `Type\Hexadecimal`
  instead of `string|false|null`.


## [4.0.0-beta1] - 2020-02-27

### Added

* Add `ValidatorInterface::getPattern()` to return the regular expression
  pattern used by the validator.
* Add `v6()` helper function for version 6 UUIDs.

### Changed

* Set the pattern constants on validators as `private`. Use the `getPattern()`
  method instead.
* Change the `$node` parameter for `UuidFactoryInterface::uuid6()` to accept
  `null` or `Type\Hexadecimal`.
* Accept `Type\Hexadecimal` for the `$node` parameter for
  `UuidFactoryInterface::uuid1()`. This is in addition to the `int|string` types
  already accepted, so there are no BC breaks. `Type\Hexadecimal` is now the
  recommended type to pass for `$node`.

### Removed

* Remove `currentTime()` method from `Provider\Time\FixedTimeProvider` and
  `Provider\Time\SystemTimeProvider`; it had previously been removed from
  `Provider\TimeProviderInterface`.


## [4.0.0-alpha5] - 2020-02-23

### Added

* Introduce `Builder\BuilderCollection` and `Provider\Node\NodeProviderCollection`.

### Changed

* `Builder\FallbackBuilder` now accepts only a `Builder\BuilderCollection` as
  its constructor parameter.
* `Provider\Node\FallbackNodeProvider` now accepts only a `Provider\Node\NodeProviderCollection`
  as its constructor parameter.
* `Provider\Time\FixedTimeProvider` no longer accepts an array but accepts only
  `Type\Time` instances.


## [4.0.0-alpha4] - 2020-02-23

### Added

* Add a `Type\TypeInterface` that each of the ramsey/uuid types implements.
* Support version 6 UUIDs; see <http://gh.peabody.io/uuidv6/>.

### Changed

* Rename `Type\IntegerValue` to `Type\Integer`. It was originally named
  `IntegerValue` because static analysis sees `Integer` in docblock annotations
  and treats it as the native `int` type. `Integer` is not a reserved word in
  PHP, so it should be named `Integer` for consistency with other types in this
  library. When using it, a class alias prevents static analysis from
  complaining.
* Mark `Guid\Guid` and `Nonstandard\Uuid` classes as `final`.
* Add `uuid6()` method to `UuidFactoryInterface`.

### Deprecated

* `Uuid::UUID_TYPE_IDENTIFIER` is deprecated. Use `Uuid::UUID_TYPE_DCE_SECURITY`
  instead.
* `Uuid::VALID_PATTERN` is deprecated. Use `Validator\GenericValidator::VALID_PATTERN`
  instead.


## [4.0.0-alpha3] - 2020-02-21

### Fixed

* Fix microsecond rounding error on 32-bit systems.


## [4.0.0-alpha2] - 2020-02-21

### Added

* Add `Uuid::fromDateTime()` to create version 1 UUIDs from instances of
  `\DateTimeInterface`.
* Add `Generator\NameGeneratorInterface` to support alternate methods of
  generating bytes for version 3 and version 5 name-based UUID. By default,
  ramsey/uuid uses the `Generator\DefaultNameGenerator`, which uses the standard
  algorithm this library has used since the beginning. You may choose to use the
  new `Generator\PeclUuidNameGenerator` to make use of the new
  `uuid_generate_md5()` and `uuid_generate_sha1()` functions in ext-uuid version
  1.1.0.

### Changed

* Add `fromDateTime()` method to `UuidFactoryInterface`.
* Change `UuidInterface::getHex()` to return a `Ramsey\Uuid\Type\Hexadecimal` instance.
* Change `UuidInterface::getInteger()` to return a `Ramsey\Uuid\Type\IntegerValue` instance.

### Fixed

* Round microseconds to six digits when getting DateTime from v1 UUIDs. This
  circumvents a needless exception for an otherwise valid time-based UUID.


## [4.0.0-alpha1] - 2020-01-22

### Added

* Add `Validator\ValidatorInterface` and `Validator\GenericValidator` to allow
  flexibility in validating UUIDs/GUIDs.
  * Add ability to change the default validator used by `Uuid` through
    `FeatureSet::setValidator()`.
  * Add `getValidator()` and `setValidator()` to `UuidFactory`.
* Add an internal `InvalidArgumentException` that descends from the built-in
  PHP `\InvalidArgumentException`. All places that used to throw
  `\InvalidArgumentException` now throw `Ramsey\Uuid\Exception\InvalidArgumentException`.
  This should not cause any BC breaks, however.
* Add an internal `DateTimeException` that descends from the built-in PHP
  `\RuntimeException`. `Uuid::getDateTime()` may throw this exception if
  `\DateTimeImmutable` throws an error or exception.
* Add `RandomSourceException` that descends from the built-in PHP
  `\RuntimeException`. `DefaultTimeGenerator`, `RandomBytesGenerator`, and
  `RandomNodeProvider` may throw this exception if `random_bytes()` or
  `random_int()` throw an error or exception.
* Add `Fields\FieldsInterface` and `Rfc4122\FieldsInterface` to define
  field layouts for UUID variants. The implementations `Rfc4122\Fields`,
  `Guid\Fields`, and `Nonstandard\Fields` store the 16-byte,
  binary string representation of the UUID internally, and these manage
  conversion of the binary string into the hexadecimal field values.
* Add `Rfc4122\UuidInterface` to specifically represent RFC 4122 variant UUIDs.
* Add classes to represent each version of RFC 4122 UUID. When generating new
  UUIDs or creating UUIDs from existing strings, bytes, or integers, if the UUID
  is an RFC 4122 variant, one of these instances will be returned:
  * `Rfc4122\UuidV1`
  * `Rfc4122\UuidV2`
  * `Rfc4122\UuidV3`
  * `Rfc4122\UuidV4`
  * `Rfc4122\UuidV5`
  * `Rfc4122\NilUuid`
* Add `Rfc4122\UuidBuilder` to build RFC 4122 variant UUIDs. This replaces the
  existing `Builder\DefaultUuidBuilder`, which is now deprecated.
* Add ability to generate version 2 (DCE Security) UUIDs, including the static
  method `Uuid::uuid2()`, which returns an `Rfc4122\UuidV2` instance.
* Add classes to represent GUIDs and nonstandard (non-RFC 4122 variant) UUIDs:
  * `Guid\Guid`
  * `Nonstandard\Uuid`.
* Introduce a `Builder\FallbackBuilder`, used by `FeatureSet` to help decide
  whether to return a `Uuid` or `Nonstandard\Uuid` when decoding a
  UUID string or bytes.
* Introduce `Type\Hexadecimal`, `Type\IntegerValue`, and `Type\Time` for
  improved type-safety when dealing with arbitrary string values.
* Introduce `Math\CalculatorInterface` for representing calculators to perform
  arithmetic operations on integers.
* Depend on [brick/math](https://github.com/brick/math) for the
  `Math\BrickMathCalculator`, which is the default calculator used by this
  library when math cannot be performed in native PHP due to integer size
  limitations. The calculator is configurable and may be changed, if desired.
* Add `Converter\Number\GenericNumberConverter` and
  `Converter\Time\GenericTimeConverter` which will use the calculator provided
  to convert numbers and time to values for UUIDs.
* The `\DateTimeInterface` instance returned by `UuidInterface::getDateTime()`
  (and now `Rfc4122\UuidV1::getDateTime()`) now includes microseconds, as
  specified by the version 1 UUID.

### Changed

* Set minimum required PHP version to 7.2.
* Add `__toString()` method to `UuidInterface`.
* The `UuidInterface::getDateTime()` method now specifies `\DateTimeInterface`
  as the return value, rather than `\DateTime`; `Uuid::getDateTime()` now
  returns an instance of `\DateTimeImmutable` instead of `\DateTime`.
* Add `getFields()` method to `UuidInterface`.
* Add `getValidator()` method to `UuidFactoryInterface`.
* Add `uuid2()` method to `UuidFactoryInterface`.
* Add `convertTime()` method to `Converter\TimeConverterInterface`.
* Add `getTime()` method to `Provider\TimeProviderInterface`.
* Change `Uuid::getFields()` to return an instance of `Fields\FieldsInterface`.
  Previously, it returned an array of integer values (on 64-bit systems only).
* Change the first required constructor parameter for `Uuid` from
  `array $fields` to `Rfc4122\FieldsInterface $fields`.
* Introduce `Converter\TimeConverterInterface $timeConverter` as fourth required
  constructor parameter for `Uuid` and second required constructor parameter for
  `Builder\DefaultUuidBuilder`.
* Change `UuidInterface::getInteger()` to always return a `string` value instead
  of `mixed`. This is a string representation of a 128-bit integer. You may then
  use a math library of your choice (bcmath, gmp, etc.) to operate on the
  string integer.
* Change the second required parameter of `Builder\UuidBuilderInterface::build()`
  from `array $fields` to `string $bytes`. Rather than accepting an array of
  hexadecimal strings as UUID fields, the `build()` method now expects a byte
  string.
* `Generator\DefaultTimeGenerator` no longer adds the variant and version bits
  to the bytes it returns. These must be applied to the bytes afterwards.
* `Converter/TimeConverterInterface::calculateTime()` now returns
  `Type\Hexadecimal` instead of `array`. The value is the full UUID timestamp
  value (count of 100-nanosecond intervals since the Gregorian calendar epoch)
  in hexadecimal format.
* Change methods in converter interfaces to accept and return string values
  instead of `mixed`; this simplifies the interface and makes it consistent:
  * `NumberConverterInterface::fromHex(string $hex): string`
  * `NumberConverterInterface::toHex(string $number): string`
  * `TimeConverterInterface::calculateTime(string $seconds, string $microseconds): array`
* `UnsupportedOperationException` is now descended from `\LogicException`.
  Previously, it descended from `\RuntimeException`.
* When encoding to bytes or decoding from bytes, `OrderedTimeCodec` now checks
  whether the UUID is an RFC 4122 variant, version 1 UUID. If not, it will throw
  an exception—`InvalidArgumentException` when using
  `OrderedTimeCodec::encodeBinary()` and `UnsupportedOperationException` when
  using `OrderedTimeCodec::decodeBytes()`.
* Out of the box, `Uuid::fromString()`, `Uuid::fromBytes()`, and
  `Uuid::fromInteger()` will now return either an `Rfc4122\UuidInterface`
  instance or an instance of `Nonstandard\Uuid`, depending on whether the input
  contains an RFC 4122 variant UUID with a valid version identifier. Both
  implement `UuidInterface`, so BC breaks should not occur if typehints use the
  interface.
* By default, the following static methods will now return the specific instance
  types. This should not cause any BC breaks if typehints target `UuidInterface`:
  * `Uuid::uuid1` returns `Rfc4122\UuidV1`
  * `Uuid::uuid3` returns `Rfc4122\UuidV3`
  * `Uuid::uuid4` returns `Rfc4122\UuidV4`
  * `Uuid::uuid5` returns `Rfc4122\UuidV5`

### Deprecated

The following functionality is deprecated and will be removed in ramsey/uuid
5.0.0.

* The following methods from `UuidInterface` and `Uuid` are deprecated. Use their
  counterparts on the `Rfc4122\FieldsInterface` returned by `Uuid::getFields()`.
  * `getClockSeqHiAndReservedHex()`
  * `getClockSeqLowHex()`
  * `getClockSequenceHex()`
  * `getFieldsHex()`
  * `getNodeHex()`
  * `getTimeHiAndVersionHex()`
  * `getTimeLowHex()`
  * `getTimeMidHex()`
  * `getTimestampHex()`
  * `getVariant()`
  * `getVersion()`
* The following methods from `Uuid` are deprecated. Use the `Rfc4122\FieldsInterface`
  instance returned by `Uuid::getFields()` to get the `Type\Hexadecimal` value
  for these fields, and then use the arbitrary-precision arithmetic library of
  your choice to convert them to string integers.
  * `getClockSeqHiAndReserved()`
  * `getClockSeqLow()`
  * `getClockSequence()`
  * `getNode()`
  * `getTimeHiAndVersion()`
  * `getTimeLow()`
  * `getTimeMid()`
  * `getTimestamp()`
* `getDateTime()` on `UuidInterface` and `Uuid` is deprecated. Use this method
  only on instances of `Rfc4122\UuidV1`.
* `getUrn()` on `UuidInterface` and `Uuid` is deprecated. It is available on
  `Rfc4122\UuidInterface` and classes that implement it.
* The following methods are deprecated and have no direct replacements. However,
  you may obtain the same information by calling `UuidInterface::getHex()` and
  splitting the return value in half.
  * `UuidInterface::getLeastSignificantBitsHex()`
  * `UuidInterface::getMostSignificantBitsHex()`
  * `Uuid::getLeastSignificantBitsHex()`
  * `Uuid::getMostSignificantBitsHex()`
  * `Uuid::getLeastSignificantBits()`
  * `Uuid::getMostSignificantBits()`
* `UuidInterface::getNumberConverter()` and `Uuid::getNumberConverter()` are
  deprecated. There is no alternative recommendation, so plan accordingly.
* `Builder\DefaultUuidBuilder` is deprecated; transition to
  `Rfc4122\UuidBuilder`.
* `Converter\Number\BigNumberConverter` is deprecated; transition to
  `Converter\Number\GenericNumberConverter`.
* `Converter\Time\BigNumberTimeConverter` is deprecated; transition to
  `Converter\Time\GenericTimeConverter`.
* `Provider\TimeProviderInterface::currentTime()` is deprecated; transition to
  the `getTimestamp()` method on the same interface.
* The classes for representing and generating *degraded* UUIDs are deprecated.
  These are no longer necessary; this library now behaves the same on 32-bit and
  64-bit PHP.
  * `Builder\DegradedUuidBuilder`
  * `Converter\Number\DegradedNumberConverter`
  * `Converter\Time\DegradedTimeConverter`
  * `DegradedUuid`

### Removed

* Remove the following bytes generators and recommend
  `Generator\RandomBytesGenerator` as a suitable replacement:
  * `Generator\MtRandGenerator`
  * `Generator\OpenSslGenerator`
  * `Generator\SodiumRandomGenerator`
* Remove `Exception\UnsatisfiedDependencyException`. This library no longer
  throws this exception.


## [3.9.3] - 2020-02-20

### Fixed

* For v1 UUIDs, round down for timestamps so that microseconds do not bump the
  timestamp to the next second.

  As an example, consider the case of timestamp `1` with  `600000` microseconds
  (`1.600000`). This is the first second after midnight on January 1, 1970, UTC.
  Previous versions of this library had a bug that would round this to `2`, so
  the rendered time was `1970-01-01 00:00:02`. This was incorrect. Despite
  having `600000` microseconds, the time should not round up to the next second.
  Rather, the time should be `1970-01-01 00:00:01.600000`. Since this version of
  ramsey/uuid does not support microseconds, the microseconds are dropped, and
  the time is `1970-01-01 00:00:01`. No rounding should occur.


## [3.9.2] - 2019-12-17

### Fixed

* Check whether files returned by `/sys/class/net/*/address` are readable
  before attempting to read them. This avoids a PHP warning that was being
  emitted on hosts that do not grant permission to read these files.


## [3.9.1] - 2019-12-01

### Fixed

* Fix `RandomNodeProvider` behavior on 32-bit systems. The `RandomNodeProvider`
  was converting a 6-byte string to a decimal number, which is a 48-bit,
  unsigned integer. This caused problems on 32-bit systems and has now been
  resolved.


## [3.9.0] - 2019-11-30

### Added

* Add function API as convenience. The functions are available in the
  `Ramsey\Uuid` namespace.
  * `v1(int|string|null $node = null, int|null $clockSeq = null): string`
  * `v3(string|UuidInterface $ns, string $name): string`
  * `v4(): string`
  * `v5(string|UuidInterface $ns, string $name): string`

### Changed

* Use paragonie/random-lib instead of ircmaxell/random-lib. This is a
  non-breaking change.
* Use a high-strength generator by default, when using `RandomLibAdapter`. This
  is a non-breaking change.

### Deprecated

These will be removed in ramsey/uuid version 4.0.0:

* `MtRandGenerator`, `OpenSslGenerator`, and `SodiumRandomGenerator` are
  deprecated in favor of using the default `RandomBytesGenerator`.

### Fixed

* Set `ext-json` as a required dependency in `composer.json`.
* Use `PHP_OS` instead of `php_uname()` when determining the system OS, for
  cases when `php_uname()` is disabled for security reasons.


## [3.8.0] - 2018-07-19

### Added

* Support discovery of MAC addresses on FreeBSD systems
* Use a polyfill to provide PHP ctype functions when running on systems where the
  ctype functions are not part of the PHP build
* Disallow a trailing newline character when validating UUIDs
* Annotate thrown exceptions for improved IDE hinting


## [3.7.3] - 2018-01-19

### Fixed

* Gracefully handle cases where `glob()` returns false when searching
  `/sys/class/net/*/address` files on Linux
* Fix off-by-one error in `DefaultTimeGenerator`

### Security

* Switch to `random_int()` from `mt_rand()` for better random numbers


## [3.7.2] - 2018-01-13

### Fixed

* Check sysfs on Linux to determine the node identifier; this provides a
  reliable way to identify the node on Docker images, etc.


## [3.7.1] - 2017-09-22

### Fixed

* Set the multicast bit for random nodes, according to RFC 4122, §4.5

### Security

* Use `random_bytes()` when generating random nodes


## [3.7.0] - 2017-08-04

### Added

* Add the following UUID version constants:
    * `Uuid::UUID_TYPE_TIME`
    * `Uuid::UUID_TYPE_IDENTIFIER`
    * `Uuid::UUID_TYPE_HASH_MD5`
    * `Uuid::UUID_TYPE_RANDOM`
    * `Uuid::UUID_TYPE_HASH_SHA1`


## [3.6.1] - 2017-03-26

### Fixed

* Optimize UUID string decoding by using `str_pad()` instead of `sprintf()`


## [3.6.0] - 2017-03-18

### Added

* Add `InvalidUuidStringException`, which is thrown when attempting to decode an
  invalid string UUID; this does not introduce any BC issues, since the new
  exception inherits from the previously used `InvalidArgumentException`

### Fixed

* Improve memory usage when generating large quantities of UUIDs (use `str_pad()`
  and `dechex()` instead of `sprintf()`)


## [3.5.2] - 2016-11-22

### Fixed

* Improve test coverage


## [3.5.1] - 2016-10-02

### Fixed

* Fix issue where the same UUIDs were not being treated as equal when using
  mixed cases


## [3.5.0] - 2016-08-02

### Added

* Add `OrderedTimeCodec` to store UUID in an optimized way for InnoDB

### Fixed

* Fix invalid node generation in `RandomNodeProvider`
* Avoid multiple unnecessary system calls by caching failed attempt to retrieve
  system node


## [3.4.1] - 2016-04-23

### Fixed

* Fix test that violated a PHP CodeSniffer rule, breaking the build


## [3.4.0] - 2016-04-23

### Added

* Add `TimestampFirstCombCodec` and `TimestampLastCombCodec` codecs to provide
  the ability to generate [COMB sequential UUIDs] with the timestamp encoded as
  either the first 48 bits or the last 48 bits
* Improve logic of `CombGenerator` for COMB sequential UUIDs


## [3.3.0] - 2016-03-22

### Security

* Drop the use of OpenSSL as a fallback and use [paragonie/random_compat] to
  support `RandomBytesGenerator` in versions of PHP earlier than 7.0;
  this addresses and fixes the [collision issue]


## [3.2.0] - 2016-02-17

### Added

* Add `SodiumRandomGenerator` to allow use of the [PECL libsodium extension] as
  a random bytes generator when creating UUIDs


## [3.1.0] - 2015-12-17

### Added

* Implement the PHP `Serializable` interface to provide the ability to
  serialize/unserialize UUID objects


## [3.0.1] - 2015-10-21

### Added

* Adopt the [Contributor Code of Conduct] for this project


## [3.0.0] - 2015-09-28

The 3.0.0 release represents a significant step for the ramsey/uuid library.
While the simple and familiar API used in previous versions remains intact, this
release provides greater flexibility to integrators, including the ability to
inject your own number generators, UUID codecs, node and time providers, and
more.

*Please note: The changelog for 3.0.0 includes all notes from the alpha and beta
versions leading up to this release.*

### Added

* Add a number of generators that may be used to override the library defaults
  for generating random bytes (version 4) or time-based (version 1) UUIDs
  * `CombGenerator` to allow generation of sequential UUIDs
  * `OpenSslGenerator` to generate random bytes on systems where
    `openssql_random_pseudo_bytes()` is present
  * `MtRandGenerator` to provide a fallback in the event other random generators
    are not present
  * `RandomLibAdapter` to allow use of [ircmaxell/random-lib]
  * `RandomBytesGenerator` for use with PHP 7; ramsey/uuid will default to use
    this generator when running on PHP 7
  * Refactor time-based (version 1) UUIDs into a `TimeGeneratorInterface` to
    allow for other sources to generate version 1 UUIDs in this library
  * `PeclUuidTimeGenerator` and `PeclUuidRandomGenerator` for creating version
    1 or version 4 UUIDs using the pecl-uuid extension
* Add a `setTimeGenerator` method on `UuidFactory` to override the default time
  generator
* Add option to enable `PeclUuidTimeGenerator` via `FeatureSet`
* Support GUID generation by configuring a `FeatureSet` to use GUIDs
* Allow UUIDs to be serialized as JSON through `JsonSerializable`

### Changed

* Change root namespace from "Rhumsaa" to "Ramsey;" in most cases, simply
  making this change in your applications is the only upgrade path you will
  need—everything else should work as expected
* No longer consider `Uuid` class as `final`; everything is now based around
  interfaces and factories, allowing you to use this package as a base to
  implement other kinds of UUIDs with different dependencies
* Return an object of type `DegradedUuid` on 32-bit systems to indicate that
  certain features are not available
* Default `RandomLibAdapter` to a medium-strength generator with
  [ircmaxell/random-lib]; this is configurable, so other generator strengths may
  be used

### Removed

* Remove `PeclUuidFactory` in favor of using pecl-uuid with generators
* Remove `timeConverter` and `timeProvider` properties, setters, and getters in
  both `FeatureSet` and `UuidFactory` as those are now exclusively used by the
  default `TimeGenerator`
* Move UUID [Doctrine field type] to [ramsey/uuid-doctrine]
* Move `uuid` console application to [ramsey/uuid-console]
* Remove `Uuid::VERSION` package version constant

### Fixed

* Improve GUID support to ensure that:
  * On little endian (LE) architectures, the byte order of the first three
    fields is LE
  * On big endian (BE) architectures, it is the same as a GUID
  * String representation is always the same
* Fix exception message for `DegradedNumberConverter::fromHex()`


## [3.0.0-beta1] - 2015-08-31

### Fixed

* Improve GUID support to ensure that:
  * On little endian (LE) architectures, the byte order of the first three
    fields is LE
  * On big endian (BE) architectures, it is the same as a GUID
  * String representation is always the same
* Fix exception message for `DegradedNumberConverter::fromHex()`


## [3.0.0-alpha3] - 2015-07-28

### Added

* Enable use of custom `TimeGenerator` implementations
* Add a `setTimeGenerator` method on `UuidFactory` to override the default time
  generator
* Add option to enable `PeclUuidTimeGenerator` via `FeatureSet`

### Removed

* Remove `timeConverter` and `timeProvider` properties, setters, and getters in
  both `FeatureSet` and `UuidFactory` as those are now exclusively used by the
  default `TimeGenerator`


## [3.0.0-alpha2] - 2015-07-28

### Added

* Refactor time-based (version 1) UUIDs into a `TimeGeneratorInterface` to allow
  for other sources to generate version 1 UUIDs in this library
* Add `PeclUuidTimeGenerator` and `PeclUuidRandomGenerator` for creating version
  1 or version 4 UUIDs using the pecl-uuid extension
* Add `RandomBytesGenerator` for use with PHP 7. ramsey/uuid will default to use
  this generator when running on PHP 7

### Changed

* Default `RandomLibAdapter` to a medium-strength generator with
  [ircmaxell/random-lib]; this is configurable, so other generator strengths may
  be used

### Removed

* Remove `PeclUuidFactory` in favor of using pecl-uuid with generators


## [3.0.0-alpha1] - 2015-07-16

### Added

* Allow dependency injection through `UuidFactory` and/or extending `FeatureSet`
  to override any package defaults
* Add a number of generators that may be used to override the library defaults:
  * `CombGenerator` to allow generation of sequential UUIDs
  * `OpenSslGenerator` to generate random bytes on systems where
    `openssql_random_pseudo_bytes()` is present
  * `MtRandGenerator` to provide a fallback in the event other random generators
    are not present
  * `RandomLibAdapter` to allow use of [ircmaxell/random-lib]
* Support GUID generation by configuring a `FeatureSet` to use GUIDs
* Allow UUIDs to be serialized as JSON through `JsonSerializable`

### Changed

* Change root namespace from "Rhumsaa" to "Ramsey;" in most cases, simply
  making this change in your applications is the only upgrade path you will
  need—everything else should work as expected
* No longer consider `Uuid` class as `final`; everything is now based around
  interfaces and factories, allowing you to use this package as a base to
  implement other kinds of UUIDs with different dependencies
* Return an object of type `DegradedUuid` on 32-bit systems to indicate that
  certain features are not available

### Removed

* Move UUID [Doctrine field type] to [ramsey/uuid-doctrine]
* Move `uuid` console application to [ramsey/uuid-console]
* Remove `Uuid::VERSION` package version constant


## [2.9.0] - 2016-03-22

### Security

* Drop the use of OpenSSL as a fallback and use [paragonie/random_compat] to
  support `RandomBytesGenerator` in versions of PHP earlier than 7.0;
  this addresses and fixes the [collision issue]


## [2.8.4] - 2015-12-17

### Added

* Add support for symfony/console v3 in the `uuid` CLI application


## [2.8.3] - 2015-08-31

### Fixed

* Fix exception message in `Uuid::calculateUuidTime()`


## [2.8.2] - 2015-07-23

### Fixed

* Ensure the release tag makes it into the rhumsaa/uuid package


## [2.8.1] - 2015-06-16

### Fixed

* Use `passthru()` and output buffering in `getIfconfig()`
* Cache the system node in a static variable so that we process it only once per
  runtime


## [2.8.0] - 2014-11-09

### Added

* Add static `fromInteger()` method to create UUIDs from string integer or
  `Moontoast\Math\BigNumber`

### Fixed

* Improve Doctrine conversion to Uuid or string for the ramsey/uuid [Doctrine field type]


## [2.7.4] - 2014-10-29

### Fixed

* Change loop in `generateBytes()` from `foreach` to `for`


## [2.7.3] - 2014-08-27

### Fixed

* Fix upper range for `mt_rand` used in version 4 UUIDs


## [2.7.2] - 2014-07-28

### Changed

* Upgrade to PSR-4 autoloading


## [2.7.1] - 2014-02-19

### Fixed

* Move moontoast/math and symfony/console to require-dev
* Support symfony/console 2.3 (LTS version)


## [2.7.0] - 2014-01-31

### Added

* Add `Uuid::VALID_PATTERN` constant containing a UUID validation regex pattern


## [2.6.1] - 2014-01-27

### Fixed

* Fix bug where `uuid` console application could not find the Composer
  autoloader when installed in another project


## [2.6.0] - 2014-01-17

### Added

* Introduce `uuid` console application for generating and decoding UUIDs from
  CLI (run `./bin/uuid` for details)
* Add `Uuid::getInteger()` to retrieve a `Moontoast\Math\BigNumber`
  representation of the 128-bit integer representing the UUID
* Add `Uuid::getHex()` to retrieve the hexadecimal representation of the UUID
* Use `netstat` on Linux to capture the node for a version 1 UUID
* Require moontoast/math as part of the regular package requirements


## [2.5.0] - 2013-10-30

### Added

* Use `openssl_random_pseudo_bytes()`, if available, to generate random bytes


## [2.4.0] - 2013-07-29

### Added

* Return `null` from `Uuid::getVersion()` if the UUID isn't an RFC 4122 variant
* Support string UUIDs without dashes passed to `Uuid::fromString()`


## [2.3.0] - 2013-07-16

### Added

* Support creation of UUIDs from bytes with `Uuid::fromBytes()`


## [2.2.0] - 2013-07-04

### Added

* Add `Doctrine\UuidType::requiresSQLCommentHint()` method


## [2.1.2] - 2013-07-03

### Fixed

* Fix cases where the system node was coming back with uppercase hexadecimal
  digits; this ensures that case in the node is converted to lowercase


## [2.1.1] - 2013-04-29

### Fixed

* Fix bug in `Uuid::isValid()` where the NIL UUID was not reported as valid


## [2.1.0] - 2013-04-15

### Added

* Allow checking the validity of a UUID through the `Uuid::isValid()` method


## [2.0.0] - 2013-02-11

### Added

* Support UUID generation on 32-bit platforms

### Changed

* Mark `Uuid` class `final`
* Require moontoast/math on 64-bit platforms for
  `Uuid::getLeastSignificantBits()` and `Uuid::getMostSignificantBits()`; the
  integers returned by these methods are *unsigned* 64-bit integers and
  unsupported even on 64-bit builds of PHP
* Move `UnsupportedOperationException` to the `Exception` subnamespace


## [1.1.2] - 2012-11-29

### Fixed

* Relax [Doctrine field type] conversion rules for UUIDs


## [1.1.1] - 2012-08-27

### Fixed

* Remove `final` keyword from `Uuid` class


## [1.1.0] - 2012-08-06

### Added

* Support ramsey/uuid UUIDs as a Doctrine Database Abstraction Layer (DBAL)
  field mapping type


## [1.0.0] - 2012-07-19

### Added

* Support generation of version 1, 3, 4, and 5 UUIDs


[comb sequential uuids]: http://www.informit.com/articles/article.aspx?p=25862&seqNum=7
[paragonie/random_compat]: https://github.com/paragonie/random_compat
[collision issue]: https://github.com/ramsey/uuid/issues/80
[contributor code of conduct]: https://github.com/ramsey/uuid/blob/master/.github/CODE_OF_CONDUCT.md
[pecl libsodium extension]: http://pecl.php.net/package/libsodium
[ircmaxell/random-lib]: https://github.com/ircmaxell/RandomLib
[doctrine field type]: http://doctrine-dbal.readthedocs.org/en/latest/reference/types.html
[ramsey/uuid-doctrine]: https://github.com/ramsey/uuid-doctrine
[ramsey/uuid-console]: https://github.com/ramsey/uuid-console

[unreleased]: https://github.com/ramsey/uuid/compare/4.0.1...HEAD
[4.0.1]: https://github.com/ramsey/uuid/compare/4.0.0...4.0.1
[4.0.0]: https://github.com/ramsey/uuid/compare/4.0.0-beta2...4.0.0
[4.0.0-beta2]: https://github.com/ramsey/uuid/compare/4.0.0-beta1...4.0.0-beta2
[4.0.0-beta1]: https://github.com/ramsey/uuid/compare/4.0.0-alpha5...4.0.0-beta1
[4.0.0-alpha5]: https://github.com/ramsey/uuid/compare/4.0.0-alpha4...4.0.0-alpha5
[4.0.0-alpha4]: https://github.com/ramsey/uuid/compare/4.0.0-alpha3...4.0.0-alpha4
[4.0.0-alpha3]: https://github.com/ramsey/uuid/compare/4.0.0-alpha2...4.0.0-alpha3
[4.0.0-alpha2]: https://github.com/ramsey/uuid/compare/4.0.0-alpha1...4.0.0-alpha2
[4.0.0-alpha1]: https://github.com/ramsey/uuid/compare/3.9.3...4.0.0-alpha1
[3.9.3]: https://github.com/ramsey/uuid/compare/3.9.2...3.9.3
[3.9.2]: https://github.com/ramsey/uuid/compare/3.9.1...3.9.2
[3.9.1]: https://github.com/ramsey/uuid/compare/3.9.0...3.9.1
[3.9.0]: https://github.com/ramsey/uuid/compare/3.8.0...3.9.0
[3.8.0]: https://github.com/ramsey/uuid/compare/3.7.3...3.8.0
[3.7.3]: https://github.com/ramsey/uuid/compare/3.7.2...3.7.3
[3.7.2]: https://github.com/ramsey/uuid/compare/3.7.1...3.7.2
[3.7.1]: https://github.com/ramsey/uuid/compare/3.7.0...3.7.1
[3.7.0]: https://github.com/ramsey/uuid/compare/3.6.1...3.7.0
[3.6.1]: https://github.com/ramsey/uuid/compare/3.6.0...3.6.1
[3.6.0]: https://github.com/ramsey/uuid/compare/3.5.2...3.6.0
[3.5.2]: https://github.com/ramsey/uuid/compare/3.5.1...3.5.2
[3.5.1]: https://github.com/ramsey/uuid/compare/3.5.0...3.5.1
[3.5.0]: https://github.com/ramsey/uuid/compare/3.4.1...3.5.0
[3.4.1]: https://github.com/ramsey/uuid/compare/3.4.0...3.4.1
[3.4.0]: https://github.com/ramsey/uuid/compare/3.3.0...3.4.0
[3.3.0]: https://github.com/ramsey/uuid/compare/3.2.0...3.3.0
[3.2.0]: https://github.com/ramsey/uuid/compare/3.1.0...3.2.0
[3.1.0]: https://github.com/ramsey/uuid/compare/3.0.1...3.1.0
[3.0.1]: https://github.com/ramsey/uuid/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/ramsey/uuid/compare/3.0.0-beta1...3.0.0
[3.0.0-beta1]: https://github.com/ramsey/uuid/compare/3.0.0-alpha3...3.0.0-beta1
[3.0.0-alpha3]: https://github.com/ramsey/uuid/compare/3.0.0-alpha2...3.0.0-alpha3
[3.0.0-alpha2]: https://github.com/ramsey/uuid/compare/3.0.0-alpha1...3.0.0-alpha2
[3.0.0-alpha1]: https://github.com/ramsey/uuid/compare/2.9.0...3.0.0-alpha1
[2.9.0]: https://github.com/ramsey/uuid/compare/2.8.4...2.9.0
[2.8.4]: https://github.com/ramsey/uuid/compare/2.8.3...2.8.4
[2.8.3]: https://github.com/ramsey/uuid/compare/2.8.2...2.8.3
[2.8.2]: https://github.com/ramsey/uuid/compare/2.8.1...2.8.2
[2.8.1]: https://github.com/ramsey/uuid/compare/2.8.0...2.8.1
[2.8.0]: https://github.com/ramsey/uuid/compare/2.7.4...2.8.0
[2.7.4]: https://github.com/ramsey/uuid/compare/2.7.3...2.7.4
[2.7.3]: https://github.com/ramsey/uuid/compare/2.7.2...2.7.3
[2.7.2]: https://github.com/ramsey/uuid/compare/2.7.1...2.7.2
[2.7.1]: https://github.com/ramsey/uuid/compare/2.7.0...2.7.1
[2.7.0]: https://github.com/ramsey/uuid/compare/2.6.1...2.7.0
[2.6.1]: https://github.com/ramsey/uuid/compare/2.6.0...2.6.1
[2.6.0]: https://github.com/ramsey/uuid/compare/2.5.0...2.6.0
[2.5.0]: https://github.com/ramsey/uuid/compare/2.4.0...2.5.0
[2.4.0]: https://github.com/ramsey/uuid/compare/2.3.0...2.4.0
[2.3.0]: https://github.com/ramsey/uuid/compare/2.2.0...2.3.0
[2.2.0]: https://github.com/ramsey/uuid/compare/2.1.2...2.2.0
[2.1.2]: https://github.com/ramsey/uuid/compare/2.1.1...2.1.2
[2.1.1]: https://github.com/ramsey/uuid/compare/2.1.0...2.1.1
[2.1.0]: https://github.com/ramsey/uuid/compare/2.0.0...2.1.0
[2.0.0]: https://github.com/ramsey/uuid/compare/1.1.2...2.0.0
[1.1.2]: https://github.com/ramsey/uuid/compare/1.1.1...1.1.2
[1.1.1]: https://github.com/ramsey/uuid/compare/1.1.0...1.1.1
[1.1.0]: https://github.com/ramsey/uuid/compare/1.0.0...1.1.0
[1.0.0]: https://github.com/ramsey/uuid/commits/1.0.0
uuid/LICENSE000064400000002104147361033650006524 0ustar00MIT License

Copyright (c) 2012-2020 Ben Ramsey <ben@benramsey.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
collection/src/Set.php000064400000003375147361033650010752 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

/**
 * A set is a collection that contains no duplicate elements.
 *
 * Great care must be exercised if mutable objects are used as set elements.
 * The behavior of a set is not specified if the value of an object is changed
 * in a manner that affects equals comparisons while the object is an element in
 * the set.
 *
 * Example usage:
 *
 * ``` php
 * $foo = new \My\Foo();
 * $set = new Set(\My\Foo::class);
 *
 * $set->add($foo); // returns TRUE, the element don't exists
 * $set->add($foo); // returns FALSE, the element already exists
 *
 * $bar = new \My\Foo();
 * $set->add($bar); // returns TRUE, $bar !== $foo
 * ```
 */
class Set extends AbstractSet
{
    /**
     * The type of elements stored in this set
     *
     * A set's type is immutable. For this reason, this property is private.
     *
     * @var string
     */
    private $setType;

    /**
     * Constructs a set object of the specified type, optionally with the
     * specified data.
     *
     * @param string $setType The type (FQCN) associated with this set.
     * @param mixed[] $data The initial items to store in the set.
     */
    public function __construct(string $setType, array $data = [])
    {
        $this->setType = $setType;
        parent::__construct($data);
    }

    /**
     * Returns the type associated with this set.
     */
    public function getType(): string
    {
        return $this->setType;
    }
}
collection/src/ArrayInterface.php000064400000001731147361033650013110 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

use ArrayAccess;
use Countable;
use IteratorAggregate;
use Serializable;

/**
 * `ArrayInterface` provides traversable array functionality to data types.
 */
interface ArrayInterface extends
    ArrayAccess,
    Countable,
    IteratorAggregate,
    Serializable
{
    /**
     * Removes all items from this array.
     */
    public function clear(): void;

    /**
     * Returns a native PHP array representation of this array object.
     *
     * @return mixed[]
     */
    public function toArray(): array;

    /**
     * Returns `true` if this array is empty.
     */
    public function isEmpty(): bool;
}
collection/src/Map/MapInterface.php000064400000010417147361033650013265 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Map;

use Ramsey\Collection\ArrayInterface;

/**
 * An object that maps keys to values.
 *
 * A map cannot contain duplicate keys; each key can map to at most one value.
 */
interface MapInterface extends ArrayInterface
{
    /**
     * Returns `true` if this map contains a mapping for the specified key.
     *
     * @param mixed $key The key to check in the map.
     */
    public function containsKey($key): bool;

    /**
     * Returns `true` if this map maps one or more keys to the specified value.
     *
     * This performs a strict type check on the value.
     *
     * @param mixed $value The value to check in the map.
     */
    public function containsValue($value): bool;

    /**
     * Return an array of the keys contained in this map.
     *
     * @return mixed[]
     */
    public function keys(): array;

    /**
     * Returns the value to which the specified key is mapped, `null` if this
     * map contains no mapping for the key, or (optionally) `$defaultValue` if
     * this map contains no mapping for the key.
     *
     * @param mixed $key The key to return from the map.
     * @param mixed $defaultValue The default value to use if `$key` is not found.
     *
     * @return mixed|null the value or `null` if the key could not be found.
     */
    public function get($key, $defaultValue = null);

    /**
     * Associates the specified value with the specified key in this map.
     *
     * If the map previously contained a mapping for the key, the old value is
     * replaced by the specified value.
     *
     * @param mixed $key The key to put or replace in the map.
     * @param mixed $value The value to store at `$key`.
     *
     * @return mixed|null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function put($key, $value);

    /**
     * Associates the specified value with the specified key in this map only if
     * it is not already set.
     *
     * If there is already a value associated with `$key`, this returns that
     * value without replacing it.
     *
     * @param mixed $key The key to put in the map.
     * @param mixed $value The value to store at `$key`.
     *
     * @return mixed|null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function putIfAbsent($key, $value);

    /**
     * Removes the mapping for a key from this map if it is present.
     *
     * @param mixed $key The key to remove from the map.
     *
     * @return mixed|null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function remove($key);

    /**
     * Removes the entry for the specified key only if it is currently mapped to
     * the specified value.
     *
     * This performs a strict type check on the value.
     *
     * @param mixed $key The key to remove from the map.
     * @param mixed $value The value to match.
     *
     * @return bool true if the value was removed.
     */
    public function removeIf($key, $value): bool;

    /**
     * Replaces the entry for the specified key only if it is currently mapped
     * to some value.
     *
     * @param mixed $key The key to replace.
     * @param mixed $value The value to set at `$key`.
     *
     * @return mixed|null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function replace($key, $value);

    /**
     * Replaces the entry for the specified key only if currently mapped to the
     * specified value.
     *
     * This performs a strict type check on the value.
     *
     * @param mixed $key The key to remove from the map.
     * @param mixed $oldValue The value to match.
     * @param mixed $newValue The value to use as a replacement.
     *
     * @return bool true if the value was replaced.
     */
    public function replaceIf($key, $oldValue, $newValue): bool;
}
collection/src/Map/TypedMap.php000064400000006575147361033650012464 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Map;

use Ramsey\Collection\Tool\TypeTrait;

/**
 * A `TypedMap` represents a map of elements where key and value are typed.
 *
 * Each element is identified by a key with defined type and a value of defined
 * type. The keys of the map must be unique. The values on the map can be=
 * repeated but each with its own different key.
 *
 * The most common case is to use a string type key, but it's not limited to
 * this type of keys.
 *
 * This is a direct implementation of `TypedMapInterface`, provided for the sake
 * of convenience.
 *
 * Example usage:
 *
 * ```php
 * $map = new TypedMap('string', Foo::class);
 * $map['x'] = new Foo();
 * foreach ($map as $key => $value) {
 *     // do something with $key, it will be a Foo::class
 * }
 *
 * // this will throw an exception since key must be string
 * $map[10] = new Foo();
 *
 * // this will throw an exception since value must be a Foo
 * $map['bar'] = 'bar';
 *
 * // initialize map with contents
 * $map = new TypedMap('string', Foo::class, [
 *     new Foo(), new Foo(), new Foo()
 * ]);
 * ```
 *
 * It is preferable to subclass `AbstractTypedMap` to create your own typed map
 * implementation:
 *
 * ```php
 * class FooTypedMap extends AbstractTypedMap
 * {
 *     public function getKeyType()
 *     {
 *         return 'int';
 *     }
 *
 *     public function getValueType()
 *     {
 *          return Foo::class;
 *     }
 * }
 * ```
 *
 * … but you also may use the `TypedMap` class:
 *
 * ```php
 * class FooTypedMap extends TypedMap
 * {
 *     public function __constructor(array $data = [])
 *     {
 *         parent::__construct('int', Foo::class, $data);
 *     }
 * }
 * ```
 */
class TypedMap extends AbstractTypedMap
{
    use TypeTrait;

    /**
     * The data type of keys stored in this collection.
     *
     * A map key's type is immutable once it is set. For this reason, this
     * property is set private.
     *
     * @var string data type of the map key.
     */
    private $keyType;

    /**
     * The data type of values stored in this collection.
     *
     * A map values's type is immutable once it is set. For this reason, this
     * property is set private.
     *
     * @var string data type of the map value.
     */
    private $valueType;

    /**
     * Constructs a map object of the specified key and value types,
     * optionally with the specified data.
     *
     * @param string $keyType The data type of the map's keys.
     * @param string $valueType The data type of the map's values.
     * @param mixed[] $data The initial data to set for this map.
     */
    public function __construct(string $keyType, string $valueType, array $data = [])
    {
        $this->keyType = $keyType;
        $this->valueType = $valueType;
        parent::__construct($data);
    }

    /**
     * Return the type used on the key.
     */
    public function getKeyType(): string
    {
        return $this->keyType;
    }

    /**
     * Return the type forced on the values.
     */
    public function getValueType(): string
    {
        return $this->valueType;
    }
}
collection/src/Map/TypedMapInterface.php000064400000001326147361033650014272 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Map;

/**
 * A `TypedMapInterface` represents a map of elements where key and value are
 * typed.
 */
interface TypedMapInterface extends MapInterface
{
    /**
     * Return the type used on the key.
     */
    public function getKeyType(): string;

    /**
     * Return the type forced on the values.
     */
    public function getValueType(): string;
}
collection/src/Map/AbstractMap.php000064400000014244147361033650013132 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Map;

use Ramsey\Collection\AbstractArray;
use Ramsey\Collection\Exception\InvalidArgumentException;

use function array_key_exists;
use function array_keys;
use function in_array;

/**
 * This class provides a basic implementation of `MapInterface`, to minimize the
 * effort required to implement this interface.
 */
abstract class AbstractMap extends AbstractArray implements MapInterface
{
    /**
     * Sets the given value to the given offset in the map.
     *
     * @param mixed $offset The offset to set.
     * @param mixed $value The value to set at the given offset.
     *
     * @throws InvalidArgumentException if the offset provided is `null`.
     */
    public function offsetSet($offset, $value): void
    {
        if ($offset === null) {
            throw new InvalidArgumentException(
                'Map elements are key/value pairs; a key must be provided for '
                . 'value ' . $value
            );
        }

        $this->data[$offset] = $value;
    }

    /**
     * Returns `true` if this map contains a mapping for the specified key.
     *
     * @param mixed $key The key to check in the map.
     */
    public function containsKey($key): bool
    {
        return array_key_exists($key, $this->data);
    }

    /**
     * Returns `true` if this map maps one or more keys to the specified value.
     *
     * This performs a strict type check on the value.
     *
     * @param mixed $value The value to check in the map.
     */
    public function containsValue($value): bool
    {
        return in_array($value, $this->data, true);
    }

    /**
     * Return an array of the keys contained in this map.
     *
     * @return mixed[]
     */
    public function keys(): array
    {
        return array_keys($this->data);
    }

    /**
     * Returns the value to which the specified key is mapped, `null` if this
     * map contains no mapping for the key, or (optionally) `$defaultValue` if
     * this map contains no mapping for the key.
     *
     * @param mixed $key The key to return from the map.
     * @param mixed $defaultValue The default value to use if `$key` is not found.
     *
     * @return mixed|null the value or `null` if the key could not be found.
     */
    public function get($key, $defaultValue = null)
    {
        if (!$this->containsKey($key)) {
            return $defaultValue;
        }

        return $this[$key];
    }

    /**
     * Associates the specified value with the specified key in this map.
     *
     * If the map previously contained a mapping for the key, the old value is
     * replaced by the specified value.
     *
     * @param mixed $key The key to put or replace in the map.
     * @param mixed $value The value to store at `$key`.
     *
     * @return mixed|null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function put($key, $value)
    {
        $previousValue = $this->get($key);
        $this[$key] = $value;

        return $previousValue;
    }

    /**
     * Associates the specified value with the specified key in this map only if
     * it is not already set.
     *
     * If there is already a value associated with `$key`, this returns that
     * value without replacing it.
     *
     * @param mixed $key The key to put in the map.
     * @param mixed $value The value to store at `$key`.
     *
     * @return mixed|null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function putIfAbsent($key, $value)
    {
        $currentValue = $this->get($key);

        if ($currentValue === null) {
            $this[$key] = $value;
        }

        return $currentValue;
    }

    /**
     * Removes the mapping for a key from this map if it is present.
     *
     * @param mixed $key The key to remove from the map.
     *
     * @return mixed|null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function remove($key)
    {
        $previousValue = $this->get($key);
        unset($this[$key]);

        return $previousValue;
    }

    /**
     * Removes the entry for the specified key only if it is currently mapped to
     * the specified value.
     *
     * This performs a strict type check on the value.
     *
     * @param mixed $key The key to remove from the map.
     * @param mixed $value The value to match.
     *
     * @return bool true if the value was removed.
     */
    public function removeIf($key, $value): bool
    {
        if ($this->get($key) === $value) {
            unset($this[$key]);

            return true;
        }

        return false;
    }

    /**
     * Replaces the entry for the specified key only if it is currently mapped
     * to some value.
     *
     * @param mixed $key The key to replace.
     * @param mixed $value The value to set at `$key`.
     *
     * @return mixed|null the previous value associated with key, or `null` if
     *     there was no mapping for `$key`.
     */
    public function replace($key, $value)
    {
        $currentValue = $this->get($key);

        if ($this->containsKey($key)) {
            $this[$key] = $value;
        }

        return $currentValue;
    }

    /**
     * Replaces the entry for the specified key only if currently mapped to the
     * specified value.
     *
     * This performs a strict type check on the value.
     *
     * @param mixed $key The key to remove from the map.
     * @param mixed $oldValue The value to match.
     * @param mixed $newValue The value to use as a replacement.
     *
     * @return bool true if the value was replaced.
     */
    public function replaceIf($key, $oldValue, $newValue): bool
    {
        if ($this->get($key) === $oldValue) {
            $this[$key] = $newValue;

            return true;
        }

        return false;
    }
}
collection/src/Map/NamedParameterMap.php000064400000006540147361033650014254 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Map;

use Ramsey\Collection\Exception\InvalidArgumentException;
use Ramsey\Collection\Tool\TypeTrait;
use Ramsey\Collection\Tool\ValueToStringTrait;

use function array_combine;
use function array_key_exists;
use function is_int;

/**
 * `NamedParameterMap` represents a mapping of values to a set of named keys
 * that may optionally be typed
 */
class NamedParameterMap extends AbstractMap
{
    use TypeTrait;
    use ValueToStringTrait;

    /**
     * Named parameters defined for this map.
     *
     * @var array<mixed, string>
     */
    protected $namedParameters;

    /**
     * Constructs a new `NamedParameterMap`.
     *
     * @param array<mixed, string> $namedParameters The named parameters defined for this map.
     * @param mixed[] $data An initial set of data to set on this map.
     */
    public function __construct(array $namedParameters, array $data = [])
    {
        $this->namedParameters = $this->filterNamedParameters($namedParameters);
        parent::__construct($data);
    }

    /**
     * Returns named parameters set for this `NamedParameterMap`.
     *
     * @return array<mixed, string>
     */
    public function getNamedParameters(): array
    {
        return $this->namedParameters;
    }

    /**
     * Sets the given value to the given offset in the map.
     *
     * @param mixed $offset The offset to set.
     * @param mixed $value The value to set at the given offset.
     *
     * @throws InvalidArgumentException if the offset provided is not a
     *     defined named parameter, or if the value is not of the type defined
     *     for the given named parameter.
     */
    public function offsetSet($offset, $value): void
    {
        if (!array_key_exists($offset, $this->namedParameters)) {
            throw new InvalidArgumentException(
                'Attempting to set value for unconfigured parameter \''
                . $offset . '\''
            );
        }

        if ($this->checkType($this->namedParameters[$offset], $value) === false) {
            throw new InvalidArgumentException(
                'Value for \'' . $offset . '\' must be of type '
                . $this->namedParameters[$offset] . '; value is '
                . $this->toolValueToString($value)
            );
        }

        $this->data[$offset] = $value;
    }

    /**
     * Given an array of named parameters, constructs a proper mapping of
     * named parameters to types.
     *
     * @param array<mixed, string> $namedParameters The named parameters to filter.
     *
     * @return array<mixed, string>
     */
    protected function filterNamedParameters(array $namedParameters): array
    {
        $names = [];
        $types = [];

        foreach ($namedParameters as $key => $value) {
            if (is_int($key)) {
                $names[] = (string) $value;
                $types[] = 'mixed';
            } else {
                $names[] = $key;
                $types[] = (string) $value;
            }
        }

        return array_combine($names, $types) ?: [];
    }
}
collection/src/Map/AssociativeArrayMap.php000064400000000770147361033650014637 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Map;

/**
 * `AssociativeArrayMap` represents a standard associative array object.
 */
class AssociativeArrayMap extends AbstractMap
{
}
collection/src/Map/AbstractTypedMap.php000064400000003342147361033650014135 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Map;

use Ramsey\Collection\Exception\InvalidArgumentException;
use Ramsey\Collection\Tool\TypeTrait;
use Ramsey\Collection\Tool\ValueToStringTrait;

/**
 * This class provides a basic implementation of `TypedMapInterface`, to
 * minimize the effort required to implement this interface.
 */
abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
{
    use TypeTrait;
    use ValueToStringTrait;

    /**
     * Sets the given value to the given offset in the map.
     *
     * @param mixed $offset The offset to set.
     * @param mixed $value The value to set at the given offset.
     *
     * @throws InvalidArgumentException if the offset or value do not match the
     *     expected types.
     */
    public function offsetSet($offset, $value): void
    {
        if ($this->checkType($this->getKeyType(), $offset) === false) {
            throw new InvalidArgumentException(
                'Key must be of type ' . $this->getKeyType() . '; key is '
                . $this->toolValueToString($offset)
            );
        }

        if ($this->checkType($this->getValueType(), $value) === false) {
            throw new InvalidArgumentException(
                'Value must be of type ' . $this->getValueType() . '; value is '
                . $this->toolValueToString($value)
            );
        }

        parent::offsetSet($offset, $value);
    }
}
collection/src/Queue.php000064400000013764147361033650011306 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

use Ramsey\Collection\Exception\InvalidArgumentException;
use Ramsey\Collection\Exception\NoSuchElementException;
use Ramsey\Collection\Tool\TypeTrait;
use Ramsey\Collection\Tool\ValueToStringTrait;

/**
 * This class provides a basic implementation of `QueueInterface`, to minimize
 * the effort required to implement this interface.
 */
class Queue extends AbstractArray implements QueueInterface
{
    use TypeTrait;
    use ValueToStringTrait;

    /**
     * The type of elements stored in this queue.
     *
     * A queue's type is immutable once it is set. For this reason, this
     * property is set private.
     *
     * @var string
     */
    private $queueType;

    /**
     * The index of the head of the queue.
     *
     * @var int
     */
    protected $index = 0;

    /**
     * Constructs a queue object of the specified type, optionally with the
     * specified data.
     *
     * @param string $queueType The type (FQCN) associated with this queue.
     * @param mixed[] $data The initial items to store in the collection.
     */
    public function __construct(string $queueType, array $data = [])
    {
        $this->queueType = $queueType;
        parent::__construct($data);
    }

    /**
     * Sets the given value to the given offset in the queue.
     *
     * Since arbitrary offsets may not be manipulated in a queue, this method
     * serves only to fulfill the `ArrayAccess` interface requirements. It is
     * invoked by other operations when adding values to the queue.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
     *
     * @param mixed|null $offset The offset is ignored and is treated as `null`.
     * @param mixed $value The value to set at the given offset.
     *
     * @throws InvalidArgumentException when the value does not match the
     *     specified type for this queue.
     */
    public function offsetSet($offset, $value): void
    {
        if ($this->checkType($this->getType(), $value) === false) {
            throw new InvalidArgumentException(
                'Value must be of type ' . $this->getType() . '; value is '
                . $this->toolValueToString($value)
            );
        }

        $this->data[] = $value;
    }

    /**
     * Ensures that this queue contains the specified element.
     *
     * This method differs from `offer()` only in that it throws an exception if
     * it cannot add the element to the queue.
     *
     * @see self::offer()
     *
     * @param mixed $element The element to add to this queue.
     *
     * @return bool `true` if this queue changed as a result of the call.
     *
     * @throws InvalidArgumentException when the element does not match the
     *     specified type for this queue.
     */
    public function add($element): bool
    {
        $this[] = $element;

        return true;
    }

    /**
     * Retrieves, but does not remove, the head of this queue.
     *
     * This method differs from `peek()` only in that it throws an exception if
     * this queue is empty.
     *
     * @see self::peek()
     *
     * @return mixed the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function element()
    {
        if ($this->count() === 0) {
            throw new NoSuchElementException(
                'Can\'t return element from Queue. Queue is empty.'
            );
        }

        return $this[$this->index];
    }

    /**
     * Inserts the specified element into this queue.
     *
     * This method differs from `add()` only in that it does not throw an
     * exception if it cannot add the element to the queue.
     *
     * @see self::add()
     *
     * @param mixed $element The element to add to this queue.
     *
     * @return bool `true` if the element was added to this queue, else `false`.
     */
    public function offer($element): bool
    {
        try {
            return $this->add($element);
        } catch (InvalidArgumentException $e) {
            return false;
        }
    }

    /**
     * Retrieves, but does not remove, the head of this queue, or returns `null`
     * if this queue is empty.
     *
     * @see self::element()
     *
     * @return mixed|null the head of this queue, or `null` if this queue is empty.
     */
    public function peek()
    {
        if ($this->count() === 0) {
            return null;
        }

        return $this[$this->index];
    }

    /**
     * Retrieves and removes the head of this queue, or returns `null`
     * if this queue is empty.
     *
     * @see self::remove()
     *
     * @return mixed|null the head of this queue, or `null` if this queue is empty.
     */
    public function poll()
    {
        if ($this->count() === 0) {
            return null;
        }

        $head = $this[$this->index];

        unset($this[$this->index]);
        $this->index++;

        return $head;
    }

    /**
     * Retrieves and removes the head of this queue.
     *
     * This method differs from `poll()` only in that it throws an exception if
     * this queue is empty.
     *
     * @see self::poll()
     *
     * @return mixed the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function remove()
    {
        if ($this->count() === 0) {
            throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
        }

        $head = $this[$this->index];

        unset($this[$this->index]);
        $this->index++;

        return $head;
    }

    /**
     * Returns the type associated with this queue.
     */
    public function getType(): string
    {
        return $this->queueType;
    }
}
collection/src/AbstractCollection.php000064400000024640147361033650013774 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

use Ramsey\Collection\Exception\CollectionMismatchException;
use Ramsey\Collection\Exception\InvalidArgumentException;
use Ramsey\Collection\Exception\InvalidSortOrderException;
use Ramsey\Collection\Exception\OutOfBoundsException;
use Ramsey\Collection\Exception\ValueExtractionException;
use Ramsey\Collection\Tool\TypeTrait;
use Ramsey\Collection\Tool\ValueExtractorTrait;
use Ramsey\Collection\Tool\ValueToStringTrait;

use function array_filter;
use function array_map;
use function array_merge;
use function array_search;
use function array_udiff;
use function array_uintersect;
use function current;
use function end;
use function in_array;
use function reset;
use function sprintf;
use function unserialize;
use function usort;

/**
 * This class provides a basic implementation of `CollectionInterface`, to
 * minimize the effort required to implement this interface
 */
abstract class AbstractCollection extends AbstractArray implements CollectionInterface
{
    use TypeTrait;
    use ValueToStringTrait;
    use ValueExtractorTrait;

    /**
     * Ensures that this collection contains the specified element.
     *
     * @param mixed $element The element to add to the collection.
     *
     * @return bool `true` if this collection changed as a result of the call.
     *
     * @throws InvalidArgumentException when the element does not match the
     *     specified type for this collection.
     */
    public function add($element): bool
    {
        $this[] = $element;

        return true;
    }

    /**
     * Returns `true` if this collection contains the specified element.
     *
     * @param mixed $element The element to check whether the collection contains.
     * @param bool $strict Whether to perform a strict type check on the value.
     */
    public function contains($element, bool $strict = true): bool
    {
        return in_array($element, $this->data, $strict);
    }

    /**
     * Sets the given value to the given offset in the array.
     *
     * @param mixed|null $offset The position to set the value in the array, or
     *     `null` to append the value to the array.
     * @param mixed $value The value to set at the given offset.
     *
     * @throws InvalidArgumentException when the value does not match the
     *     specified type for this collection.
     */
    public function offsetSet($offset, $value): void
    {
        if ($this->checkType($this->getType(), $value) === false) {
            throw new InvalidArgumentException(
                'Value must be of type ' . $this->getType() . '; value is '
                . $this->toolValueToString($value)
            );
        }

        if ($offset === null) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }

    /**
     * Removes a single instance of the specified element from this collection,
     * if it is present.
     *
     * @param mixed $element The element to remove from the collection.
     *
     * @return bool `true` if an element was removed as a result of this call.
     */
    public function remove($element): bool
    {
        if (($position = array_search($element, $this->data, true)) !== false) {
            unset($this->data[$position]);

            return true;
        }

        return false;
    }

    /**
     * Returns the values from given property or method.
     *
     * @param string $propertyOrMethod The property or method name to filter by.
     *
     * @return mixed[]
     *
     * @throws ValueExtractionException if property or method is not defined.
     */
    public function column(string $propertyOrMethod): array
    {
        $temp = [];

        foreach ($this->data as $item) {
            $temp[] = $this->extractValue($item, $propertyOrMethod);
        }

        return $temp;
    }

    /**
     * Returns the first item of the collection.
     *
     * @return mixed
     *
     * @throws OutOfBoundsException when the collection is empty.
     */
    public function first()
    {
        if ($this->isEmpty()) {
            throw new OutOfBoundsException('Can\'t determine first item. Collection is empty');
        }

        reset($this->data);

        return current($this->data);
    }

    /**
     * Returns the last item of the collection.
     *
     * @return mixed
     *
     * @throws OutOfBoundsException when the collection is empty.
     */
    public function last()
    {
        if ($this->isEmpty()) {
            throw new OutOfBoundsException('Can\'t determine last item. Collection is empty');
        }

        $item = end($this->data);
        reset($this->data);

        return $item;
    }

    /**
     * Returns a sorted collection.
     *
     * {@inheritdoc}
     *
     * @param string $propertyOrMethod The property or method to sort by.
     * @param string $order The sort order for the resulting collection (one of
     *     this interface's `SORT_*` constants).
     *
     * @return CollectionInterface<mixed, mixed>
     *
     * @throws InvalidSortOrderException if neither "asc" nor "desc" was given
     *     as the order.
     * @throws ValueExtractionException if property or method is not defined.
     */
    public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): CollectionInterface
    {
        if (!in_array($order, [self::SORT_ASC, self::SORT_DESC], true)) {
            throw new InvalidSortOrderException('Invalid sort order given: ' . $order);
        }

        $collection = clone $this;

        usort($collection->data, function ($a, $b) use ($propertyOrMethod, $order) {
            $aValue = $this->extractValue($a, $propertyOrMethod);
            $bValue = $this->extractValue($b, $propertyOrMethod);

            return ($aValue <=> $bValue) * ($order === self::SORT_DESC ? -1 : 1);
        });

        return $collection;
    }

    /**
     * Returns a filtered collection.
     *
     * {@inheritdoc}
     *
     * @param callable $callback A callable to use for filtering elements.
     *
     * @return CollectionInterface<mixed, mixed>
     */
    public function filter(callable $callback): CollectionInterface
    {
        $collection = clone $this;
        $collection->data = array_merge([], array_filter($collection->data, $callback));

        return $collection;
    }

    /**
     * Returns a collection of matching items.
     *
     * {@inheritdoc}
     *
     * @param string $propertyOrMethod The property or method to evaluate.
     * @param mixed  $value The value to match.
     *
     * @return CollectionInterface<mixed, mixed>
     *
     * @throws ValueExtractionException if property or method is not defined.
     */
    public function where(string $propertyOrMethod, $value): CollectionInterface
    {
        return $this->filter(function ($item) use ($propertyOrMethod, $value) {
            $accessorValue = $this->extractValue($item, $propertyOrMethod);

            return $accessorValue === $value;
        });
    }

    /**
     * Applies a callback to each item of the collection.
     *
     * {@inheritdoc}
     *
     * @param callable $callback A callable to apply to each item of the
     *     collection.
     *
     * @return CollectionInterface<mixed, mixed>
     */
    public function map(callable $callback): CollectionInterface
    {
        $collection = clone $this;
        array_map($callback, $collection->data);

        return $collection;
    }

    /**
     * Create a new collection with divergent items between current and given
     * collection.
     *
     * @param CollectionInterface<mixed, mixed> $other The collection to check for divergent
     *     items.
     *
     * @return CollectionInterface<mixed, mixed>
     *
     * @throws CollectionMismatchException if the given collection is not of the
     *     same type.
     */
    public function diff(CollectionInterface $other): CollectionInterface
    {
        if (!$other instanceof static) {
            throw new CollectionMismatchException('Collection must be of type ' . static::class);
        }

        $comparator = function ($a, $b) {
            return $a === $b ? 0 : -1;
        };

        $diffAtoB = array_udiff($this->data, $other->data, $comparator);
        $diffBtoA = array_udiff($other->data, $this->data, $comparator);

        return new static(array_merge($diffAtoB, $diffBtoA));
    }

    /**
     * Create a new collection with intersecting item between current and given
     * collection.
     *
     * @param CollectionInterface<mixed, mixed> $other The collection to check for
     *     intersecting items.
     *
     * @return CollectionInterface<mixed, mixed>
     *
     * @throws CollectionMismatchException if the given collection is not of the
     *     same type.
     */
    public function intersect(CollectionInterface $other): CollectionInterface
    {
        if (!$other instanceof static) {
            throw new CollectionMismatchException('Collection must be of type ' . static::class);
        }

        $intersect = array_uintersect($this->data, $other->data, function ($a, $b) {
            return $a === $b ? 0 : -1;
        });

        return new static($intersect);
    }

    /**
     * Merge current items and items of given collections into a new one.
     *
     * @param CollectionInterface<mixed, mixed> ...$collections The collections to merge.
     *
     * @return CollectionInterface<mixed, mixed>
     *
     * @throws CollectionMismatchException if any of the given collections are not of the same type.
     */
    public function merge(CollectionInterface ...$collections): CollectionInterface
    {
        $temp = [$this->data];

        foreach ($collections as $index => $collection) {
            if (!$collection instanceof static) {
                throw new CollectionMismatchException(
                    sprintf('Collection with index %d must be of type %s', $index, static::class)
                );
            }

            $temp[] = $collection->toArray();
        }

        return new static(array_merge(...$temp));
    }

    /**
     * @inheritDoc
     */
    public function unserialize($serialized): void
    {
        $this->data = unserialize($serialized, ['allowed_classes' => [$this->getType()]]);
    }
}
collection/src/QueueInterface.php000064400000016204147361033650013117 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

use Ramsey\Collection\Exception\NoSuchElementException;

/**
 * A queue is a collection in which the entities in the collection are kept in
 * order.
 *
 * The principal operations on the queue are the addition of entities to the end
 * (tail), also known as *enqueue*, and removal of entities from the front
 * (head), also known as *dequeue*. This makes the queue a first-in-first-out
 * (FIFO) data structure.
 *
 * Besides basic array operations, queues provide additional insertion,
 * extraction, and inspection operations. Each of these methods exists in two
 * forms: one throws an exception if the operation fails, the other returns a
 * special value (either `null` or `false`, depending on the operation). The
 * latter form of the insert operation is designed specifically for use with
 * capacity-restricted `QueueInterface` implementations; in most
 * implementations, insert operations cannot fail.
 *
 * <table>
 * <caption>Summary of QueueInterface methods</caption>
 * <thead>
 * <tr>
 * <td></td>
 * <td><em>Throws exception</em></td>
 * <td><em>Returns special value</em></td>
 * </tr>
 * </thead>
 * <tbody>
 * <tr>
 * <th>Insert</th>
 * <td><code>add()</code></td>
 * <td><code>offer()</code></td>
 * </tr>
 * <tr>
 * <th>Remove</th>
 * <td><code>remove()</code></td>
 * <td><code>poll()</code></td>
 * </tr>
 * <tr>
 * <th>Examine</th>
 * <td><code>element()</code></td>
 * <td><code>peek()</code></td>
 * </tr>
 * </tbody>
 * </table>
 *
 * Queues typically, but do not necessarily, order elements in a FIFO
 * (first-in-first-out) manner. Among the exceptions are priority queues, which
 * order elements according to a supplied comparator, or the elements' natural
 * ordering, and LIFO queues (or stacks) which order the elements LIFO
 * (last-in-first-out). Whatever the ordering used, the head of the queue is
 * that element which would be removed by a call to remove() or poll(). In a
 * FIFO queue, all new elements are inserted at the tail of the queue. Other
 * kinds of queues may use different placement rules. Every `QueueInterface`
 * implementation must specify its ordering properties.
 *
 * The `offer()` method inserts an element if possible, otherwise returning
 * `false`. This differs from the `add()` method, which can fail to add an
 * element only by throwing an unchecked exception. The `offer()` method is
 * designed for use when failure is a normal, rather than exceptional
 * occurrence, for example, in fixed-capacity (or "bounded") queues.
 *
 * The `remove()` and `poll()` methods remove and return the head of the queue.
 * Exactly which element is removed from the queue is a function of the queue's
 * ordering policy, which differs from implementation to implementation. The
 * `remove()` and `poll()` methods differ only in their behavior when the queue
 * is empty: the `remove()` method throws an exception, while the `poll()`
 * method returns `null`.
 *
 * The `element()` and `peek()` methods return, but do not remove, the head of
 * the queue.
 *
 * `QueueInterface` implementations generally do not allow insertion of `null`
 * elements, although some implementations do not prohibit insertion of `null`.
 * Even in the implementations that permit it, `null` should not be inserted
 * into a queue, as `null` is also used as a special return value by the
 * `poll()` method to indicate that the queue contains no elements.
 */
interface QueueInterface extends ArrayInterface
{
    /**
     * Ensures that this queue contains the specified element (optional
     * operation).
     *
     * Returns `true` if this queue changed as a result of the call. (Returns
     * `false` if this queue does not permit duplicates and already contains the
     * specified element.)
     *
     * Queues that support this operation may place limitations on what elements
     * may be added to this queue. In particular, some queues will refuse to add
     * `null` elements, and others will impose restrictions on the type of
     * elements that may be added. Queue classes should clearly specify in their
     * documentation any restrictions on what elements may be added.
     *
     * If a queue refuses to add a particular element for any reason other than
     * that it already contains the element, it must throw an exception (rather
     * than returning `false`). This preserves the invariant that a queue always
     * contains the specified element after this call returns.
     *
     * @see self::offer()
     *
     * @param mixed $element The element to add to this queue.
     *
     * @return bool `true` if this queue changed as a result of the call.
     *
     * @throws \RuntimeException if a queue refuses to add a particular element
     *     for any reason other than that it already contains the element.
     *     Implementations should use a more-specific exception that extends
     *     `\RuntimeException`.
     */
    public function add($element): bool;

    /**
     * Retrieves, but does not remove, the head of this queue.
     *
     * This method differs from `peek()` only in that it throws an exception if
     * this queue is empty.
     *
     * @see self::peek()
     *
     * @return mixed the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function element();

    /**
     * Inserts the specified element into this queue if it is possible to do so
     * immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted queue, this method is generally
     * preferable to `add()`, which can fail to insert an element only by
     * throwing an exception.
     *
     * @see self::add()
     *
     * @param mixed $element The element to add to this queue.
     *
     * @return bool `true` if the element was added to this queue, else `false`.
     */
    public function offer($element): bool;

    /**
     * Retrieves, but does not remove, the head of this queue, or returns `null`
     * if this queue is empty.
     *
     * @see self::element()
     *
     * @return mixed|null the head of this queue, or `null` if this queue is empty.
     */
    public function peek();

    /**
     * Retrieves and removes the head of this queue, or returns `null`
     * if this queue is empty.
     *
     * @see self::remove()
     *
     * @return mixed|null the head of this queue, or `null` if this queue is empty.
     */
    public function poll();

    /**
     * Retrieves and removes the head of this queue.
     *
     * This method differs from `poll()` only in that it throws an exception if
     * this queue is empty.
     *
     * @see self::poll()
     *
     * @return mixed the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function remove();

    /**
     * Returns the type associated with this queue.
     */
    public function getType(): string;
}
collection/src/Tool/TypeTrait.php000064400000003650147361033650013055 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Tool;

use function is_array;
use function is_bool;
use function is_callable;
use function is_float;
use function is_int;
use function is_numeric;
use function is_object;
use function is_resource;
use function is_scalar;
use function is_string;

/**
 * Provides functionality to check values for specific types.
 */
trait TypeTrait
{
    /**
     * Returns `true` if value is of the specified type.
     *
     * @param string $type The type to check the value against.
     * @param mixed $value The value to check.
     */
    protected function checkType(string $type, $value): bool
    {
        switch ($type) {
            case 'array':
                return is_array($value);
            case 'bool':
            case 'boolean':
                return is_bool($value);
            case 'callable':
                return is_callable($value);
            case 'float':
            case 'double':
                return is_float($value);
            case 'int':
            case 'integer':
                return is_int($value);
            case 'null':
                return $value === null;
            case 'numeric':
                return is_numeric($value);
            case 'object':
                return is_object($value);
            case 'resource':
                return is_resource($value);
            case 'scalar':
                return is_scalar($value);
            case 'string':
                return is_string($value);
            case 'mixed':
                return true;
            default:
                return $value instanceof $type;
        }
    }
}
collection/src/Tool/ValueToStringTrait.php000064400000004341147361033650014700 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Tool;

use DateTimeInterface;

use function get_class;
use function get_resource_type;
use function is_array;
use function is_bool;
use function is_callable;
use function is_resource;
use function is_scalar;

/**
 * Provides functionality to express a value as string
 */
trait ValueToStringTrait
{
    /**
     * Returns a string representation of the value.
     *
     * - null value: `'NULL'`
     * - boolean: `'TRUE'`, `'FALSE'`
     * - array: `'Array'`
     * - scalar: converted-value
     * - resource: `'(type resource #number)'`
     * - object with `__toString()`: result of `__toString()`
     * - object DateTime: ISO 8601 date
     * - object: `'(className Object)'`
     * - anonymous function: same as object
     *
     * @param mixed $value the value to return as a string.
     */
    protected function toolValueToString($value): string
    {
        // null
        if ($value === null) {
            return 'NULL';
        }

        // boolean constants
        if (is_bool($value)) {
            return $value ? 'TRUE' : 'FALSE';
        }

        // array
        if (is_array($value)) {
            return 'Array';
        }

        // scalar types (integer, float, string)
        if (is_scalar($value)) {
            return (string) $value;
        }

        // resource
        if (is_resource($value)) {
            return '(' . get_resource_type($value) . ' resource #' . (int) $value . ')';
        }

        // after this line $value is an object since is not null, scalar, array or resource

        // __toString() is implemented
        if (is_callable([$value, '__toString'])) {
            return (string) $value->__toString();
        }

        // object of type \DateTime
        if ($value instanceof DateTimeInterface) {
            return $value->format('c');
        }

        // unknown type
        return '(' . get_class($value) . ' Object)';
    }
}
collection/src/Tool/ValueExtractorTrait.php000064400000003103147361033650015075 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Tool;

use Ramsey\Collection\Exception\ValueExtractionException;

use function get_class;
use function method_exists;
use function property_exists;
use function sprintf;

/**
 * Provides functionality to extract the value of a property or method from an object.
 */
trait ValueExtractorTrait
{
    /**
     * Extracts the value of the given property or method from the object.
     *
     * @param object $object The object to extract the value from.
     * @param string $propertyOrMethod The property or method for which the
     *     value should be extracted.
     *
     * @return mixed the value extracted from the specified property or method.
     *
     * @throws ValueExtractionException if the method or property is not defined.
     */
    protected function extractValue(object $object, string $propertyOrMethod)
    {
        if (property_exists($object, $propertyOrMethod)) {
            return $object->$propertyOrMethod;
        }

        if (method_exists($object, $propertyOrMethod)) {
            return $object->{$propertyOrMethod}();
        }

        throw new ValueExtractionException(
            sprintf('Method or property "%s" not defined in %s', $propertyOrMethod, get_class($object))
        );
    }
}
collection/src/GenericArray.php000064400000000734147361033650012566 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

/**
 * `GenericArray` represents a standard array object.
 */
class GenericArray extends AbstractArray
{
}
collection/src/DoubleEndedQueueInterface.php000064400000024015147361033650015211 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

use Ramsey\Collection\Exception\NoSuchElementException;

/**
 * A linear collection that supports element insertion and removal at both ends.
 *
 * Most `DoubleEndedQueueInterface` implementations place no fixed limits on the
 * number of elements they may contain, but this interface supports
 * capacity-restricted double-ended queues as well as those with no fixed size
 * limit.
 *
 * This interface defines methods to access the elements at both ends of the
 * double-ended queue. Methods are provided to insert, remove, and examine the
 * element. Each of these methods exists in two forms: one throws an exception
 * if the operation fails, the other returns a special value (either `null` or
 * `false`, depending on the operation). The latter form of the insert operation
 * is designed specifically for use with capacity-restricted implementations; in
 * most implementations, insert operations cannot fail.
 *
 * The twelve methods described above are summarized in the following table:
 *
 * <table>
 * <caption>Summary of DoubleEndedQueueInterface methods</caption>
 * <thead>
 * <tr>
 * <th></th>
 * <th colspan=2>First Element (Head)</th>
 * <th colspan=2>Last Element (Tail)</th>
 * </tr>
 * <tr>
 * <td></td>
 * <td><em>Throws exception</em></td>
 * <td><em>Special value</em></td>
 * <td><em>Throws exception</em></td>
 * <td><em>Special value</em></td>
 * </tr>
 * </thead>
 * <tbody>
 * <tr>
 * <th>Insert</th>
 * <td><code>addFirst()</code></td>
 * <td><code>offerFirst()</code></td>
 * <td><code>addLast()</code></td>
 * <td><code>offerLast()</code></td>
 * </tr>
 * <tr>
 * <th>Remove</th>
 * <td><code>removeFirst()</code></td>
 * <td><code>pollFirst()</code></td>
 * <td><code>removeLast()</code></td>
 * <td><code>pollLast()</code></td>
 * </tr>
 * <tr>
 * <th>Examine</th>
 * <td><code>firstElement()</code></td>
 * <td><code>peekFirst()</code></td>
 * <td><code>lastElement()</code></td>
 * <td><code>peekLast()</code></td>
 * </tr>
 * </tbody>
 * </table>
 *
 * This interface extends the `QueueInterface`. When a double-ended queue is
 * used as a queue, FIFO (first-in-first-out) behavior results. Elements are
 * added at the end of the double-ended queue and removed from the beginning.
 * The methods inherited from the `QueueInterface` are precisely equivalent to
 * `DoubleEndedQueueInterface` methods as indicated in the following table:
 *
 * <table>
 * <caption>Comparison of QueueInterface and DoubleEndedQueueInterface methods</caption>
 * <thead>
 * <tr>
 * <th>QueueInterface Method</th>
 * <th>DoubleEndedQueueInterface Method</th>
 * </tr>
 * </thead>
 * <tbody>
 * <tr>
 * <td><code>add()</code></td>
 * <td><code>addLast()</code></td>
 * </tr>
 * <tr>
 * <td><code>offer()</code></td>
 * <td><code>offerLast()</code></td>
 * </tr>
 * <tr>
 * <td><code>remove()</code></td>
 * <td><code>removeFirst()</code></td>
 * </tr>
 * <tr>
 * <td><code>poll()</code></td>
 * <td><code>pollFirst()</code></td>
 * </tr>
 * <tr>
 * <td><code>element()</code></td>
 * <td><code>firstElement()</code></td>
 * </tr>
 * <tr>
 * <td><code>peek()</code></td>
 * <td><code>peekFirst()</code></td>
 * </tr>
 * </tbody>
 * </table>
 *
 * Double-ended queues can also be used as LIFO (last-in-first-out) stacks. When
 * a double-ended queue is used as a stack, elements are pushed and popped from
 * the beginning of the double-ended queue. Stack concepts are precisely
 * equivalent to `DoubleEndedQueueInterface` methods as indicated in the table
 * below:
 *
 * <table>
 * <caption>Comparison of stack concepts and DoubleEndedQueueInterface methods</caption>
 * <thead>
 * <tr>
 * <th>Stack concept</th>
 * <th>DoubleEndedQueueInterface Method</th>
 * </tr>
 * </thead>
 * <tbody>
 * <tr>
 * <td><em>push</em></td>
 * <td><code>addFirst()</code></td>
 * </tr>
 * <tr>
 * <td><em>pop</em></td>
 * <td><code>removeFirst()</code></td>
 * </tr>
 * <tr>
 * <td><em>peek</em></td>
 * <td><code>peekFirst()</code></td>
 * </tr>
 * </tbody>
 * </table>
 *
 * Note that the `peek()` method works equally well when a double-ended queue is
 * used as a queue or a stack; in either case, elements are drawn from the
 * beginning of the double-ended queue.
 *
 * While `DoubleEndedQueueInterface` implementations are not strictly required
 * to prohibit the insertion of `null` elements, they are strongly encouraged to
 * do so. Users of any `DoubleEndedQueueInterface` implementations that do allow
 * `null` elements are strongly encouraged *not* to take advantage of the
 * ability to insert nulls. This is so because `null` is used as a special
 * return value by various methods to indicated that the double-ended queue is
 * empty.
 */
interface DoubleEndedQueueInterface extends QueueInterface
{
    /**
     * Inserts the specified element at the front of this queue if it is
     * possible to do so immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted double-ended queue, it is generally
     * preferable to use the `offerFirst()` method.
     *
     * @param mixed $element The element to add to the front of this queue.
     *
     * @return bool `true` if this queue changed as a result of the call.
     *
     * @throws \RuntimeException if a queue refuses to add a particular element
     *     for any reason other than that it already contains the element.
     *     Implementations should use a more-specific exception that extends
     *     `\RuntimeException`.
     */
    public function addFirst($element): bool;

    /**
     * Inserts the specified element at the end of this queue if it is possible
     * to do so immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted double-ended queue, it is generally
     * preferable to use the `offerLast()` method.
     *
     * This method is equivalent to `add()`.
     *
     * @param mixed $element The element to add to the end of this queue.
     *
     * @return bool `true` if this queue changed as a result of the call.
     *
     * @throws \RuntimeException if a queue refuses to add a particular element
     *     for any reason other than that it already contains the element.
     *     Implementations should use a more-specific exception that extends
     *     `\RuntimeException`.
     */
    public function addLast($element): bool;

    /**
     * Inserts the specified element at the front of this queue if it is
     * possible to do so immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted queue, this method is generally
     * preferable to `addFirst()`, which can fail to insert an element only by
     * throwing an exception.
     *
     * @param mixed $element The element to add to the front of this queue.
     *
     * @return bool `true` if the element was added to this queue, else `false`.
     */
    public function offerFirst($element): bool;

    /**
     * Inserts the specified element at the end of this queue if it is possible
     * to do so immediately without violating capacity restrictions.
     *
     * When using a capacity-restricted queue, this method is generally
     * preferable to `addLast()` which can fail to insert an element only by
     * throwing an exception.
     *
     * @param mixed $element The element to add to the end of this queue.
     *
     * @return bool `true` if the element was added to this queue, else `false`.
     */
    public function offerLast($element): bool;

    /**
     * Retrieves and removes the head of this queue.
     *
     * This method differs from `pollFirst()` only in that it throws an
     * exception if this queue is empty.
     *
     * @return mixed the first element in this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function removeFirst();

    /**
     * Retrieves and removes the tail of this queue.
     *
     * This method differs from `pollLast()` only in that it throws an exception
     * if this queue is empty.
     *
     * @return mixed the last element in this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function removeLast();

    /**
     * Retrieves and removes the head of this queue, or returns `null` if this
     * queue is empty.
     *
     * @return mixed|null the head of this queue, or `null` if this queue is empty.
     */
    public function pollFirst();

    /**
     * Retrieves and removes the tail of this queue, or returns `null` if this
     * queue is empty.
     *
     * @return mixed|null the tail of this queue, or `null` if this queue is empty.
     */
    public function pollLast();

    /**
     * Retrieves, but does not remove, the head of this queue.
     *
     * This method differs from `peekFirst()` only in that it throws an
     * exception if this queue is empty.
     *
     * @return mixed the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function firstElement();

    /**
     * Retrieves, but does not remove, the tail of this queue.
     *
     * This method differs from `peekLast()` only in that it throws an exception
     * if this queue is empty.
     *
     * @return mixed the tail of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function lastElement();

    /**
     * Retrieves, but does not remove, the head of this queue, or returns `null`
     * if this queue is empty.
     *
     * @return mixed|null the head of this queue, or `null` if this queue is empty.
     */
    public function peekFirst();

    /**
     * Retrieves, but does not remove, the tail of this queue, or returns `null`
     * if this queue is empty.
     *
     * @return mixed|null the tail of this queue, or `null` if this queue is empty.
     */
    public function peekLast();
}
collection/src/AbstractArray.php000064400000011305147361033650012751 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

use ArrayIterator;
use Traversable;

use function serialize;
use function unserialize;

/**
 * This class provides a basic implementation of `ArrayInterface`, to minimize
 * the effort required to implement this interface.
 */
abstract class AbstractArray implements ArrayInterface
{
    /**
     * The items of this array.
     *
     * @var mixed[]
     */
    protected $data = [];

    /**
     * Constructs a new array object.
     *
     * @param mixed[] $data The initial items to add to this array.
     */
    public function __construct(array $data = [])
    {
        // Invoke offsetSet() for each value added; in this way, sub-classes
        // may provide additional logic about values added to the array object.
        foreach ($data as $key => $value) {
            $this[$key] = $value;
        }
    }

    /**
     * Returns an iterator for this array.
     *
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php IteratorAggregate::getIterator()
     *
     * @return ArrayIterator<mixed, mixed>
     */
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->data);
    }

    /**
     * Returns `true` if the given offset exists in this array.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php ArrayAccess::offsetExists()
     *
     * @param mixed $offset The offset to check.
     */
    public function offsetExists($offset): bool
    {
        return isset($this->data[$offset]);
    }

    /**
     * Returns the value at the specified offset.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetget.php ArrayAccess::offsetGet()
     *
     * @param mixed $offset The offset for which a value should be returned.
     *
     * @return mixed|null the value stored at the offset, or null if the offset
     *     does not exist.
     */
    public function offsetGet($offset)
    {
        return $this->data[$offset] ?? null;
    }

    /**
     * Sets the given value to the given offset in the array.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
     *
     * @param mixed|null $offset The offset to set. If `null`, the value may be
     *     set at a numerically-indexed offset.
     * @param mixed $value The value to set at the given offset.
     */
    public function offsetSet($offset, $value): void
    {
        if ($offset === null) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }

    /**
     * Removes the given offset and its value from the array.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php ArrayAccess::offsetUnset()
     *
     * @param mixed $offset The offset to remove from the array.
     */
    public function offsetUnset($offset): void
    {
        unset($this->data[$offset]);
    }

    /**
     * Returns a serialized string representation of this array object.
     *
     * @link http://php.net/manual/en/serializable.serialize.php Serializable::serialize()
     *
     * @return string a PHP serialized string.
     */
    public function serialize(): string
    {
        return serialize($this->data);
    }

    /**
     * Converts a serialized string representation into an instance object.
     *
     * @link http://php.net/manual/en/serializable.unserialize.php Serializable::unserialize()
     *
     * @param string $serialized A PHP serialized string to unserialize.
     *
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     */
    public function unserialize($serialized): void
    {
        $this->data = unserialize($serialized, ['allowed_classes' => false]);
    }

    /**
     * Returns the number of items in this array.
     *
     * @link http://php.net/manual/en/countable.count.php Countable::count()
     */
    public function count(): int
    {
        return count($this->data);
    }

    /**
     * Removes all items from this array.
     */
    public function clear(): void
    {
        $this->data = [];
    }

    /**
     * Returns a native PHP array representation of this array object.
     *
     * @return mixed[]
     */
    public function toArray(): array
    {
        return $this->data;
    }

    /**
     * Returns `true` if this array is empty.
     */
    public function isEmpty(): bool
    {
        return count($this->data) === 0;
    }
}
collection/src/Exception/NoSuchElementException.php000064400000001002147361033650016526 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Exception;

/**
 * Thrown when attempting to access an element that does not exist.
 */
class NoSuchElementException extends \RuntimeException
{
}
collection/src/Exception/UnsupportedOperationException.php000064400000001012147361033650020227 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Exception;

/**
 * Thrown to indicate that the requested operation is not supported.
 */
class UnsupportedOperationException extends \RuntimeException
{
}
collection/src/Exception/InvalidSortOrderException.php000064400000001007147361033650017254 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Exception;

/**
 * Thrown when attempting to use a sort order that is not recognized.
 */
class InvalidSortOrderException extends \RuntimeException
{
}
collection/src/Exception/InvalidArgumentException.php000064400000001007147361033650017113 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Exception;

/**
 * Thrown to indicate an argument is not of the expected type.
 */
class InvalidArgumentException extends \InvalidArgumentException
{
}
collection/src/Exception/CollectionMismatchException.php000064400000001013147361033650017600 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Exception;

/**
 * Thrown when attempting to operate on collections of differing types.
 */
class CollectionMismatchException extends \RuntimeException
{
}
collection/src/Exception/ValueExtractionException.php000064400000001033147361033650017136 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Exception;

/**
 * Thrown when attempting to extract a value for a method or property that does not exist.
 */
class ValueExtractionException extends \RuntimeException
{
}
collection/src/Exception/OutOfBoundsException.php000064400000001023147361033650016227 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection\Exception;

/**
 * Thrown when attempting to access an element out of the range of the collection.
 */
class OutOfBoundsException extends \OutOfBoundsException
{
}
collection/src/DoubleEndedQueue.php000064400000017250147361033650013373 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

use Ramsey\Collection\Exception\InvalidArgumentException;
use Ramsey\Collection\Exception\NoSuchElementException;

/**
 * This class provides a basic implementation of `DoubleEndedQueueInterface`, to
 * minimize the effort required to implement this interface.
 */
class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
{
    /**
     * Index of the last element in the queue.
     *
     * @var int
     */
    private $tail = -1;

    /**
     * Sets the given value to the given offset in the queue.
     *
     * Since arbitrary offsets may not be manipulated in a queue, this method
     * serves only to fulfill the `ArrayAccess` interface requirements. It is
     * invoked by other operations when adding values to the queue.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
     *
     * @param mixed|null $offset The offset is ignored and is treated as `null`.
     * @param mixed $value The value to set at the given offset.
     *
     * @throws InvalidArgumentException when the value does not match the
     *     specified type for this queue.
     */
    public function offsetSet($offset, $value): void
    {
        if ($this->checkType($this->getType(), $value) === false) {
            throw new InvalidArgumentException(
                'Value must be of type ' . $this->getType() . '; value is '
                . $this->toolValueToString($value)
            );
        }

        $this->tail++;

        $this->data[$this->tail] = $value;
    }

    /**
     * Ensures that the specified element is inserted at the front of this queue.
     *
     * @see self::offerFirst()
     *
     * @param mixed $element The element to add to this queue.
     *
     * @return bool `true` if this queue changed as a result of the call.
     *
     * @throws InvalidArgumentException when the value does not match the
     *     specified type for this queue.
     */
    public function addFirst($element): bool
    {
        if ($this->checkType($this->getType(), $element) === false) {
            throw new InvalidArgumentException(
                'Value must be of type ' . $this->getType() . '; value is '
                . $this->toolValueToString($element)
            );
        }

        $this->index--;

        $this->data[$this->index] = $element;

        return true;
    }

    /**
     * Ensures that the specified element in inserted at the end of this queue.
     *
     * @see Queue::add()
     *
     * @param mixed $element The element to add to this queue.
     *
     * @return bool `true` if this queue changed as a result of the call.
     *
     * @throws InvalidArgumentException when the value does not match the
     *     specified type for this queue.
     */
    public function addLast($element): bool
    {
        return $this->add($element);
    }

    /**
     * Inserts the specified element at the front this queue.
     *
     * @see self::addFirst()
     *
     * @param mixed $element The element to add to this queue.
     *
     * @return bool `true` if the element was added to this queue, else `false`.
     */
    public function offerFirst($element): bool
    {
        try {
            return $this->addFirst($element);
        } catch (InvalidArgumentException $e) {
            return false;
        }
    }

    /**
     * Inserts the specified element at the end this queue.
     *
     * @see self::addLast()
     * @see Queue::offer()
     *
     * @param mixed $element The element to add to this queue.
     *
     * @return bool `true` if the element was added to this queue, else `false`.
     */
    public function offerLast($element): bool
    {
        return $this->offer($element);
    }

    /**
     * Retrieves and removes the head of this queue.
     *
     * This method differs from `pollFirst()` only in that it throws an
     * exception if this queue is empty.
     *
     * @see self::pollFirst()
     * @see Queue::remove()
     *
     * @return mixed the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function removeFirst()
    {
        return $this->remove();
    }

    /**
     * Retrieves and removes the tail of this queue.
     *
     * This method differs from `pollLast()` only in that it throws an exception
     * if this queue is empty.
     *
     * @see self::pollLast()
     *
     * @return mixed the tail of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function removeLast()
    {
        if ($this->count() === 0) {
            throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
        }

        $tail = $this[$this->tail];

        unset($this[$this->tail]);
        $this->tail--;

        return $tail;
    }

    /**
     * Retrieves and removes the head of this queue, or returns `null` if this
     * queue is empty.
     *
     * @see self::removeFirst()
     *
     * @return mixed|null the head of this queue, or `null` if this queue is empty.
     */
    public function pollFirst()
    {
        return $this->poll();
    }

    /**
     * Retrieves and removes the tail of this queue, or returns `null` if this
     * queue is empty.
     *
     * @see self::removeLast()
     *
     * @return mixed|null the tail of this queue, or `null` if this queue is empty.
     */
    public function pollLast()
    {
        if ($this->count() === 0) {
            return null;
        }

        $tail = $this[$this->tail];

        unset($this[$this->tail]);
        $this->tail--;

        return $tail;
    }

    /**
     * Retrieves, but does not remove, the head of this queue.
     *
     * This method differs from `peekFirst()` only in that it throws an
     * exception if this queue is empty.
     *
     * @see self::peekFirst()
     * @see Queue::element()
     *
     * @return mixed the head of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function firstElement()
    {
        return $this->element();
    }

    /**
     * Retrieves, but does not remove, the tail of this queue.
     *
     * This method differs from `peekLast()` only in that it throws an exception
     * if this queue is empty.
     *
     * @see self::peekLast()
     *
     * @return mixed the tail of this queue.
     *
     * @throws NoSuchElementException if this queue is empty.
     */
    public function lastElement()
    {
        if ($this->count() === 0) {
            throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
        }

        return $this->data[$this->tail];
    }

    /**
     * Retrieves, but does not remove, the head of this queue, or returns `null`
     * if this queue is empty.
     *
     * @see self::firstElement()
     * @see Queue::peek()
     *
     * @return mixed|null the head of this queue, or `null` if this queue is empty.
     */
    public function peekFirst()
    {
        return $this->peek();
    }

    /**
     * Retrieves, but does not remove, the tail of this queue, or returns `null`
     * if this queue is empty.
     *
     * @see self::lastElement()
     *
     * @return mixed|null the tail of this queue, or `null` if this queue is empty
     */
    public function peekLast()
    {
        if ($this->count() === 0) {
            return null;
        }

        return $this->data[$this->tail];
    }
}
collection/src/CollectionInterface.php000064400000014536147361033650014134 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

/**
 * A collection represents a group of objects, known as its elements.
 *
 * Some collections allow duplicate elements and others do not. Some are ordered
 * and others unordered.
 */
interface CollectionInterface extends ArrayInterface
{
    /**
     * Ascending sort type.
     */
    public const SORT_ASC = 'asc';

    /**
     * Descending sort type.
     */
    public const SORT_DESC = 'desc';

    /**
     * Ensures that this collection contains the specified element (optional
     * operation).
     *
     * Returns `true` if this collection changed as a result of the call.
     * (Returns `false` if this collection does not permit duplicates and
     * already contains the specified element.)
     *
     * Collections that support this operation may place limitations on what
     * elements may be added to this collection. In particular, some
     * collections will refuse to add `null` elements, and others will impose
     * restrictions on the type of elements that may be added. Collection
     * classes should clearly specify in their documentation any restrictions
     * on what elements may be added.
     *
     * If a collection refuses to add a particular element for any reason other
     * than that it already contains the element, it must throw an exception
     * (rather than returning `false`). This preserves the invariant that a
     * collection always contains the specified element after this call returns.
     *
     * @param mixed $element The element to add to the collection.
     *
     * @return bool `true` if this collection changed as a result of the call.
     */
    public function add($element): bool;

    /**
     * Returns `true` if this collection contains the specified element.
     *
     * @param mixed $element The element to check whether the collection contains.
     * @param bool $strict Whether to perform a strict type check on the value.
     */
    public function contains($element, bool $strict = true): bool;

    /**
     * Returns the type associated with this collection.
     */
    public function getType(): string;

    /**
     * Removes a single instance of the specified element from this collection,
     * if it is present.
     *
     * @param mixed $element The element to remove from the collection.
     *
     * @return bool `true` if an element was removed as a result of this call.
     */
    public function remove($element): bool;

    /**
     * Returns the values from the given property or method.
     *
     * @param string $propertyOrMethod The property or method name to filter by.
     *
     * @return mixed[]
     */
    public function column(string $propertyOrMethod): array;

    /**
     * Returns the first item of the collection.
     *
     * @return mixed
     */
    public function first();

    /**
     * Returns the last item of the collection.
     *
     * @return mixed
     */
    public function last();

    /**
     * Sort the collection by a property or method with the given sort order.
     *
     * This will always leave the original collection untouched and will return
     * a new one.
     *
     * @param string $propertyOrMethod The property or method to sort by.
     * @param string $order The sort order for the resulting collection (one of
     *     this interface's `SORT_*` constants).
     *
     * @return CollectionInterface<mixed, mixed>
     */
    public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): self;

    /**
     * Filter out items of the collection which don't match the criteria of
     * given callback.
     *
     * This will always leave the original collection untouched and will return
     * a new one.
     *
     * See the {@link http://php.net/manual/en/function.array-filter.php PHP array_filter() documentation}
     * for examples of how the `$callback` parameter works.
     *
     * @param callable $callback A callable to use for filtering elements.
     *
     * @return CollectionInterface<mixed, mixed>
     */
    public function filter(callable $callback): self;

    /**
     * Create a new collection where items match the criteria of given callback.
     *
     * This will always leave the original collection untouched and will return
     * a new one.
     *
     * @param string $propertyOrMethod The property or method to evaluate.
     * @param mixed  $value The value to match.
     *
     * @return CollectionInterface<mixed, mixed>
     */
    public function where(string $propertyOrMethod, $value): self;

    /**
     * Apply a given callback method on each item of the collection.
     *
     * This will always leave the original collection untouched and will return
     * a new one.
     *
     * See the {@link http://php.net/manual/en/function.array-map.php PHP array_map() documentation}
     * for examples of how the `$callback` parameter works.
     *
     * @param callable $callback A callable to apply to each item of the
     *     collection.
     *
     * @return CollectionInterface<mixed, mixed>
     */
    public function map(callable $callback): self;

    /**
     * Create a new collection with divergent items between current and given
     * collection.
     *
     * @param CollectionInterface<mixed, mixed> $other The collection to check for divergent
     *     items.
     *
     * @return CollectionInterface<mixed, mixed>
     */
    public function diff(CollectionInterface $other): self;

    /**
     * Create a new collection with intersecting item between current and given
     * collection.
     *
     * @param CollectionInterface<mixed, mixed> $other The collection to check for
     *     intersecting items.
     *
     * @return CollectionInterface<mixed, mixed>
     */
    public function intersect(CollectionInterface $other): self;

    /**
     * Merge current items and items of given collections into a new one.
     *
     * @param CollectionInterface<mixed, mixed> ...$collections The collections to merge.
     *
     * @return CollectionInterface<mixed, mixed>
     */
    public function merge(CollectionInterface ...$collections): self;
}
collection/src/Collection.php000064400000005061147361033650012304 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

/**
 * A collection represents a group of objects.
 *
 * Each object in the collection is of a specific, defined type.
 *
 * This is a direct implementation of `CollectionInterface`, provided for
 * the sake of convenience.
 *
 * Example usage:
 *
 * ``` php
 * $collection = new \Ramsey\Collection\Collection('My\\Foo');
 * $collection->add(new \My\Foo());
 * $collection->add(new \My\Foo());
 *
 * foreach ($collection as $foo) {
 *     // Do something with $foo
 * }
 * ```
 *
 * It is preferable to subclass `AbstractCollection` to create your own typed
 * collections. For example:
 *
 * ``` php
 * namespace My\Foo;
 *
 * class FooCollection extends \Ramsey\Collection\AbstractCollection
 * {
 *     public function getType()
 *     {
 *         return 'My\\Foo';
 *     }
 * }
 * ```
 *
 * And then use it similarly to the earlier example:
 *
 * ``` php
 * $fooCollection = new \My\Foo\FooCollection();
 * $fooCollection->add(new \My\Foo());
 * $fooCollection->add(new \My\Foo());
 *
 * foreach ($fooCollection as $foo) {
 *     // Do something with $foo
 * }
 * ```
 *
 * The benefit with this approach is that you may do type-checking on the
 * collection object:
 *
 * ``` php
 * if ($collection instanceof \My\Foo\FooCollection) {
 *     // the collection is a collection of My\Foo objects
 * }
 * ```
 */
class Collection extends AbstractCollection
{
    /**
     * The type of elements stored in this collection.
     *
     * A collection's type is immutable once it is set. For this reason, this
     * property is set private.
     *
     * @var string
     */
    private $collectionType;

    /**
     * Constructs a collection object of the specified type, optionally with the
     * specified data.
     *
     * @param string $collectionType The type (FQCN) associated with this
     *     collection.
     * @param mixed[] $data The initial items to store in the collection.
     */
    public function __construct(string $collectionType, array $data = [])
    {
        $this->collectionType = $collectionType;
        parent::__construct($data);
    }

    /**
     * Returns the type associated with this collection.
     */
    public function getType(): string
    {
        return $this->collectionType;
    }
}
collection/src/AbstractSet.php000064400000003425147361033650012432 0ustar00<?php

/**
 * This file is part of the ramsey/collection 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\Collection;

use Ramsey\Collection\Exception\InvalidArgumentException;

/**
 * This class contains the basic implementation of a collection that does not
 * allow duplicated values (a set), to minimize the effort required to implement
 * this specific type of collection.
 */
abstract class AbstractSet extends AbstractCollection
{
    /**
     * Adds the specified element to this set, if it is not already present.
     *
     * @param mixed $element The element to add to the set.
     *
     * @return bool `true` if this set did not already contain the specified
     *     element.
     *
     * @throws InvalidArgumentException when the element does not match the
     *     specified type for this set.
     */
    public function add($element): bool
    {
        if ($this->contains($element)) {
            return false;
        }

        return parent::add($element);
    }

    /**
     * Sets the given value to the given offset in this set, if it is not
     * already present.
     *
     * @param mixed|null $offset The offset is ignored and is treated as `null`.
     * @param mixed $value The value to set at the given offset.
     *
     * @throws InvalidArgumentException when the value does not match the
     *     specified type for this set.
     */
    public function offsetSet($offset, $value): void
    {
        if ($this->contains($value)) {
            return;
        }

        parent::offsetSet($offset, $value);
    }
}
collection/README.md000064400000005365147361033650010177 0ustar00# ramsey/collection

[![Source Code][badge-source]][source]
[![Latest Version][badge-release]][release]
[![Software License][badge-license]][license]
[![Build Status][badge-build]][build]
[![Coverage Status][badge-coverage]][coverage]
[![Total Downloads][badge-downloads]][downloads]

ramsey/collection is a PHP 7.2+ library for representing and manipulating collections..

This project adheres to a [Contributor Code of Conduct][conduct]. By participating in this project and its community, you are expected to uphold this code.


## About

Much inspiration for this library came from the [Java Collections Framework][java].


## Installation

The preferred method of installation is via [Packagist][] and [Composer][]. Run
the following command to install the package and add it as a requirement to
your project's `composer.json`:

```bash
composer require ramsey/collection
```


## API documentation

The [latest class API documentation][apidocs] is available online.


## Examples

Examples of how to use this framework can be found in the [Wiki pages](https://github.com/ramsey/collection/wiki/Examples).


## Contributing

Contributions are welcome! Please read [CONTRIBUTING][] for details.


## Copyright and License

The ramsey/collection library is copyright © [Ben Ramsey](https://benramsey.com/) and licensed for use under the MIT License (MIT). Please see [LICENSE][] for more information.



[conduct]: https://github.com/ramsey/collection/blob/master/.github/CODE_OF_CONDUCT.md
[java]: http://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html
[packagist]: https://packagist.org/packages/ramsey/collection
[composer]: http://getcomposer.org/
[apidocs]: https://docs.benramsey.com/ramsey-collection/latest/
[contributing]: https://github.com/ramsey/collection/blob/master/.github/CONTRIBUTING.md

[badge-source]: http://img.shields.io/badge/source-ramsey/collection-blue.svg?style=flat-square
[badge-release]: https://img.shields.io/github/release/ramsey/collection.svg?style=flat-square
[badge-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
[badge-build]: https://img.shields.io/travis/ramsey/collection/master.svg?style=flat-square
[badge-coverage]: https://img.shields.io/coveralls/ramsey/collection/master.svg?style=flat-square
[badge-downloads]: https://img.shields.io/packagist/dt/ramsey/collection.svg?style=flat-square

[source]: https://github.com/ramsey/collection
[release]: https://github.com/ramsey/collection/releases
[license]: https://github.com/ramsey/collection/blob/master/LICENSE
[build]: https://travis-ci.org/ramsey/collection
[hhvm]: http://hhvm.h4cc.de/package/ramsey/collection
[coverage]: https://coveralls.io/r/ramsey/collection?branch=master
[downloads]: https://packagist.org/packages/ramsey/collection
collection/CHANGELOG.md000064400000006553147361033650010531 0ustar00# ramsey/collection Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
### Changed
### Deprecated
### Removed
### Fixed
### Security

## [1.0.1] - 2020-01-04

### Fixed

* Fixed `AbstractCollection::offsetSet()` so that it uses the provided `$offset`
  when setting `$value` in the array.

## [1.0.0] - 2018-12-31

### Added

* Added support for *queue* data structures to represent collections of ordered
  entities. Together with *double-ended queues* (a.k.a. *deques*),
  first-in-first-out (FIFO), last-in-first-out (LIFO), and other queue and stack
  behaviors may be implemented. This functionality includes interfaces
  `QueueInterface` and `DoubleEndedQueueInterface` and classes `Queue` and
  `DoubleEndedQueue`.
* Added support for *set* data structures, representing collections that cannot
  contain any duplicated elements; includes classes `AbstractSet` and `Set`.
* Added support for *typed map* data structures to represent maps of elements
  where both keys and values have specified data types; includes
  `TypedMapInterface` and the classes `AbstractTypedMap` and `TypedMap`.
* Added new manipulation and analyze methods for collections: `column()`,
  `first()`, `last()`, `sort()`, `filter()`, `where()`, `map()`, `diff()`,
  `intersect()`, and `merge()`. See [CollectionInterface](https://github.com/ramsey/collection/blob/master/src/CollectionInterface.php)
  for more information.
* Added the following new exceptions specific to the ramsey/collection library:
  `CollectionMismatchException`, `InvalidArgumentException`,
  `InvalidSortOrderException`, `NoSuchElementException`, `OutOfBoundsException`,
  `UnsupportedOperationException`, and `ValueExtractionException`.

### Changed

* Minimum PHP version supported is 7.2.
* Strict types are enforced throughout.

### Removed

* Removed support for HHVM.

### Security

* Fixed possible exploit using `AbstractArray::unserialize()`
  (see [#47](https://github.com/ramsey/collection/issues/47)).

## [0.3.0] - 2016-05-23

### Added

* Added `MapInterface::keys()` method to return the keys from a `MapInterface`
  object. This was added to the `AbstractMap` class.

### Removed

* Removed `getType()` and constructor methods from `AbstractCollection`. Children
  of `AbstractCollection` must now implement `getType()`, which should return a
  string value that defines the data type of items for the collection.

### Fixed

* Improve error messages in exceptions when `Collection` and `NamedParameterMap`
  items fail type checks.

## [0.2.1] - 2016-02-22

### Fixed

* Allow non-strict checking of values in typed collections.

## [0.2.0] - 2016-02-05

### Added

* Support typed collections.

## [0.1.0] - 2015-10-27

### Added

* Support generic arrays and maps.

[Unreleased]: https://github.com/ramsey/collection/compare/1.0.1...HEAD
[1.0.1]: https://github.com/ramsey/collection/compare/1.0.0...1.0.1
[1.0.0]: https://github.com/ramsey/collection/compare/0.3.0...1.0.0
[0.3.0]: https://github.com/ramsey/collection/compare/0.2.1...0.3.0
[0.2.1]: https://github.com/ramsey/collection/compare/0.2.0...0.2.1
[0.2.0]: https://github.com/ramsey/collection/compare/0.1.0...0.2.0
[0.1.0]: https://github.com/ramsey/collection/commits/0.1.0
collection/LICENSE000064400000002067147361033650007721 0ustar00Copyright (c) 2015-2020 Ben Ramsey <ben@benramsey.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.