Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First look at ext-encoding integration #122

Open
wants to merge 5 commits into
base: stable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"require": {
"php": "^7.4 || ^8.0",
"php-64bit": "*",
"pocketmine/binaryutils": "^0.2.0"
"ext-encoding": "~0.4.0"
},
"require-dev": {
"phpstan/phpstan": "2.1.0",
Expand Down
61 changes: 31 additions & 30 deletions src/BaseNbtSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,28 @@

namespace pocketmine\nbt;

use pmmp\encoding\Byte;
use pmmp\encoding\ByteBuffer;
use pmmp\encoding\DataDecodeException;
use pocketmine\nbt\tag\Tag;
use pocketmine\utils\Binary;
use pocketmine\utils\BinaryDataException;
use pocketmine\utils\BinaryStream;
use function strlen;

/**
* Base Named Binary Tag encoder/decoder
*/
abstract class BaseNbtSerializer implements NbtStreamReader, NbtStreamWriter{
/** @var BinaryStream */
protected $buffer;
protected ByteBuffer $buffer;

public function __construct(){
$this->buffer = new BinaryStream();
$this->buffer = new ByteBuffer();
}

/**
* @throws BinaryDataException
* @throws DataDecodeException
* @throws NbtDataException
*/
private function readRoot(int $maxDepth) : TreeRoot{
$type = $this->readByte();
$type = Byte::readUnsigned($this->buffer);
if($type === NBT::TAG_End){
throw new NbtDataException("Found TAG_End at the start of buffer");
}
Expand All @@ -62,14 +61,15 @@ private function readRoot(int $maxDepth) : TreeRoot{
* @throws NbtDataException
*/
public function read(string $buffer, int &$offset = 0, int $maxDepth = 0) : TreeRoot{
$this->buffer = new BinaryStream($buffer, $offset);
$this->buffer = new ByteBuffer($buffer);
$this->buffer->setReadOffset($offset);

try{
$data = $this->readRoot($maxDepth);
}catch(BinaryDataException $e){
}catch(DataDecodeException $e){
throw new NbtDataException($e->getMessage(), 0, $e);
}
$offset = $this->buffer->getOffset();
$offset = $this->buffer->getReadOffset();

return $data;
}
Expand All @@ -85,10 +85,11 @@ public function read(string $buffer, int &$offset = 0, int $maxDepth = 0) : Tree
* @throws NbtDataException
*/
public function readHeadless(string $buffer, int $rootType, int &$offset = 0, int $maxDepth = 0) : Tag{
$this->buffer = new BinaryStream($buffer, $offset);
$this->buffer = new ByteBuffer($buffer);
$this->buffer->setReadOffset($offset);

$data = NBT::createTag($rootType, $this, new ReaderTracker($maxDepth));
$offset = $this->buffer->getOffset();
$offset = $this->buffer->getReadOffset();

return $data;
}
Expand All @@ -103,14 +104,14 @@ public function readHeadless(string $buffer, int $rootType, int &$offset = 0, in
* @throws NbtDataException
*/
public function readMultiple(string $buffer, int $maxDepth = 0) : array{
$this->buffer = new BinaryStream($buffer);
$this->buffer = new ByteBuffer($buffer);

$retval = [];

while(!$this->buffer->feof()){
while($this->buffer->getReadOffset() < $this->buffer->getUsedLength()){
try{
$retval[] = $this->readRoot($maxDepth);
}catch(BinaryDataException $e){
}catch(DataDecodeException $e){
throw new NbtDataException($e->getMessage(), 0, $e);
}
}
Expand All @@ -119,17 +120,17 @@ public function readMultiple(string $buffer, int $maxDepth = 0) : array{
}

private function writeRoot(TreeRoot $root) : void{
$this->writeByte($root->getTag()->getType());
Byte::writeUnsigned($this->buffer, $root->getTag()->getType());
$this->writeString($root->getName());
$root->getTag()->write($this);
}

public function write(TreeRoot $data) : string{
$this->buffer = new BinaryStream();
$this->buffer = new ByteBuffer();

$this->writeRoot($data);

return $this->buffer->getBuffer();
return $this->buffer->toString();
}

/**
Expand All @@ -139,45 +140,45 @@ public function write(TreeRoot $data) : string{
* @see BaseNbtSerializer::readHeadless()
*/
public function writeHeadless(Tag $data) : string{
$this->buffer = new BinaryStream();
$this->buffer = new ByteBuffer();
$data->write($this);
return $this->buffer->getBuffer();
return $this->buffer->toString();
}

/**
* @param TreeRoot[] $data
*/
public function writeMultiple(array $data) : string{
$this->buffer = new BinaryStream();
$this->buffer = new ByteBuffer();
foreach($data as $root){
$this->writeRoot($root);
}
return $this->buffer->getBuffer();
return $this->buffer->toString();
}

public function readByte() : int{
return $this->buffer->getByte();
return Byte::readUnsigned($this->buffer);
}

public function readSignedByte() : int{
return Binary::signByte($this->buffer->getByte());
return Byte::readSigned($this->buffer);
}

public function writeByte(int $v) : void{
$this->buffer->putByte($v);
Byte::writeUnsigned($this->buffer, $v);
}

public function readByteArray() : string{
$length = $this->readInt();
if($length < 0){
throw new NbtDataException("Array length cannot be less than zero ($length < 0)");
}
return $this->buffer->get($length);
return $this->buffer->readByteArray($length);
}

public function writeByteArray(string $v) : void{
$this->writeInt(strlen($v)); //TODO: overflow
$this->buffer->put($v);
$this->buffer->writeByteArray($v);
}

/**
Expand All @@ -201,14 +202,14 @@ protected static function checkWriteStringLength(int $len) : int{
}

public function readString() : string{
return $this->buffer->get(self::checkReadStringLength($this->readShort()));
return $this->buffer->readByteArray(self::checkReadStringLength($this->readShort()));
}

/**
* @throws \InvalidArgumentException if the string is too long
*/
public function writeString(string $v) : void{
$this->writeShort(self::checkWriteStringLength(strlen($v)));
$this->buffer->put($v);
$this->buffer->writeByteArray($v);
}
}
27 changes: 14 additions & 13 deletions src/BigEndianNbtSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

namespace pocketmine\nbt;

use pmmp\encoding\BE;
use function array_values;
use function assert;
use function count;
Expand All @@ -32,47 +33,47 @@
class BigEndianNbtSerializer extends BaseNbtSerializer{

public function readShort() : int{
return $this->buffer->getShort();
return BE::readUnsignedShort($this->buffer);
}

public function readSignedShort() : int{
return $this->buffer->getSignedShort();
return BE::readSignedShort($this->buffer);
}

public function writeShort(int $v) : void{
$this->buffer->putShort($v);
BE::writeUnsignedShort($this->buffer, $v);
}

public function readInt() : int{
return $this->buffer->getInt();
return BE::readSignedInt($this->buffer);
}

public function writeInt(int $v) : void{
$this->buffer->putInt($v);
BE::writeSignedInt($this->buffer, $v);
}

public function readLong() : int{
return $this->buffer->getLong();
return BE::readSignedLong($this->buffer);
}

public function writeLong(int $v) : void{
$this->buffer->putLong($v);
BE::writeSignedLong($this->buffer, $v);
}

public function readFloat() : float{
return $this->buffer->getFloat();
return BE::readFloat($this->buffer);
}

public function writeFloat(float $v) : void{
$this->buffer->putFloat($v);
BE::writeFloat($this->buffer, $v);
}

public function readDouble() : float{
return $this->buffer->getDouble();
return BE::readDouble($this->buffer);
}

public function writeDouble(float $v) : void{
$this->buffer->putDouble($v);
BE::writeDouble($this->buffer, $v);
}

public function readIntArray() : array{
Expand All @@ -81,13 +82,13 @@ public function readIntArray() : array{
throw new NbtDataException("Array length cannot be less than zero ($len < 0)");
}
/** @var array<int>|false $unpacked */
$unpacked = unpack("N*", $this->buffer->get($len * 4));
$unpacked = unpack("N*", $this->buffer->readByteArray($len * 4));
assert($unpacked !== false, "The formatting string is valid, and we gave a multiple of 4 bytes");
return array_values($unpacked);
}

public function writeIntArray(array $array) : void{
$this->writeInt(count($array));
$this->buffer->put(pack("N*", ...$array));
$this->buffer->writeByteArray(pack("N*", ...$array));
}
}
Loading
Loading