Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/**
4
 * This file is part of the ramsey/uuid library
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 *
9
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
10
 * @license http://opensource.org/licenses/MIT MIT
11
 */
12
 
13
declare(strict_types=1);
14
 
15
namespace Ramsey\Uuid\Guid;
16
 
17
use Ramsey\Uuid\Exception\InvalidArgumentException;
18
use Ramsey\Uuid\Fields\SerializableFieldsTrait;
19
use Ramsey\Uuid\Rfc4122\FieldsInterface;
20
use Ramsey\Uuid\Rfc4122\MaxTrait;
21
use Ramsey\Uuid\Rfc4122\NilTrait;
22
use Ramsey\Uuid\Rfc4122\VariantTrait;
23
use Ramsey\Uuid\Rfc4122\VersionTrait;
24
use Ramsey\Uuid\Type\Hexadecimal;
25
use Ramsey\Uuid\Uuid;
26
 
27
use function bin2hex;
28
use function dechex;
29
use function hexdec;
30
use function pack;
31
use function sprintf;
32
use function str_pad;
33
use function strlen;
34
use function substr;
35
use function unpack;
36
 
37
use const STR_PAD_LEFT;
38
 
39
/**
40
 * GUIDs are comprised of a set of named fields, according to RFC 4122
41
 *
42
 * @see Guid
43
 *
44
 * @psalm-immutable
45
 */
46
final class Fields implements FieldsInterface
47
{
48
    use MaxTrait;
49
    use NilTrait;
50
    use SerializableFieldsTrait;
51
    use VariantTrait;
52
    use VersionTrait;
53
 
54
    /**
55
     * @param string $bytes A 16-byte binary string representation of a UUID
56
     *
57
     * @throws InvalidArgumentException if the byte string is not exactly 16 bytes
58
     * @throws InvalidArgumentException if the byte string does not represent a GUID
59
     * @throws InvalidArgumentException if the byte string does not contain a valid version
60
     */
61
    public function __construct(private string $bytes)
62
    {
63
        if (strlen($this->bytes) !== 16) {
64
            throw new InvalidArgumentException(
65
                'The byte string must be 16 bytes long; '
66
                . 'received ' . strlen($this->bytes) . ' bytes'
67
            );
68
        }
69
 
70
        if (!$this->isCorrectVariant()) {
71
            throw new InvalidArgumentException(
72
                'The byte string received does not conform to the RFC '
73
                . '4122 or Microsoft Corporation variants'
74
            );
75
        }
76
 
77
        if (!$this->isCorrectVersion()) {
78
            throw new InvalidArgumentException(
79
                'The byte string received does not contain a valid version'
80
            );
81
        }
82
    }
83
 
84
    public function getBytes(): string
85
    {
86
        return $this->bytes;
87
    }
88
 
89
    public function getTimeLow(): Hexadecimal
90
    {
91
        // Swap the bytes from little endian to network byte order.
92
        /** @var array $hex */
93
        $hex = unpack(
94
            'H*',
95
            pack(
96
                'v*',
97
                hexdec(bin2hex(substr($this->bytes, 2, 2))),
98
                hexdec(bin2hex(substr($this->bytes, 0, 2)))
99
            )
100
        );
101
 
102
        return new Hexadecimal((string) ($hex[1] ?? ''));
103
    }
104
 
105
    public function getTimeMid(): Hexadecimal
106
    {
107
        // Swap the bytes from little endian to network byte order.
108
        /** @var array $hex */
109
        $hex = unpack(
110
            'H*',
111
            pack(
112
                'v',
113
                hexdec(bin2hex(substr($this->bytes, 4, 2)))
114
            )
115
        );
116
 
117
        return new Hexadecimal((string) ($hex[1] ?? ''));
118
    }
119
 
120
    public function getTimeHiAndVersion(): Hexadecimal
121
    {
122
        // Swap the bytes from little endian to network byte order.
123
        /** @var array $hex */
124
        $hex = unpack(
125
            'H*',
126
            pack(
127
                'v',
128
                hexdec(bin2hex(substr($this->bytes, 6, 2)))
129
            )
130
        );
131
 
132
        return new Hexadecimal((string) ($hex[1] ?? ''));
133
    }
134
 
135
    public function getTimestamp(): Hexadecimal
136
    {
137
        return new Hexadecimal(sprintf(
138
            '%03x%04s%08s',
139
            hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
140
            $this->getTimeMid()->toString(),
141
            $this->getTimeLow()->toString()
142
        ));
143
    }
144
 
145
    public function getClockSeq(): Hexadecimal
146
    {
147
        if ($this->isMax()) {
148
            $clockSeq = 0xffff;
149
        } elseif ($this->isNil()) {
150
            $clockSeq = 0x0000;
151
        } else {
152
            $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
153
        }
154
 
155
        return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
156
    }
157
 
158
    public function getClockSeqHiAndReserved(): Hexadecimal
159
    {
160
        return new Hexadecimal(bin2hex(substr($this->bytes, 8, 1)));
161
    }
162
 
163
    public function getClockSeqLow(): Hexadecimal
164
    {
165
        return new Hexadecimal(bin2hex(substr($this->bytes, 9, 1)));
166
    }
167
 
168
    public function getNode(): Hexadecimal
169
    {
170
        return new Hexadecimal(bin2hex(substr($this->bytes, 10)));
171
    }
172
 
173
    public function getVersion(): ?int
174
    {
175
        if ($this->isNil() || $this->isMax()) {
176
            return null;
177
        }
178
 
179
        /** @var array $parts */
180
        $parts = unpack('n*', $this->bytes);
181
 
182
        return ((int) $parts[4] >> 4) & 0x00f;
183
    }
184
 
185
    private function isCorrectVariant(): bool
186
    {
187
        if ($this->isNil() || $this->isMax()) {
188
            return true;
189
        }
190
 
191
        $variant = $this->getVariant();
192
 
193
        return $variant === Uuid::RFC_4122 || $variant === Uuid::RESERVED_MICROSOFT;
194
    }
195
}