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 13declare(strict_types=1); 14 15namespace Ramsey\Uuid\Rfc4122; 16 17use Ramsey\Uuid\Exception\InvalidBytesException; 18use Ramsey\Uuid\Uuid; 19 20use function decbin; 21use function str_pad; 22use function strlen; 23use function strpos; 24use function substr; 25use function unpack; 26 27use const STR_PAD_LEFT; 28 29/** 30 * Provides common functionality for handling the variant, as defined by RFC 4122 31 * 32 * @psalm-immutable 33 */ 34trait VariantTrait 35{ 36 /** 37 * Returns the bytes that comprise the fields 38 */ 39 abstract public function getBytes(): string; 40 41 /** 42 * Returns the variant identifier, according to RFC 4122, for the given bytes 43 * 44 * The following values may be returned: 45 * 46 * - `0` -- Reserved, NCS backward compatibility. 47 * - `2` -- The variant specified in RFC 4122. 48 * - `6` -- Reserved, Microsoft Corporation backward compatibility. 49 * - `7` -- Reserved for future definition. 50 * 51 * @link https://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant 52 * 53 * @return int The variant identifier, according to RFC 4122 54 */ 55 public function getVariant(): int 56 { 57 if (strlen($this->getBytes()) !== 16) { 58 throw new InvalidBytesException('Invalid number of bytes'); 59 } 60 61 $parts = unpack('n*', $this->getBytes()); 62 63 // $parts[5] is a 16-bit, unsigned integer containing the variant bits 64 // of the UUID. We convert this integer into a string containing a 65 // binary representation, padded to 16 characters. We analyze the first 66 // three characters (three most-significant bits) to determine the 67 // variant. 68 $binary = str_pad( 69 decbin((int) $parts[5]), 70 16, 71 '0', 72 STR_PAD_LEFT 73 ); 74 75 $msb = substr($binary, 0, 3); 76 77 if ($msb === '111') { 78 $variant = Uuid::RESERVED_FUTURE; 79 } elseif ($msb === '110') { 80 $variant = Uuid::RESERVED_MICROSOFT; 81 } elseif (strpos($msb, '10') === 0) { 82 $variant = Uuid::RFC_4122; 83 } else { 84 $variant = Uuid::RESERVED_NCS; 85 } 86 87 return $variant; 88 } 89} 90