~earboxer/bare-mess-php

f970915988422bab3444b8b1279bd81b4f54b283 — Zach DeCook 3 years ago c9e497b
* Primitives: Add UInt
2 files changed, 82 insertions(+), 0 deletions(-)

A src/UInt.php
M tests/PrimitivesTest.php
A src/UInt.php => src/UInt.php +44 -0
@@ 0,0 1,44 @@
<?php

namespace BareMess;

class UInt
{
    use Mutatable;
    private int $value = 0;

    public function __construct(& $mess = null)
    {
        if ($mess === null){
            return;
        }
        $this->value = 0;
        for($i = 0; $i < strlen($mess); $i++) {
            // Least significant bits first
            $this->value += (ord($mess[$i]) & 0b01111111) << (7 * $i);
            if(! (ord($mess[$i]) & 0b10000000) ) {
                $mess = substr($mess, $i + 1);
                return;
            }
        }
    }

    public function mess()
    {
        $mess = '';
        // The number of bytes should be greater than or equal to the number required,
        // value < pow(2, 7 * bytes)
        $bytes = floor(log($this->value + 1, 2) / 7) + 1;

        for ($i = 0; $i < $bytes; $i++) {
            // BARE encodes integers as little-endian (least significant first),
            $bits = ($this->value >> ($i * 7)) & 0b01111111;
            // with the most significant bit being set for all except the last byte.
            if ($i != $bytes - 1) {
                $bits = $bits | 0b10000000;
            }
            $mess .= chr($bits);
        }
        return $mess;
    }
}

M tests/PrimitivesTest.php => tests/PrimitivesTest.php +38 -0
@@ 6,6 6,7 @@ use BareMess\Bare;
use BareMess\Example\PublicKey;
use BareMess\{I8,I16,I32,I64};
use BareMess\{U8,U16,U32,U64};
use BareMess\UInt;
use PHPUnit\Framework\TestCase;

class PrimitivesTest extends TestCase


@@ 87,6 88,43 @@ class PrimitivesTest extends TestCase
        // TODO: Test strings longer than 127 characters
    }

    public function testUInt()
    {
        // Various equivalent uints.
        $mess = "\xC2\x80\x00\xC2\x00\x42";
        $uint = new UInt($mess);
        $uint2 = new UInt($mess);
        $uint3 = new UInt($mess);
        $this->assertEquals('', $mess);
        $this->assertEquals(66, $uint->get());
        $this->assertEquals(66, $uint2->get());
        $this->assertEquals(66, $uint3->get());
        $this->assertEquals("\x42", $uint->mess());
        $this->assertEquals("\x42", $uint2->mess());
        $this->assertEquals("\x42", $uint3->mess());

        $uint->set(0);
        $this->assertEquals("\x00", $uint->mess());

        // This is usually equal to PHP_INT_MAX
        $sixtythreeBitNumber = 0x7FFFFFFFFFFFFFFF;
        $mess = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F";
        $uint = new UInt($mess);
        $this->assertEquals("", $mess);
        $this->assertEquals($sixtythreeBitNumber, $uint->get());
        $mess = $uint->mess();
        $uint2 = new UInt($mess);
        $this->assertEquals('', $mess);
        $this->assertEquals($sixtythreeBitNumber, $uint2->get());

        // Test round-tripping with mess (since these have multiple representations).
        $uint->set(pow(2,7*8));
        $mess = $uint->mess();
        $uint2 = new UInt($mess);
        $this->assertEquals("", $mess);
        $this->assertEquals(pow(2, 7*8), $uint2->get());
    }

    public function testUs()
    {
        $u8 = new U8();