ConverterTrait::int64ToBytes()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
/**
4
 * Copyright (c) 2020 UMI
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in all
14
 * copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 */
24
25
declare(strict_types=1);
26
27
namespace UmiTop\UmiCore\Util;
28
29
use Exception;
30
31
/**
32
 * Trait ConverterTrait
33
 * @package UmiTop\UmiCore\Util
34
 */
35
trait ConverterTrait
36
{
37
    /**
38
     * Преобразует версию адреса в префикс.
39
     * @param int $version Версия адреса.
40
     * @return string
41
     * @throws Exception
42
     */
43 9
    private function versionToPrefix(int $version): string
44
    {
45 9
        if ($version === 0) {
46 2
            return 'genesis';
47
        }
48
49 7
        $ch1 = $version >> 10 & 0x1F;
50 7
        $ch2 = $version >> 5 & 0x1F;
51 7
        $ch3 = $version & 0x1F;
52
53 7
        $this->checkPrefixChars([$ch1, $ch2, $ch3]);
54
55 7
        return chr($ch1 + 96) . chr($ch2 + 96) . chr($ch3 + 96);
56
    }
57
58
    /**
59
     * Преобразует бинарное представление версии в префикс.
60
     * @param string $bytes Версия в бинарном виде, длина 2 байта.
61
     * @return string
62
     * @throws Exception
63
     */
64 8
    private function bytesToPrefix(string $bytes): string
65
    {
66 8
        return $this->versionToPrefix($this->bytesToUint16($bytes));
67
    }
68
69
    /**
70
     * Преобразует префикс в версию.
71
     * @param string $prefix Префикс адреса, три символа.
72
     * @return int
73
     * @throws Exception
74
     */
75 25
    private function prefixToVersion(string $prefix): int
76
    {
77 25
        if ($prefix === 'genesis') {
78 2
            return 0;
79
        }
80
81 25
        if (strlen($prefix) !== 3) {
82 2
            throw new Exception('bech32: invalid prefix length');
83
        }
84
85 25
        $ch1 = ord($prefix[0]) - 96;
86 25
        $ch2 = ord($prefix[1]) - 96;
87 25
        $ch3 = ord($prefix[2]) - 96;
88
89 25
        $this->checkPrefixChars([$ch1, $ch2, $ch3]);
90
91 25
        return ($ch1 << 10) + ($ch2 << 5) + $ch3;
92
    }
93
94
    /**
95
     * Преобразует префикс в бинарное представление.
96
     * @param string $prefix Префикс адреса, три символа.
97
     * @return string
98
     * @throws Exception
99
     */
100 24
    private function prefixToBytes(string $prefix): string
101
    {
102 24
        return $this->uint16ToBytes($this->prefixToVersion($prefix));
103
    }
104
105
    /**
106
     * @param array<int, int> $chars
107
     * @return void
108
     * @throws Exception
109
     */
110 25
    private function checkPrefixChars(array $chars): void
111
    {
112 25
        foreach ($chars as $chr) {
113 25
            if ($chr < 1 || $chr > 26) {
114 25
                throw new Exception('bech32: invalid prefix character');
115
            }
116
        }
117 25
    }
118
119
    /**
120
     * @param int $value
121
     * @return string
122
     */
123 27
    private function uint16ToBytes(int $value): string
124
    {
125 27
        return (chr($value >> 8 & 0xff) . chr($value & 0xff));
126
    }
127
128
    /**
129
     * @param string $bytes
130
     * @return int
131
     */
132 11
    private function bytesToUint16(string $bytes): int
133
    {
134 11
        return ((ord($bytes[0]) << 8) + ord($bytes[1]));
135
    }
136
137
    /**
138
     * @param int $value
139
     * @return string
140
     */
141 3
    private function int64ToBytes(int $value): string
142
    {
143 3
        return chr($value >> 56 & 0xff) . chr($value >> 48 & 0xff) . chr($value >> 40 & 0xff)
144 3
            . chr($value >> 32 & 0xff) . chr($value >> 24 & 0xff) . chr($value >> 16 & 0xff)
145 3
            . chr($value >> 8 & 0xff) . chr($value & 0xff);
146
    }
147
148
    /**
149
     * @param string $bytes
150
     * @return int
151
     */
152 2
    private function bytesToInt64(string $bytes): int
153
    {
154 2
        return (ord($bytes[0]) << 56) | (ord($bytes[1]) << 48) | (ord($bytes[2]) << 40) | (ord($bytes[3]) << 32)
155 2
            | (ord($bytes[4]) << 24) | (ord($bytes[5]) << 16) | (ord($bytes[6]) << 8) | (ord($bytes[7]));
156
    }
157
}
158