Skip to content

Commit

Permalink
feat: Adds validation for data decoding in base62.
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavofreze committed Jun 8, 2023
1 parent a453e68 commit 1c06391
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 6 deletions.
19 changes: 13 additions & 6 deletions src/Base62.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

namespace TinyBlocks\Encoder;

use TinyBlocks\Encoder\Internal\Exceptions\InvalidBase62Encoding;

final class Base62
{
private const BASE62_RADIX = 62;
private const BASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
private const HEXADECIMAL_RADIX = 16;
private const BASE62_HEXADECIMAL_RADIX = 16;

public static function encode(string $value): string
{
Expand All @@ -21,16 +23,20 @@ public static function encode(string $value): string
$base62 = str_repeat(self::BASE62_ALPHABET[0], $bytes);

if (empty($hexadecimal)) {
return strtr($base62, self::BASE62_ALPHABET, self::BASE62_ALPHABET);
return $base62;
}

$base62Conversion = gmp_strval(gmp_init($hexadecimal, self::HEXADECIMAL_RADIX), self::BASE62_RADIX);
$number = gmp_init($hexadecimal, self::BASE62_HEXADECIMAL_RADIX);

return strtr($base62 . $base62Conversion, self::BASE62_ALPHABET, self::BASE62_ALPHABET);
return $base62 . gmp_strval($number, self::BASE62_RADIX);
}

public static function decode(string $value): string
{
if (strlen($value) !== strspn($value, self::BASE62_ALPHABET)) {
throw new InvalidBase62Encoding(value: $value);
}

$bytes = 0;

while (!empty($value) && str_starts_with($value, self::BASE62_ALPHABET[0])) {
Expand All @@ -42,9 +48,10 @@ public static function decode(string $value): string
return str_repeat("\x00", $bytes);
}

$hexadecimal = gmp_strval(gmp_init($value, self::BASE62_RADIX), self::HEXADECIMAL_RADIX);
$number = gmp_init($value, self::BASE62_RADIX);
$hexadecimal = gmp_strval($number, self::BASE62_HEXADECIMAL_RADIX);

if (strlen($hexadecimal) % 2 !== 0) {
if (strlen($hexadecimal) % 2) {
$hexadecimal = '0' . $hexadecimal;
}

Expand Down
14 changes: 14 additions & 0 deletions src/Internal/Exceptions/InvalidBase62Encoding.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace TinyBlocks\Encoder\Internal\Exceptions;

use RuntimeException;

final class InvalidBase62Encoding extends RuntimeException
{
public function __construct(private readonly string $value)
{
$template = 'The value <%s> does not have a valid base62 encoding.';
parent::__construct(message: sprintf($template, $this->value));
}
}
12 changes: 12 additions & 0 deletions tests/Base62Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace TinyBlocks\Encoder;

use PHPUnit\Framework\TestCase;
use TinyBlocks\Encoder\Internal\Exceptions\InvalidBase62Encoding;

class Base62Test extends TestCase
{
Expand Down Expand Up @@ -37,6 +38,17 @@ public function testEncodeAndDecodeWithLeadingZeroBytes(string $value): void
self::assertEquals($value, $actual);
}

public function testWhenInvalidBase62Encoding(): void
{
$value = hex2bin('9850EEEC191BF4FF26F99315CE43B0C8');
$template = 'The value <%s> does not have a valid base62 encoding.';

$this->expectException(InvalidBase62Encoding::class);
$this->expectExceptionMessage(sprintf($template, $value));

Base62::decode(value: $value);
}

public function providerForTestEncode(): array
{
return [
Expand Down

0 comments on commit 1c06391

Please sign in to comment.