Completed
Pull Request — master (#63)
by Eugene
05:25
created

DecimalExtension::unpackExt()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
nc 6
nop 2
dl 0
loc 17
rs 9.9
c 1
b 0
f 0
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
    public const DEFAULT_PRECISION = 38;
24
25
    private const TYPE = 1;
26
27
    public function getType() : int
28
    {
29
        return self::TYPE;
30
    }
31
32
    public function pack(Packer $packer, $value) : ?string
33
    {
34
        if (!$value instanceof Decimal) {
35
            return null;
36
        }
37
38
        // @see https://github.com/php-decimal/ext-decimal/issues/22#issuecomment-512364914
39
        $data = $value->toFixed(self::DEFAULT_PRECISION);
40
41
        if ('-' === $data[0]) {
42
            $nibble = 'd';
43
            $data = \substr($data, 1);
44
        } else {
45
            $nibble = 'c';
46
        }
47
48
        if ($scale = \strpos($data, '.')) {
49
            $data = \substr_replace($data, '', $scale, 1);
50
        }
51
52
        $data = (0 === \strlen($data) % 2) ? "0{$data}{$nibble}" : "{$data}{$nibble}";
53
54
        return $packer->packExt(self::TYPE,
55
            $packer->packInt($scale).\hex2bin($data)
56
        );
57
    }
58
59
    public function unpackExt(BufferUnpacker $unpacker, int $extLength)
60
    {
61
        $scale = $unpacker->unpackInt();
62
        $data = $unpacker->read($extLength - 1);
63
        $data = \bin2hex($data);
64
65
        $sign = 'd' === $data[-1] ? '-' : '';
66
        $dec = \substr($data, 0, -1);
67
68
        if (0 !== $scale) {
69
            $length = \strlen($dec);
70
            $dec = ($length <= $scale)
71
                ? \substr_replace($dec, '0.'.\str_repeat('0', $scale - $length), -$scale, 0)
72
                : \substr_replace($dec, '.', -$scale, 0);
73
        }
74
75
        return new Decimal($sign.$dec, self::DEFAULT_PRECISION);
76
    }
77
}
78