TinyID::stringSplit()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace TinyID;
6
7
use BCMathExtended\BC;
8
use InvalidArgumentException;
9
10
class TinyID
11
{
12
    private array $dictionary;
13
    private int $dictionaryLength;
14
15 9
    public function __construct(string $dictionary)
16
    {
17 9
        $dictionaryLength = mb_strlen($dictionary, 'UTF-8');
18 9
        if ($dictionaryLength <= 1) {
19 1
            throw new InvalidArgumentException('dictionary too short');
20
        }
21
22 8
        $this->dictionary = $this->stringSplit($dictionary);
23 8
        $this->dictionaryLength = count(array_unique($this->dictionary));
24
25 8
        if ($dictionaryLength !== $this->dictionaryLength) {
26 1
            throw new InvalidArgumentException('dictionary contains duplicated characters');
27
        }
28 7
    }
29
30 8
    private function stringSplit(string $value): array
31
    {
32 8
        return (array)preg_split('//u', $value, -1, PREG_SPLIT_NO_EMPTY);
33
    }
34
35 6
    public function encode(string $value): string
36
    {
37 6
        if (BC::COMPARE_RIGHT_GRATER === BC::comp($value, '0')) {
38 1
            throw new InvalidArgumentException('cannot encode negative number');
39
        }
40
41 5
        $encoded = '';
42
        do {
43 5
            $encoded = $this->dictionary[BC::mod($value, (string)$this->dictionaryLength, 0)] . $encoded;
44 5
            $value = BC::div($value, (string)$this->dictionaryLength, 0);
45 5
        } while ($value);
46
47 5
        return $encoded;
48
    }
49
50 6
    public function decode(string $value): string
51
    {
52 6
        $charsToPosition = array_flip($this->dictionary);
53 6
        $out = '0';
54 6
        foreach (array_reverse($this->stringSplit($value)) as $pos => $tmp) {
55 6
            if (!isset($charsToPosition[$tmp])) {
56 1
                throw new InvalidArgumentException('cannot decode string with characters not in dictionary');
57
            }
58 5
            $out = BC::add($out, BC::mul((string)$charsToPosition[$tmp], BC::pow((string)$this->dictionaryLength, (string)$pos, 0), 0), 0);
59
        }
60
61 5
        return $out;
62
    }
63
}