Skip to content

Commit 2298018

Browse files
authored
refactor(cuid2): leverage markrogoyski/math-php when GMP extension is unavailable (#261)
Signed-off-by: Alan Brault <alan.brault@visus.io>
1 parent 208d23f commit 2298018

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ A PHP implementation of collision-resistant ids. You can read more about CUIDs f
1717

1818
You can install visus/cuid2 as a [composer package](https://packagist.org/packages/visus/cuid2):
1919

20-
> [!IMPORTANT]
21-
> The PHP extension [GMP](https://www.php.net/manual/en/intro.gmp.php) is required in order to use this library.
22-
2320
```shell
2421
composer require visus/cuid2
2522
```
23+
> [!TIP]
24+
> Consider installing/enabling the PHP extension [GMP](https://www.php.net/manual/en/intro.gmp.php).
25+
> If this is not an option then [markrogoyski/math-php](https://github.com/markrogoyski/math-php) will be used as a fallback.
2626
2727
## Quick Example
2828

composer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
],
1616
"require": {
1717
"php": "^8.1",
18-
"ext-gmp": "*",
18+
"markrogoyski/math-php": "^2.11",
1919
"symfony/polyfill-php83": "^1.32"
2020
},
2121
"require-dev": {
@@ -29,6 +29,9 @@
2929
"squizlabs/php_codesniffer": "^3.7",
3030
"vimeo/psalm": "^6.0"
3131
},
32+
"suggest": {
33+
"ext-gmp": "Allows for quicker Base16 to Base36 conversion"
34+
},
3235
"minimum-stability": "dev",
3336
"prefer-stable": true,
3437
"autoload": {

src/Cuid2.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@
77
use DateTime;
88
use Exception;
99
use JsonSerializable;
10+
use MathPHP\Exception\BadParameterException;
11+
use MathPHP\Functions\BaseEncoderDecoder;
1012
use OutOfRangeException;
1113
use Override;
1214

1315
final class Cuid2 implements JsonSerializable
1416
{
17+
public const BASE36_ALPHANUMERIC = '0123456789abcdefghijklmnopqrstuvwxyz';
18+
1519
private readonly int $counter;
1620

1721
/**
@@ -99,12 +103,13 @@ public function jsonSerialize(): string
99103

100104
/**
101105
* @throws Exception
106+
* @throws BadParameterException
102107
*/
103108
private function render(): string
104109
{
105110
if (!in_array('sha3-512', hash_algos())) {
106111
// phpcs:ignore Generic.Files.LineLength
107-
throw new Exception('SHA3-512 appears to be unsupported - make sure you have support for it, or upgrade your version of PHP.');
112+
throw new InvalidOperationException('SHA3-512 appears to be unsupported - make sure you have support for it, or upgrade your version of PHP.');
108113
}
109114

110115
$hash = hash_init('sha3-512');
@@ -117,8 +122,25 @@ private function render(): string
117122

118123
$hash = hash_final($hash);
119124

120-
$result = gmp_strval(gmp_init($hash, 16), 36);
125+
$result = self::convert($hash);
121126

122127
return $this->prefix . substr($result, 0, $this->length - 1);
123128
}
129+
130+
/**
131+
* Converts Base16 to Base36
132+
*
133+
* @param string $value
134+
* @return string
135+
* @throws BadParameterException
136+
*/
137+
private static function convert(string $value): string
138+
{
139+
if (extension_loaded('gmp')) {
140+
return gmp_strval(gmp_init($value, 16), 36);
141+
}
142+
143+
$integer = BaseEncoderDecoder::createArbitraryInteger($value, 16);
144+
return BaseEncoderDecoder::toBase($integer, 36, self::BASE36_ALPHANUMERIC);
145+
}
124146
}

src/InvalidOperationException.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Visus\Cuid2;
4+
5+
use Exception;
6+
7+
/**
8+
* Exception that is thrown when a method call is invalid for the object's current state.
9+
*/
10+
final class InvalidOperationException extends Exception
11+
{
12+
}

0 commit comments

Comments
 (0)