Binary strict types (#969)

* Some Binary cleanup, type-hints and strict types
yes, I know this is very crashy... that's good, because it highlights unexpected behaviour

* added some default values
This commit is contained in:
Dylan K. Taylor 2017-06-03 09:39:45 +01:00 committed by GitHub
parent 8bb0e8d398
commit 22ba017965
8 changed files with 234 additions and 114 deletions

View File

@ -38,8 +38,8 @@ class AddEntityPacket extends DataPacket{
public $speedX;
public $speedY;
public $speedZ;
public $yaw;
public $pitch;
public $yaw = 0.0;
public $pitch = 0.0;
/** @var Attribute[] */
public $attributes = [];
public $metadata = [];

View File

@ -29,7 +29,7 @@ class AvailableCommandsPacket extends DataPacket{
const NETWORK_ID = ProtocolInfo::AVAILABLE_COMMANDS_PACKET;
public $commands; //JSON-encoded command data
public $unknown;
public $unknown = "";
public function decode(){
$this->commands = $this->getString();

View File

@ -31,10 +31,10 @@ class ContainerSetSlotPacket extends DataPacket{
public $windowid;
public $slot;
public $hotbarSlot;
public $hotbarSlot = 0;
/** @var Item */
public $item;
public $selectSlot;
public $selectSlot = 0;
public function decode(){
$this->windowid = $this->getByte();

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>

View File

@ -50,19 +50,19 @@ class EntityEventPacket extends DataPacket{
public $eid;
public $event;
public $unknown;
public $data = 0;
public function decode(){
$this->eid = $this->getEntityRuntimeId();
$this->event = $this->getByte();
$this->unknown = $this->getVarInt();
$this->data = $this->getVarInt();
}
public function encode(){
$this->reset();
$this->putEntityRuntimeId($this->eid);
$this->putByte($this->event);
$this->putVarInt($this->unknown);
$this->putVarInt($this->data);
}
public function handle(NetworkSession $session) : bool{

View File

@ -43,7 +43,7 @@ class MovePlayerPacket extends DataPacket{
public $pitch;
public $mode = self::MODE_NORMAL;
public $onGround;
public $ridingEid;
public $ridingEid = 0;
public $int1 = 0;
public $int2 = 0;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
/**
* Methods for working with binary strings
*/
@ -33,57 +35,10 @@ class Binary{
assert(($len = strlen($str)) === $expect, "Expected $expect bytes, got $len");
}
/**
* Reads a 3-byte big-endian number
*
* @param $str
*
* @return mixed
*/
public static function readTriad($str){
self::checkLength($str, 3);
return unpack("N", "\x00" . $str)[1];
}
/**
* Writes a 3-byte big-endian number
*
* @param $value
*
* @return string
*/
public static function writeTriad($value){
return substr(pack("N", $value), 1);
}
/**
* Reads a 3-byte little-endian number
*
* @param $str
*
* @return mixed
*/
public static function readLTriad($str){
self::checkLength($str, 3);
return unpack("V", $str . "\x00")[1];
}
/**
* Writes a 3-byte little-endian number
*
* @param $value
*
* @return string
*/
public static function writeLTriad($value){
return substr(pack("V", $value), 0, -1);
}
/**
* Reads a byte boolean
*
* @param string $b
*
* @return bool
*/
public static function readBool(string $b) : bool{
@ -94,7 +49,6 @@ class Binary{
* Writes a byte boolean
*
* @param bool $b
*
* @return string
*/
public static function writeBool(bool $b) : string{
@ -105,18 +59,17 @@ class Binary{
* Reads an unsigned byte (0 - 255)
*
* @param string $c
*
* @return int
*/
public static function readByte(string $c){
public static function readByte(string $c) : int{
self::checkLength($c, 1);
return ord($c{0});
}
/**
* Reads a signed byte (-128 - 127)
* @param string $c
*
* @param string $c
* @return int
*/
public static function readSignedByte(string $c) : int{
@ -127,7 +80,6 @@ class Binary{
* Writes an unsigned/signed byte
*
* @param int $c
*
* @return string
*/
public static function writeByte(int $c) : string{
@ -137,11 +89,10 @@ class Binary{
/**
* Reads a 16-bit unsigned big-endian number
*
* @param $str
*
* @param string $str
* @return int
*/
public static function readShort($str){
public static function readShort(string $str) : int{
self::checkLength($str, 2);
return unpack("n", $str)[1];
}
@ -153,7 +104,7 @@ class Binary{
*
* @return int
*/
public static function readSignedShort($str){
public static function readSignedShort(string $str) : int{
self::checkLength($str, 2);
if(PHP_INT_SIZE === 8){
return unpack("n", $str)[1] << 48 >> 48;
@ -165,22 +116,22 @@ class Binary{
/**
* Writes a 16-bit signed/unsigned big-endian number
*
* @param $value
* @param int $value
*
* @return string
*/
public static function writeShort($value){
public static function writeShort(int $value) : string{
return pack("n", $value);
}
/**
* Reads a 16-bit unsigned little-endian number
*
* @param $str
* @param string $str
*
* @return int
*/
public static function readLShort($str){
public static function readLShort(string $str) : int{
self::checkLength($str, 2);
return unpack("v", $str)[1];
}
@ -192,7 +143,7 @@ class Binary{
*
* @return int
*/
public static function readSignedLShort($str){
public static function readSignedLShort(string $str) : int{
self::checkLength($str, 2);
if(PHP_INT_SIZE === 8){
return unpack("v", $str)[1] << 48 >> 48;
@ -208,11 +159,59 @@ class Binary{
*
* @return string
*/
public static function writeLShort($value){
public static function writeLShort(int $value) : string{
return pack("v", $value);
}
public static function readInt($str){
/**
* Reads a 3-byte big-endian number
*
* @param string $str
* @return int
*/
public static function readTriad(string $str) : int{
self::checkLength($str, 3);
return unpack("N", "\x00" . $str)[1];
}
/**
* Writes a 3-byte big-endian number
*
* @param int $value
* @return string
*/
public static function writeTriad(int $value) : string{
return substr(pack("N", $value), 1);
}
/**
* Reads a 3-byte little-endian number
*
* @param string $str
* @return int
*/
public static function readLTriad(string $str) : int{
self::checkLength($str, 3);
return unpack("V", $str . "\x00")[1];
}
/**
* Writes a 3-byte little-endian number
*
* @param int $value
* @return string
*/
public static function writeLTriad(int $value) : string{
return substr(pack("V", $value), 0, -1);
}
/**
* Reads a 4-byte signed integer
*
* @param string $str
* @return int
*/
public static function readInt(string $str) : int{
self::checkLength($str, 4);
if(PHP_INT_SIZE === 8){
return unpack("N", $str)[1] << 32 >> 32;
@ -221,11 +220,23 @@ class Binary{
}
}
public static function writeInt($value){
/**
* Writes a 4-byte integer
*
* @param int $value
* @return string
*/
public static function writeInt(int $value) : string{
return pack("N", $value);
}
public static function readLInt($str){
/**
* Reads a 4-byte signed little-endian integer
*
* @param string $str
* @return int
*/
public static function readLInt(string $str) : int{
self::checkLength($str, 4);
if(PHP_INT_SIZE === 8){
return unpack("V", $str)[1] << 32 >> 32;
@ -234,59 +245,141 @@ class Binary{
}
}
public static function writeLInt($value){
/**
* Writes a 4-byte signed little-endian integer
*
* @param int $value
* @return string
*/
public static function writeLInt(int $value) : string{
return pack("V", $value);
}
public static function readFloat($str){
/**
* Reads a 4-byte floating-point number
*
* @param string $str
* @return float
*/
public static function readFloat(string $str) : float{
self::checkLength($str, 4);
return (ENDIANNESS === self::BIG_ENDIAN ? unpack("f", $str)[1] : unpack("f", strrev($str))[1]);
}
/**
* Reads a 4-byte floating-point number, rounded to the specified number of decimal places.
*
* @param string $str
* @param int $accuracy
*
* @return float
*/
public static function readRoundedFloat(string $str, int $accuracy){
return round(self::readFloat($str), $accuracy);
}
public static function writeFloat($value){
/**
* Writes a 4-byte floating-point number.
*
* @param float $value
* @return string
*/
public static function writeFloat(float $value) : string{
return ENDIANNESS === self::BIG_ENDIAN ? pack("f", $value) : strrev(pack("f", $value));
}
public static function readLFloat($str){
/**
* Reads a 4-byte little-endian floating-point number.
*
* @param string $str
* @return float
*/
public static function readLFloat(string $str) : float{
self::checkLength($str, 4);
return (ENDIANNESS === self::BIG_ENDIAN ? unpack("f", strrev($str))[1] : unpack("f", $str)[1]);
}
/**
* Reads a 4-byte little-endian floating-point number rounded to the specified number of decimal places.
*
* @param string $str
* @param int $accuracy
*
* @return float
*/
public static function readRoundedLFloat(string $str, int $accuracy){
return round(self::readLFloat($str), $accuracy);
}
public static function writeLFloat($value){
/**
* Writes a 4-byte little-endian floating-point number.
*
* @param float $value
* @return string
*/
public static function writeLFloat(float $value) : string{
return ENDIANNESS === self::BIG_ENDIAN ? strrev(pack("f", $value)) : pack("f", $value);
}
public static function printFloat($value){
/**
* Returns a printable floating-point number.
*
* @param float $value
* @return string
*/
public static function printFloat(float $value){
return preg_replace("/(\\.\\d+?)0+$/", "$1", sprintf("%F", $value));
}
public static function readDouble($str){
/**
* Reads an 8-byte floating-point number.
*
* @param string $str
* @return float
*/
public static function readDouble(string $str) : float{
self::checkLength($str, 8);
return ENDIANNESS === self::BIG_ENDIAN ? unpack("d", $str)[1] : unpack("d", strrev($str))[1];
}
public static function writeDouble($value){
/**
* Writes an 8-byte floating-point number.
*
* @param float $value
* @return string
*/
public static function writeDouble(float $value) : string{
return ENDIANNESS === self::BIG_ENDIAN ? pack("d", $value) : strrev(pack("d", $value));
}
public static function readLDouble($str){
/**
* Reads an 8-byte little-endian floating-point number.
*
* @param string $str
* @return float
*/
public static function readLDouble(string $str) : float{
self::checkLength($str, 8);
return ENDIANNESS === self::BIG_ENDIAN ? unpack("d", strrev($str))[1] : unpack("d", $str)[1];
}
public static function writeLDouble($value){
/**
* Writes an 8-byte floating-point little-endian number.
* @param float $value
* @return string
*/
public static function writeLDouble(float $value) : string{
return ENDIANNESS === self::BIG_ENDIAN ? strrev(pack("d", $value)) : pack("d", $value);
}
public static function readLong($x){
/**
* Reads an 8-byte integer.
* Note that this method will return a string on 32-bit PHP.
*
* @param string $x
* @return int|string
*/
public static function readLong(string $x){
self::checkLength($x, 8);
if(PHP_INT_SIZE === 8){
$int = unpack("N*", $x);
@ -306,7 +399,13 @@ class Binary{
}
}
public static function writeLong($value){
/**
* Writes an 8-byte integer.
*
* @param int|string $value
* @return string
*/
public static function writeLong($value) : string{
if(PHP_INT_SIZE === 8){
return pack("NN", $value >> 32, $value & 0xFFFFFFFF);
}else{
@ -325,25 +424,36 @@ class Binary{
}
}
public static function readLLong($str){
/**
* Reads an 8-byte little-endian integer.
*
* @param string $str
* @return int|string
*/
public static function readLLong(string $str){
return self::readLong(strrev($str));
}
public static function writeLLong($value){
/**
* Writes an 8-byte little-endian integer.
*
* @param int|string $value
* @return string
*/
public static function writeLLong($value) : string{
return strrev(self::writeLong($value));
}
/**
* Reads a 32-bit zigzag-encoded variable-length integer from the supplied stream.
* Reads a 32-bit zigzag-encoded variable-length integer.
*
* @param string $buffer
* @param int &$offset
*
* @return int
*/
public static function readVarInt(string $buffer, int &$offset){
public static function readVarInt(string $buffer, int &$offset) : int{
$shift = PHP_INT_SIZE === 8 ? 63 : 31;
$raw = self::readUnsignedVarInt($buffer, $offset);
$temp = ((($raw << $shift) >> $shift) ^ $raw) >> 1;
@ -351,14 +461,16 @@ class Binary{
}
/**
* Reads a 32-bit variable-length unsigned integer from the supplied stream.
* Reads a 32-bit variable-length unsigned integer.
*
* @param string $buffer
* @param int &$offset
*
* @return int
*
* @throws \InvalidArgumentException if the var-int did not end after 5 bytes
*/
public static function readUnsignedVarInt(string $buffer, int &$offset){
public static function readUnsignedVarInt(string $buffer, int &$offset) : int{
$value = 0;
for($i = 0; $i <= 35; $i += 7){
$b = ord($buffer{$offset++});
@ -378,10 +490,9 @@ class Binary{
* Writes a 32-bit integer as a zigzag-encoded variable-length integer.
*
* @param int $v
*
* @return string
*/
public static function writeVarInt($v){
public static function writeVarInt(int $v) : string{
if(PHP_INT_SIZE === 8){
$v = ($v << 32 >> 32);
}
@ -390,16 +501,16 @@ class Binary{
/**
* Writes a 32-bit unsigned integer as a variable-length integer.
* @param int $value
*
* @param int $value
* @return string up to 5 bytes
*/
public static function writeUnsignedVarInt($value){
public static function writeUnsignedVarInt(int $value) : string{
$buf = "";
$value &= 0xffffffff;
for($i = 0; $i < 5; ++$i){
if(($value >> 7) !== 0){
$buf .= chr($value | 0x80); //Let chr() take the last byte of this, it's faster than adding another & 0x7f.
$buf .= chr($value | 0x80);
}else{
$buf .= chr($value & 0x7f);
return $buf;
@ -412,9 +523,9 @@ class Binary{
}
/**
* Reads a 64-bit zigzag-encoded variable-length integer from the supplied stream.
*
* @param string $buffer
* @param int &$offset
*
@ -430,12 +541,13 @@ class Binary{
/**
* Legacy BC Math zigzag VarLong reader. Will work on 32-bit or 64-bit, but will be slower than the regular 64-bit method.
*
* @param string $buffer
* @param int &$offset
*
* @return string
*/
public static function readVarLong_32(string $buffer, int &$offset){
public static function readVarLong_32(string $buffer, int &$offset) : string{
/** @var string $raw */
$raw = self::readUnsignedVarLong_32($buffer, $offset);
$result = bcdiv($raw, "2");
@ -448,12 +560,13 @@ class Binary{
/**
* 64-bit zizgag VarLong reader.
*
* @param string $buffer
* @param int &$offset
*
* @return int
*/
public static function readVarLong_64(string $buffer, int &$offset){
public static function readVarLong_64(string $buffer, int &$offset) : int{
$raw = self::readUnsignedVarLong_64($buffer, $offset);
$temp = ((($raw << 63) >> 63) ^ $raw) >> 1;
return $temp ^ ($raw & (1 << 63));
@ -461,6 +574,7 @@ class Binary{
/**
* Reads an unsigned VarLong from the supplied stream.
*
* @param string $buffer
* @param int &$offset
*
@ -476,12 +590,13 @@ class Binary{
/**
* Legacy BC Math unsigned VarLong reader.
*
* @param string $buffer
* @param int &$offset
*
* @return string
*/
public static function readUnsignedVarLong_32(string $buffer, int &$offset){
public static function readUnsignedVarLong_32(string $buffer, int &$offset) : string{
$value = "0";
for($i = 0; $i <= 63; $i += 7){
$b = ord($buffer{$offset++});
@ -499,12 +614,13 @@ class Binary{
/**
* 64-bit unsigned VarLong reader.
*
* @param string $buffer
* @param int &$offset
*
* @return int
*/
public static function readUnsignedVarLong_64(string $buffer, int &$offset){
public static function readUnsignedVarLong_64(string $buffer, int &$offset) : int{
$value = 0;
for($i = 0; $i <= 63; $i += 7){
$b = ord($buffer{$offset++});
@ -524,11 +640,11 @@ class Binary{
/**
* Writes a 64-bit integer as a variable-length long.
* @param int|string $v
*
* @param int|string $v
* @return string up to 10 bytes
*/
public static function writeVarLong($v){
public static function writeVarLong($v) : string{
if(PHP_INT_SIZE === 8){
return self::writeVarLong_64($v);
}else{
@ -538,11 +654,11 @@ class Binary{
/**
* Legacy BC Math zigzag VarLong encoder.
* @param string $v
*
* @param string $v
* @return string
*/
public static function writeVarLong_32($v){
public static function writeVarLong_32(string $v) : string{
$v = bcmod(bcmul($v, "2"), "18446744073709551616");
if(bccomp($v, "0") == -1){
$v = bcsub(bcmul($v, "-1"), "1");
@ -553,21 +669,21 @@ class Binary{
/**
* 64-bit VarLong encoder.
* @param int $v
*
* @param int $v
* @return string
*/
public static function writeVarLong_64($v){
public static function writeVarLong_64(int $v) : string{
return self::writeUnsignedVarLong_64(($v << 1) ^ ($v >> 63));
}
/**
* Writes a 64-bit integer as a variable-length long
* @param int|string $v
*
* @param int|string $v
* @return string up to 10 bytes
*/
public static function writeUnsignedVarLong($v){
public static function writeUnsignedVarLong($v) : string{
if(PHP_INT_SIZE === 8){
return self::writeUnsignedVarLong_64($v);
}else{
@ -577,11 +693,11 @@ class Binary{
/**
* Legacy BC Math unsigned VarLong encoder.
* @param string $value
*
* @param string $value
* @return string
*/
public static function writeUnsignedVarLong_32($value){
public static function writeUnsignedVarLong_32(string $value) : string{
$buf = "";
if(bccomp($value, "0") == -1){
@ -608,7 +724,7 @@ class Binary{
*
* @return string
*/
public static function writeUnsignedVarLong_64($value){
public static function writeUnsignedVarLong_64(int $value) : string{
$buf = "";
for($i = 0; $i < 10; ++$i){
if(($value >> 7) !== 0){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\utils;
#include <rules/DataPacket.h>