Passed
Push — master ( 66c616...00643e )
by Eugene
03:07
created

DecimalExtension   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 58
Duplicated Lines 0 %

Test Coverage

Coverage 69.05%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 31
dl 0
loc 58
rs 10
c 1
b 0
f 0
wmc 11
ccs 29
cts 42
cp 0.6905

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getType() 0 3 1
A unpackExt() 0 17 4
A pack() 0 28 6
1
<?php
2
3
/**
4
 * This file is part of the Tarantool Client package.
5
 *
6
 * (c) Eugene Leonovich <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Tarantool\Client\Packer\Extension;
15
16
use Decimal\Decimal;
0 ignored issues
show
Bug introduced by
The type Decimal\Decimal was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use MessagePack\BufferUnpacker;
18
use MessagePack\Packer;
19
use MessagePack\TypeTransformer\Extension;
20
21
class DecimalExtension implements Extension
22
{
23
    private const TYPE = 1;
24
    private const PRECISION = 38;
25
26 14
    public function getType() : int
27
    {
28 14
        return self::TYPE;
29
    }
30
31 14
    public function pack(Packer $packer, $value) : ?string
32
    {
33 14
        if (!$value instanceof Decimal) {
34
            return null;
35
        }
36
37
        // @see https://github.com/php-decimal/ext-decimal/issues/22#issuecomment-512364914
38 14
        $data = $value->toFixed(self::PRECISION);
39
40 14
        if ('-' === $data[0]) {
41 2
            $nibble = 'd';
42 2
            $data = \substr($data, 1);
43
        } else {
44 12
            $nibble = 'c';
45
        }
46
47 14
        $pieces = \explode('.', $data, 2);
48 14
        if (isset($pieces[1])) {
49 14
            $pieces[1] = \rtrim($pieces[1], '0');
50
        }
51
52 14
        $data = "{$pieces[0]}{$pieces[1]}{$nibble}";
53 14
        if (0 !== \strlen($data) % 2) {
54 7
            $data = "0{$data}";
55
        }
56
57 14
        return $packer->packExt(self::TYPE,
58 14
            $packer->packInt(empty($pieces[1]) ? 0 : \strlen($pieces[1])).\hex2bin($data)
59
        );
60
    }
61
62 14
    public function unpackExt(BufferUnpacker $unpacker, int $extLength)
63
    {
64 14
        $scale = $unpacker->unpackInt();
65 14
        $data = $unpacker->read($extLength - 1);
66 14
        $data = \bin2hex($data);
67
68 14
        $sign = 'd' === $data[-1] ? '-' : '';
69 14
        $dec = \substr($data, 0, -1);
70
71 14
        if (0 !== $scale) {
72 10
            $length = \strlen($dec);
73 10
            $dec = ($length <= $scale)
74 4
                ? \substr_replace($dec, '0.'.\str_repeat('0', $scale - $length), -$scale, 0)
75 10
                : \substr_replace($dec, '.', -$scale, 0);
76
        }
77
78 14
        return new Decimal($sign.$dec, self::PRECISION);
79
    }
80
}
81