Skip to content

Commit

Permalink
automatically convert strings in Java Edition nbt to utf-8
Browse files Browse the repository at this point in the history
  • Loading branch information
KurtThiemann committed Dec 1, 2022
1 parent 4639486 commit 44f524d
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 44 deletions.
15 changes: 15 additions & 0 deletions src/Deserializer/BedrockEditionNbtDeserializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Aternos\Nbt\MachineByteOrder;
use Aternos\Nbt\NbtFormat;
use Aternos\Nbt\String\StringDataFormatException;
use pocketmine\utils\Binary;

class BedrockEditionNbtDeserializer extends NbtDeserializer
Expand Down Expand Up @@ -88,4 +89,18 @@ public function readDouble(): DeserializerFloatReadResult
$raw = $this->getReader()->read(8);
return new DeserializerFloatReadResult(Binary::readLDouble($raw), $raw);
}

/**
* @inheritDoc
* @throws StringDataFormatException
*/
public function readString(): DeserializerStringReadResult
{
$length = $this->readStringLengthPrefix();
$val = $this->getReader()->read($length->getValue());
if(strlen($val) !== $length->getValue()){
throw new StringDataFormatException("Failed to read string: expected length " . $length->getValue() . ", got " . strlen($val));
}
return new DeserializerStringReadResult($val, $length->getRawData() . $val);
}
}
35 changes: 35 additions & 0 deletions src/Deserializer/DeserializerStringReadResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Aternos\Nbt\Deserializer;

class DeserializerStringReadResult extends DeserializerReadResult
{
public function __construct(protected string $value, string $rawData)
{
parent::__construct($rawData);
}

/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}

/**
* @return int
*/
public function getRawLength(): int
{
return strlen($this->getRawData());
}

/**
* @return int
*/
public function getLength(): int
{
return strlen($this->value);
}
}
16 changes: 16 additions & 0 deletions src/Deserializer/JavaEditionNbtDeserializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Aternos\Nbt\MachineByteOrder;
use Aternos\Nbt\NbtFormat;
use Aternos\Nbt\String\JavaEncoding;
use Aternos\Nbt\String\StringDataFormatException;
use pocketmine\utils\Binary;

class JavaEditionNbtDeserializer extends NbtDeserializer
Expand Down Expand Up @@ -88,4 +90,18 @@ public function readDouble(): DeserializerFloatReadResult
$raw = $this->getReader()->read(8);
return new DeserializerFloatReadResult(Binary::readDouble($raw), $raw);
}

/**
* @inheritDoc
* @throws StringDataFormatException
*/
public function readString(): DeserializerStringReadResult
{
$length = $this->readStringLengthPrefix();
$val = $this->getReader()->read($length->getValue());
if(strlen($val) !== $length->getValue()){
throw new StringDataFormatException("Failed to read string: expected length " . $length->getValue() . ", got " . strlen($val));
}
return new DeserializerStringReadResult(JavaEncoding::getInstance()->decode($val), $length->getRawData() . $val);
}
}
5 changes: 5 additions & 0 deletions src/Deserializer/NbtDeserializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ abstract public function readFloat(): DeserializerFloatReadResult;
*/
abstract public function readDouble(): DeserializerFloatReadResult;

/**
* @return DeserializerStringReadResult
*/
abstract public function readString(): DeserializerStringReadResult;

/**
* @return int
*/
Expand Down
12 changes: 11 additions & 1 deletion src/Serializer/BedrockEditionNbtSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,17 @@ public function writeFloat(float $value): static
*/
public function writeDouble(float $value): static
{
$this->writer->write(Binary::writeLDouble($value));
$this->getWriter()->write(Binary::writeLDouble($value));
return $this;
}

/**
* @inheritDoc
*/
public function writeString(string $value): static
{
$this->writeStringLengthPrefix(strlen($value));
$this->getWriter()->write($value);
return $this;
}
}
14 changes: 13 additions & 1 deletion src/Serializer/JavaEditionNbtSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Aternos\Nbt\MachineByteOrder;
use Aternos\Nbt\NbtFormat;
use Aternos\Nbt\String\JavaEncoding;
use pocketmine\utils\Binary;

class JavaEditionNbtSerializer extends NbtSerializer
Expand Down Expand Up @@ -85,7 +86,18 @@ public function writeFloat(float $value): static
*/
public function writeDouble(float $value): static
{
$this->writer->write(Binary::writeDouble($value));
$this->getWriter()->write(Binary::writeDouble($value));
return $this;
}

/**
* @inheritDoc
*/
public function writeString(string $value): static
{
$encoded = JavaEncoding::getInstance()->encode($value);
$this->writeStringLengthPrefix(strlen($encoded));
$this->getWriter()->write($encoded);
return $this;
}
}
6 changes: 6 additions & 0 deletions src/Serializer/NbtSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ abstract public function writeFloat(float $value): static;
*/
abstract public function writeDouble(float $value): static;

/**
* @param string $value
* @return $this
*/
abstract public function writeString(string $value): static;

/**
* @return int
*/
Expand Down
2 changes: 1 addition & 1 deletion src/String/JavaEncoding.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function encode(string $string, string $sourceEncoding = "UTF-8"): string
}

$result .= chr(0xED);
$result .= chr(0xA0 | (($c >> 0x10) & 0x0F));
$result .= chr(0xA0 | ((($c >> 0x10) & 0x0F) - 1));
$result .= chr(0x80 | (($c >> 0x0A) & 0x3f));
$result .= chr(0xED);
$result .= chr(0xb0 | (($c >> 0x06) & 0x0f));
Expand Down
29 changes: 2 additions & 27 deletions src/Tag/StringTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

use Aternos\Nbt\IO\Reader\Reader;
use Aternos\Nbt\IO\Writer\Writer;
use Aternos\Nbt\String\JavaEncoding;
use Aternos\Nbt\String\StringDataFormatException;
use Exception;

class StringTag extends Tag
Expand All @@ -22,16 +20,6 @@ public function getValue(): string
return $this->value;
}

/**
* @param string $encoding
* @return string
* @throws StringDataFormatException
*/
public function getDecodedValue(string $encoding = "UTF-8"): string
{
return JavaEncoding::getInstance()->decode($this->value, $encoding);
}

/**
* @param string $value
* @return StringTag
Expand All @@ -42,17 +30,6 @@ public function setValue(string $value): StringTag
return $this;
}

/**
* @param string $value
* @param string $encoding
* @return StringTag
*/
public function setDecodedValue(string $value, string $encoding = "UTF-8"): StringTag
{
$this->value = JavaEncoding::getInstance()->encode($value, $encoding);
return $this;
}

/**
* @return int
*/
Expand All @@ -71,8 +48,7 @@ public function writeContent(Writer $writer): static
if ($length > 0xffff) {
throw new Exception("String exceeds maximum length of " . 0xffff . " characters");
}
$writer->getSerializer()->writeStringLengthPrefix($length);
$writer->write($this->value);
$writer->getSerializer()->writeString($this->value);
return $this;
}

Expand All @@ -81,8 +57,7 @@ public function writeContent(Writer $writer): static
*/
protected function readContent(Reader $reader): static
{
$length = $reader->getDeserializer()->readStringLengthPrefix()->getValue();
$this->value = $reader->read($length);
$this->value = $reader->getDeserializer()->readString()->getValue();
return $this;
}

Expand Down
19 changes: 5 additions & 14 deletions src/Tag/Tag.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,8 @@ public function getType(): int
public function read(Reader $reader, bool $named = true): static
{
if ($named && static::canBeNamed()) {
$nameLength = $reader->getDeserializer()->readStringLengthPrefix()->getValue();
$name = $reader->read($nameLength);
if (strlen($name) !== $nameLength) {
throw new Exception("Failed to read name of " . static::class);
}
$this->setName($name);
$name = $reader->getDeserializer()->readString();
$this->setName($name->getValue());
}
return $this->readContent($reader);
}
Expand All @@ -180,12 +176,8 @@ public static function readRaw(Reader $reader, TagOptions $options, bool $named
{
$result = "";
if ($named && static::canBeNamed()) {
$nameLength = $reader->getDeserializer()->readStringLengthPrefix();
$name = $reader->read($nameLength->getValue());
if (strlen($name) !== $nameLength->getValue()) {
throw new Exception("Failed to read name of " . static::class);
}
$result .= $nameLength->getRawData() . $name;
$name = $reader->getDeserializer()->readString();
$result .= $name->getRawData();
}
$result .= static::readContentRaw($reader, $options);
return $result;
Expand All @@ -210,8 +202,7 @@ public function writeData(Writer $writer, bool $named = true): static
if (is_null($name)) {
throw new Exception("Cannot write named tag, because tag does not have a name value");
}
$serializer->writeStringLengthPrefix(strlen($this->getName()));
$writer->write($this->getName());
$serializer->writeString($this->getName());
}
$this->writeContent($writer);
$this->isBeingSerialized = false;
Expand Down

0 comments on commit 44f524d

Please sign in to comment.