Skip to content

Commit 8cfa34c

Browse files
committed
First look at basic read ops cost accounting
1 parent c3b4a96 commit 8cfa34c

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

src/BinaryStream.php

+48
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class BinaryStream{
3636
/** @var string */
3737
protected $buffer;
3838

39+
private int $readOps = 0;
40+
private int $readOpsLimit = 0;
41+
3942
public function __construct(string $buffer = "", int $offset = 0){
4043
$this->buffer = $buffer;
4144
$this->offset = $offset;
@@ -56,6 +59,45 @@ public function getOffset() : int{
5659
return $this->offset;
5760
}
5861

62+
/**
63+
* @internal Experimental, may be removed
64+
* Returns the total number of operations done on this BinaryStream so far
65+
* When this value exceeds the read cost limit (if set to a value > 0), a BinaryDataException will be thrown
66+
*/
67+
public function getReadOps() : int{
68+
return $this->readOps;
69+
}
70+
71+
/**
72+
* @internal Experimental, may be removed
73+
*/
74+
public function setReadOps(int $readOps) : void{
75+
$this->readOps = $readOps;
76+
}
77+
78+
private function addReadOps(int $amount) : void{
79+
if($this->readOpsLimit > 0){
80+
$this->readOps += $amount;
81+
if($this->readOps > $this->readOpsLimit){
82+
throw new BinaryDataException("Operations limit of $this->readOpsLimit exceeded, cannot process any more data");
83+
}
84+
}
85+
}
86+
87+
/**
88+
* @internal Experimental, may be removed
89+
*/
90+
public function getReadOpsLimit() : int{
91+
return $this->readOpsLimit;
92+
}
93+
94+
/**
95+
* @internal Experimental, may be removed
96+
*/
97+
public function setReadOpsLimit(int $readOpsLimit) : void{
98+
$this->readOpsLimit = $readOpsLimit;
99+
}
100+
59101
public function getBuffer() : string{
60102
return $this->buffer;
61103
}
@@ -71,6 +113,7 @@ public function get(int $len) : string{
71113
if($len < 0){
72114
throw new \InvalidArgumentException("Length must be positive");
73115
}
116+
$this->addReadOps(1);
74117

75118
$remaining = strlen($this->buffer) - $this->offset;
76119
if($remaining < $len){
@@ -89,6 +132,7 @@ public function getRemaining() : string{
89132
if($this->offset >= $buflen){
90133
throw new BinaryDataException("No bytes left to read");
91134
}
135+
$this->addReadOps(1);
92136
$str = substr($this->buffer, $this->offset);
93137
$this->offset = $buflen;
94138
return $str;
@@ -305,6 +349,7 @@ public function putLLong(int $v) : void{
305349
* @throws BinaryDataException
306350
*/
307351
public function getUnsignedVarInt() : int{
352+
$this->addReadOps(5); //technically this could be 1-5, but varints are costly in any case
308353
return Binary::readUnsignedVarInt($this->buffer, $this->offset);
309354
}
310355

@@ -322,6 +367,7 @@ public function putUnsignedVarInt(int $v) : void{
322367
* @throws BinaryDataException
323368
*/
324369
public function getVarInt() : int{
370+
$this->addReadOps(5);
325371
return Binary::readVarInt($this->buffer, $this->offset);
326372
}
327373

@@ -339,13 +385,15 @@ public function putVarInt(int $v) : void{
339385
* @throws BinaryDataException
340386
*/
341387
public function getUnsignedVarLong() : int{
388+
$this->addReadOps(10);
342389
return Binary::readUnsignedVarLong($this->buffer, $this->offset);
343390
}
344391

345392
/**
346393
* Writes a 64-bit variable-length integer to the end of the buffer.
347394
*/
348395
public function putUnsignedVarLong(int $v) : void{
396+
$this->addReadOps(10);
349397
$this->buffer .= Binary::writeUnsignedVarLong($v);
350398
}
351399

0 commit comments

Comments
 (0)