Skip to content

Commit

Permalink
Add getRemainingCount(), hasRemaining() and release() to BufferUnpacker
Browse files Browse the repository at this point in the history
  • Loading branch information
rybakit committed Jan 4, 2020
1 parent 5531abe commit 342a747
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 10 deletions.
18 changes: 18 additions & 0 deletions README.md
Expand Up @@ -201,6 +201,24 @@ To skip bytes from the current position, use `skip`:
$unpacker->skip(10); // set position to 10 bytes ahead of the current position
```

To get the number of remaining (unread) bytes in the buffer:

```php
$unreadBytesCount = $unpacker->getRemainingCount();
```

To check whether the buffer has unread data:

```php
$hasUnreadBytes = $unpacker->hasRemaining();
```

If needed, you can remove already read data from the buffer by calling:

```php
$releasedBytesCount = $unpacker->release();
```

With the `read` method you can read raw (packed) data:

```php
Expand Down
28 changes: 23 additions & 5 deletions src/BufferUnpacker.php
Expand Up @@ -122,6 +122,29 @@ public function skip(int $length) : self
return $this;
}

public function getRemainingCount() : int
{
return \strlen($this->buffer) - $this->offset;
}

public function hasRemaining() : bool
{
return isset($this->buffer[$this->offset]);
}

public function release() : int
{
if (0 === $this->offset) {
return 0;
}

$releasedBytesCount = $this->offset;
$this->buffer = isset($this->buffer[$this->offset]) ? \substr($this->buffer, $this->offset) : '';
$this->offset = 0;

return $releasedBytesCount;
}

/**
* @param int $length
*
Expand Down Expand Up @@ -153,11 +176,6 @@ public function tryUnpack() : array
$this->offset = $offset;
}

if ($this->offset) {
$this->buffer = isset($this->buffer[$this->offset]) ? \substr($this->buffer, $this->offset) : '';
$this->offset = 0;
}

return $data;
}

Expand Down
53 changes: 48 additions & 5 deletions tests/Unit/BufferUnpackerTest.php
Expand Up @@ -45,6 +45,8 @@ public function testUnpack($raw, string $packed) : void
$isOrHasObject
? self::assertEquals($raw, $this->unpacker->unpack())
: self::assertSame($raw, $this->unpacker->unpack());

self::assertFalse($this->unpacker->hasRemaining());
}

/**
Expand Down Expand Up @@ -159,12 +161,11 @@ public function testUnpackBigIntAsGmp() : void

public function testResetEmptiesBuffer() : void
{
$this->unpacker->append("\xc3")->reset();

$this->expectException(InsufficientDataException::class);
$this->expectExceptionMessage('Not enough data to read.');
$this->unpacker->append("\xc3");
self::assertSame(1, $this->unpacker->getRemainingCount());

$this->unpacker->unpack();
$this->unpacker->reset();
self::assertSame(0, $this->unpacker->getRemainingCount());
}

public function testResetWithBuffer() : void
Expand Down Expand Up @@ -218,6 +219,37 @@ public function testSkipThrowsExceptionOnInvalidOffset() : void
$this->unpacker->skip(20);
}

public function testRemaining() : void
{
self::assertSame(0, $this->unpacker->getRemainingCount());
self::assertFalse($this->unpacker->hasRemaining());

$this->unpacker->reset("\x01\x02");

self::assertSame(1, $this->unpacker->unpack());
self::assertSame(1, $this->unpacker->getRemainingCount());
self::assertTrue($this->unpacker->hasRemaining());

self::assertSame(2, $this->unpacker->unpack());
self::assertSame(0, $this->unpacker->getRemainingCount());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testRelease() : void
{
self::assertSame(0, $this->unpacker->release());
$this->unpacker->reset("\x01\x02");
self::assertSame(0, $this->unpacker->release());

self::assertSame(1, $this->unpacker->unpack());
self::assertSame(1, $this->unpacker->release());

self::assertSame(2, $this->unpacker->unpack());
self::assertSame(1, $this->unpacker->release());

self::assertSame(0, $this->unpacker->release());
}

public function testClone() : void
{
$this->unpacker->reset("\xc3");
Expand Down Expand Up @@ -259,12 +291,14 @@ public function testTryUnpack() : void

$this->unpacker->append($packed[2].$packed[3]);
self::assertSame([$foo], $this->unpacker->tryUnpack());
self::assertTrue($this->unpacker->hasRemaining());

$this->unpacker->append($packed[4].$packed[5]);
self::assertSame([], $this->unpacker->tryUnpack());

$this->unpacker->append($packed[6]);
self::assertSame([$bar], $this->unpacker->tryUnpack());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testTryUnpackReturnsAllUnpackedData() : void
Expand Down Expand Up @@ -363,6 +397,7 @@ public function testUnpackCustomType() : void
public function testUnpackNil($raw, string $packed) : void
{
self::assertNull($this->unpacker->reset($packed)->unpackNil());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testUnpackNilThrowsExceptionOnInsufficientData() : void
Expand All @@ -389,6 +424,7 @@ public function testUnpackNilThrowsExceptionOnUnexpectedCode() : void
public function testUnpackBool(bool $raw, string $packed) : void
{
self::assertSame($raw, $this->unpacker->reset($packed)->unpackBool());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testUnpackBoolThrowsExceptionOnInsufficientData() : void
Expand All @@ -415,6 +451,7 @@ public function testUnpackBoolThrowsExceptionOnUnexpectedCode() : void
public function testUnpackInt(int $raw, string $packed) : void
{
self::assertSame($raw, $this->unpacker->reset($packed)->unpackInt());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testUnpackIntThrowsExceptionOnInsufficientData() : void
Expand All @@ -441,6 +478,7 @@ public function testUnpackIntThrowsExceptionOnUnexpectedCode() : void
public function testUnpackFloat(float $raw, string $packed) : void
{
self::assertSame($raw, $this->unpacker->reset($packed)->unpackFloat());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testUnpackFloatThrowsExceptionOnInsufficientData() : void
Expand All @@ -467,6 +505,7 @@ public function testUnpackFloatThrowsExceptionOnUnexpectedCode() : void
public function testUnpackStr(string $raw, string $packed) : void
{
self::assertSame($raw, $this->unpacker->reset($packed)->unpackStr());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testUnpackStrThrowsExceptionOnInsufficientData() : void
Expand All @@ -493,6 +532,7 @@ public function testUnpackStrThrowsExceptionOnUnexpectedCode() : void
public function testUnpackBin(string $raw, string $packed) : void
{
self::assertSame($raw, $this->unpacker->reset($packed)->unpackBin());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testUnpackBinThrowsExceptionOnInsufficientData() : void
Expand All @@ -519,6 +559,7 @@ public function testUnpackBinThrowsExceptionOnUnexpectedCode() : void
public function testUnpackArray(array $raw, string $packed) : void
{
self::assertEquals($raw, $this->unpacker->reset($packed)->unpackArray());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testUnpackArrayThrowsExceptionOnInsufficientData() : void
Expand All @@ -545,6 +586,7 @@ public function testUnpackArrayThrowsExceptionOnUnexpectedCode() : void
public function testUnpackMap(array $raw, string $packed) : void
{
self::assertEquals($raw, $this->unpacker->reset($packed)->unpackMap());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testUnpackMapThrowsExceptionOnInsufficientData() : void
Expand Down Expand Up @@ -615,6 +657,7 @@ public function provideMapWithInvalidKeyData() : iterable
public function testUnpackExt(Ext $raw, string $packed) : void
{
self::assertEquals($raw, $this->unpacker->reset($packed)->unpackExt());
self::assertFalse($this->unpacker->hasRemaining());
}

public function testUnpackExtThrowsExceptionOnInsufficientData() : void
Expand Down

0 comments on commit 342a747

Please sign in to comment.