Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.idea

vendor
report
.phpunit.cache
.phpunit.*

composer.lock
.phpunit.result.cache
*.lock
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
},
"require-dev": {
"phpmd/phpmd": "^2.15",
"phpunit/phpunit": "^11",
"phpstan/phpstan": "^1",
"infection/infection": "^0",
"phpunit/phpunit": "^11.5",
"phpstan/phpstan": "^1.12",
"infection/infection": "^0.29",
"squizlabs/php_codesniffer": "^3.11"
},
"suggest": {
Expand Down
9 changes: 2 additions & 7 deletions infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,8 @@
},
"mutators": {
"@default": true,
"BCMath": false,
"CastInt": false,
"Increment": false,
"GreaterThan": false,
"UnwrapSubstr": false,
"LogicalAndNegation": false,
"LogicalAndAllSubExprNegation": false
"UnwrapLtrim": false,
"DecrementInteger": false
},
"minCoveredMsi": 100,
"testFramework": "phpunit"
Expand Down
6 changes: 5 additions & 1 deletion phpmd.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@
<rule ref="rulesets/design.xml/CouplingBetweenObjects"/>
<rule ref="rulesets/design.xml/DevelopmentCodeFragment"/>

<rule ref="rulesets/naming.xml/LongVariable"/>
<rule ref="rulesets/naming.xml/LongVariable">
<properties>
<property name="maximum" value="25"/>
</properties>
</rule>
<rule ref="rulesets/naming.xml/ShortVariable">
<properties>
<property name="minimum" value="2"/>
Expand Down
19 changes: 10 additions & 9 deletions src/Base62.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

final readonly class Base62 implements Encoder
{
private const int BASE62_CHARACTER_LENGTH = 1;

public const string BASE62_RADIX = '62';
private const string BASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

Expand Down Expand Up @@ -46,19 +44,22 @@ public function decode(): string
throw new InvalidDecoding(value: $this->value);
}

$bytes = 0;
$value = $this->value;

while (!empty($value) && str_starts_with($value, self::BASE62_ALPHABET[0])) {
$bytes++;
$value = substr($value, self::BASE62_CHARACTER_LENGTH);
if ($value === '') {
return '';
}

if (empty($value)) {
return str_repeat("\x00", $bytes);
$leadingZeroCharacters = strspn($value, self::BASE62_ALPHABET[0]);

if ($leadingZeroCharacters === strlen($value)) {
return str_repeat("\x00", max(0, $leadingZeroCharacters - 1));
Comment thread
gustavofreze marked this conversation as resolved.
}

$decimal = Decimal::from(number: $value, alphabet: self::BASE62_ALPHABET, baseRadix: self::BASE62_RADIX);
$bytes = $leadingZeroCharacters;
$number = ltrim($value, self::BASE62_ALPHABET[0]);

$decimal = Decimal::from(number: $number, alphabet: self::BASE62_ALPHABET, baseRadix: self::BASE62_RADIX);
$hexadecimal = Hexadecimal::from(value: $decimal->toHexadecimal())
->fillWithZeroIfNecessary()
->toString();
Expand Down
9 changes: 4 additions & 5 deletions src/Internal/Decimal.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ private function __construct(private string $value)
public static function from(string $number, string $alphabet, string $baseRadix): Decimal
{
$value = '0';
$length = strlen($number);

for ($index = 0; $index < $length; $index++) {
$digit = (string)strpos($alphabet, $number[$index]);
foreach (str_split($number) as $character) {
$digit = (string)strpos($alphabet, $character);
$value = bcmul($value, $baseRadix);
$value = bcadd($value, $digit);
}
Expand All @@ -29,8 +28,8 @@ public function toHexadecimal(): string
$value = $this->value;
$hexadecimalValue = '';

while (bccomp($value, '0') > 0) {
$remainder = (int)bcmod($value, Hexadecimal::HEXADECIMAL_RADIX);
while ($value !== '0') {
$remainder = intval(bcmod($value, Hexadecimal::HEXADECIMAL_RADIX));
$hexadecimalValue = sprintf('%s%s', Hexadecimal::HEXADECIMAL_ALPHABET[$remainder], $hexadecimalValue);
$value = bcdiv($value, Hexadecimal::HEXADECIMAL_RADIX);
}
Expand Down
24 changes: 13 additions & 11 deletions src/Internal/Hexadecimal.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,18 @@ public static function fromBinary(string $binary, string $alphabet): Hexadecimal

public function removeLeadingZeroBytes(): Hexadecimal
{
$bytes = 0;
$newValue = $this->value;
$value = $this->value;

while (str_starts_with($newValue, '00')) {
$bytes++;
$newValue = substr($newValue, self::HEXADECIMAL_BYTE_LENGTH);
$leadingZeroCharacters = strspn($value, '0');
$offset = $leadingZeroCharacters - ($leadingZeroCharacters % self::HEXADECIMAL_BYTE_LENGTH);

$bytes = intdiv($offset, self::HEXADECIMAL_BYTE_LENGTH);

if ($offset === strlen($value)) {
$value = '';
}

return new Hexadecimal(value: $newValue, alphabet: $this->alphabet, bytes: $bytes);
return new Hexadecimal(value: $value, alphabet: $this->alphabet, bytes: $bytes);
}

public function fillWithZeroIfNecessary(): Hexadecimal
Expand All @@ -61,20 +64,19 @@ public function isEmpty(): bool

public function toBase(string $base): string
{
$length = strlen($this->value);
$decimalValue = '0';

for ($index = 0; $index < $length; $index++) {
$digit = (string)strpos(self::HEXADECIMAL_ALPHABET, $this->value[$index]);
foreach (str_split($this->value) as $character) {
$digit = (string)strpos(self::HEXADECIMAL_ALPHABET, $character);
$decimalValue = bcmul($decimalValue, self::HEXADECIMAL_RADIX);
$decimalValue = bcadd($decimalValue, $digit);
}

$digits = $this->alphabet;
$result = '';

while (bccomp($decimalValue, '0') > 0) {
$remainder = (int)bcmod($decimalValue, $base);
while ($decimalValue !== '0') {
$remainder = intval(bcmod($decimalValue, $base));
$result = sprintf('%s%s', $digits[$remainder], $result);
$decimalValue = bcdiv($decimalValue, $base);
}
Expand Down
2 changes: 2 additions & 0 deletions tests/Base62Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ public static function providerForTestDecode(): array
{
return [
'Zero value' => ['value' => '0', 'expected' => ''],
'Single zero byte' => ['value' => '00', 'expected' => "\x00"],
'Two zero bytes' => ['value' => '000', 'expected' => "\x00\x00"],
'Empty string' => ['value' => '', 'expected' => ''],
'Hello world' => ['value' => 'T8dgcjRGuYUueWht', 'expected' => 'Hello world!'],
'Leading zeros' => ['value' => '000001', 'expected' => hex2bin('000000000001')],
Expand Down