Skip to content

Commit 85b97ea

Browse files
authored
Merge pull request #74 from afk11/rewrite-varint
VarInt: rewrite for better performance
2 parents 5c2c8c0 + 98c597b commit 85b97ea

1 file changed

Lines changed: 30 additions & 62 deletions

File tree

src/Buffertools/Types/VarInt.php

Lines changed: 30 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -9,62 +9,39 @@
99

1010
class VarInt extends AbstractType
1111
{
12-
/**
13-
* @var array
14-
*/
15-
private $sizeInfo = [];
16-
17-
/**
18-
* @param int $byteOrder
19-
*/
20-
public function __construct(int $byteOrder = ByteOrder::BE)
21-
{
22-
parent::__construct($byteOrder);
23-
$two = gmp_init(2, 10);
24-
$this->sizeInfo = [
25-
[Uint16::class, gmp_pow($two, 16), 0xfd],
26-
[Uint32::class, gmp_pow($two, 32), 0xfe],
27-
[Uint64::class, gmp_pow($two, 64), 0xff],
28-
];
29-
}
30-
3112
/**
3213
* @param \GMP $integer
3314
* @return array
3415
*/
35-
public function solveWriteSize(\GMP $integer): array
16+
public function solveWriteSize(\GMP $integer)
3617
{
37-
foreach ($this->sizeInfo as $config) {
38-
list($uint, $limit, $prefix) = $config;
39-
if (gmp_cmp($integer, $limit) < 0) {
40-
return [
41-
new $uint(ByteOrder::LE),
42-
$prefix
43-
];
44-
}
18+
if (gmp_cmp($integer, gmp_pow(gmp_init(2), 16)) < 0) {
19+
return [new Uint16(ByteOrder::LE), 0xfd];
20+
} else if (gmp_cmp($integer, gmp_pow(gmp_init(2), 32)) < 0) {
21+
return [new Uint32(ByteOrder::LE), 0xfe];
22+
} else if (gmp_cmp($integer, gmp_pow(gmp_init(2), 64)) < 0) {
23+
return [new Uint64(ByteOrder::LE), 0xff];
24+
} else {
25+
throw new \InvalidArgumentException('Integer too large, exceeds 64 bit');
4526
}
46-
47-
throw new \InvalidArgumentException('Integer too large, exceeds 64 bit');
4827
}
4928

5029
/**
51-
* @param int $givenPrefix
30+
* @param \GMP $givenPrefix
5231
* @return UintInterface[]
5332
* @throws \InvalidArgumentException
5433
*/
55-
public function solveReadSize(int $givenPrefix): array
34+
public function solveReadSize(\GMP $givenPrefix)
5635
{
57-
foreach ($this->sizeInfo as $config) {
58-
$uint = $config[0];
59-
$prefix = $config[2];
60-
if ($givenPrefix === $prefix) {
61-
return [
62-
new $uint(ByteOrder::LE)
63-
];
64-
}
36+
if (gmp_cmp($givenPrefix, 0xfd) === 0) {
37+
return [new Uint16(ByteOrder::LE)];
38+
} else if (gmp_cmp($givenPrefix, 0xfe) === 0) {
39+
return [new Uint32(ByteOrder::LE)];
40+
} else if (gmp_cmp($givenPrefix, 0xff) === 0) {
41+
return [new Uint64(ByteOrder::LE)];
6542
}
6643

67-
throw new \InvalidArgumentException('Integer too large, exceeds 64 bit');
44+
throw new \InvalidArgumentException('Unknown varint prefix');
6845
}
6946

7047
/**
@@ -73,35 +50,26 @@ public function solveReadSize(int $givenPrefix): array
7350
*/
7451
public function write($integer): string
7552
{
76-
$gmp = gmp_init($integer, 10);
77-
$uint8 = new Uint8();
78-
if (gmp_cmp($gmp, gmp_init(0xfd, 10)) < 0) {
79-
$int = $uint8;
80-
} else {
81-
list ($int, $prefix) = $this->solveWriteSize($gmp);
82-
$prefix = gmp_strval($prefix, 10);
53+
$gmpInt = gmp_init($integer, 10);
54+
if (gmp_cmp($gmpInt, gmp_init(0xfd, 10)) < 0) {
55+
return pack("C", $integer);
8356
}
84-
85-
$prefix = isset($prefix) ? $uint8->write($prefix) : '';
86-
$bits = $prefix . $int->write($integer);
87-
88-
return $bits;
57+
list ($int, $prefix) = $this->solveWriteSize($gmpInt);
58+
return pack("C", $prefix) . $int->write($integer);
8959
}
9060

9161
/**
9262
* {@inheritdoc}
9363
* @see \BitWasp\Buffertools\Types\TypeInterface::read()
9464
*/
95-
public function read(Parser $parser): string
65+
public function read(Parser $parser)
9666
{
97-
$uint8 = new Uint8();
98-
$int = (int) $uint8->readBits($parser);
99-
100-
if ($int < 0xfd) {
101-
return (string) $int;
102-
} else {
103-
$uint = $this->solveReadSize($int)[0];
104-
return $uint->read($parser);
67+
$byte = unpack("C", $parser->readBytes(1)->getBinary())[1];
68+
if (gmp_init($byte) < 0xfd) {
69+
return $byte;
10570
}
71+
72+
list ($uint) = $this->solveReadSize(gmp_init($byte, 10));
73+
return $uint->read($parser);
10674
}
10775
}

0 commit comments

Comments
 (0)