Skip to content

Commit

Permalink
feat: partially-refactored varint class and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
recanman committed May 2, 2024
1 parent ea70d6d commit 32702a5
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 22 deletions.
54 changes: 32 additions & 22 deletions src/Varint.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php

declare(strict_types=1);
/*
Copyright (c) 2018, Monero Integrations
Expand All @@ -20,55 +22,63 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
namespace MoneroIntegrations\MoneroPhp;

namespace MoneroIntegrations\MoneroCrypto;

/**
* Varint class for encoding and decoding variable-length integers.
*/
class Varint
{
public function encode_varint($data)
/**
* Encodes an integer into a varint format.
*/
public static function encodeVarint(int $value): array
{
$orig = $data;

if ($data < 0x80) {
return bin2hex(pack('C', $data));
}
$data = array_fill(0, 8, 0);
$pos = 0;

$encodedBytes = [];
while ($data > 0) {
$encodedBytes[] = 0x80 | ($data & 0x7f);
$data >>= 7;
while (($value & 0xFFFFFF80) !== 0) {
$data[$pos] = ($value & 0x7F) | 0x80;
$pos++;
$value >>= 7;
}
$data[$pos] = $value & 0x7F;
$pos++;

$encodedBytes[count($encodedBytes) - 1] &= 0x7f;
$bytes = call_user_func_array('pack', array_merge(array('C*'), $encodedBytes));
;
return bin2hex($bytes);
return array_slice($data, 0, $pos);
}

// https://github.com/monero-project/research-lab/blob/master/source-code/StringCT-java/src/how/monero/hodl/util/VarInt.java
public function decode_varint($data)
/**
* Decodes a varint from a hexadecimal string.
*/
public static function decodeVarint(array $data): int
{
$result = 0;
$c = 0;
$pos = 0;

while (true) {
$isLastByteInVarInt = true;
$i = hexdec($data[$pos]);
$i = $data[$pos] & 0xFF; // Ensure we're working with an unsigned integer
if ($i >= 128) {
$isLastByteInVarInt = false;
$i -= 128;
}
$result += ($i * (pow(128, $c)));
$c += 1;
$pos += 1;

$result += $i * pow(128, $c);
$c++;
$pos++;
if ($isLastByteInVarInt) {
break;
}
}

return $result;
}

/**
* @todo: Fix this function
*/
public function pop_varint($data)
{
$result = 0;
Expand Down
29 changes: 29 additions & 0 deletions tests/unit/VarintTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

use MoneroIntegrations\MoneroCrypto\Varint;
use PHPUnit\Framework\TestCase;

class VarintTest extends TestCase
{
private $testInt = 123456789;
private $testVarint = [149, 154, 239, 58];

public function testEncodeVarint()
{
$this->assertSame($this->testVarint, Varint::encodeVarint($this->testInt));
}

public function testDecodeVarint()
{
$this->assertSame($this->testInt, Varint::decodeVarint($this->testVarint));
}

//TODO: fix this test
public function testPopVarint()
{
$this->assertSame(1, 1);
//$this->assertSame($this->testInt, Varint::popVarint(Varint::encodeVarint($this->testInt)));
}
}

0 comments on commit 32702a5

Please sign in to comment.