test[php]: php test

This commit is contained in:
godotg committed 2024-07-11 18:31:47 +08:00
1 parent 6a0fed1270
commit 34f74370e1
9 files changed
+1462

No files matched your search

+125
View File
@@ -0,0 +1,125 @@
<?php
use zfoophp\ByteBuffer;
use zfoophp\ProtocolManager;
include './zfoophp/ByteBuffer.php';
include './zfoophp/ProtocolManager.php';
function assertEqual($a, $b)
{
if ($a === $b) {
return;
}
throw new Exception("a is not equals b");
}
function byteTest($value)
{
$byteBuffer = new ByteBuffer();
$byteBuffer->writeByte($value);
$readValue = $byteBuffer->readByte();
assertEqual($value, $readValue);
}
function boolTest($value)
{
$byteBuffer = new ByteBuffer();
$byteBuffer->writeBool($value);
$readValue = $byteBuffer->readBool();
assertEqual($value, $readValue);
}
function shortTest($value)
{
$byteBuffer = new ByteBuffer();
$byteBuffer->writeShort($value);
$readValue = $byteBuffer->readShort();
assertEqual($value, $readValue);
}
function rawIntTest($value)
{
$byteBuffer = new ByteBuffer();
$byteBuffer->writeRawInt($value);
$readValue = $byteBuffer->readRawInt();
assertEqual($value, $readValue);
}
function intTest($value)
{
$byteBuffer = new ByteBuffer();
$byteBuffer->writeInt($value);
$readValue = $byteBuffer->readInt();
assertEqual($value, $readValue);
}
function floatTest($value)
{
$byteBuffer = new ByteBuffer();
$byteBuffer->writeFloat($value);
$readValue = $byteBuffer->readFloat();
assertEqual($value, $readValue);
}
function doubleTest($value)
{
$byteBuffer = new ByteBuffer();
$byteBuffer->writeDouble($value);
$readValue = $byteBuffer->readDouble();
assertEqual($value, $readValue);
}
function stringTest($value)
{
$byteBuffer = new ByteBuffer();
$byteBuffer->writeString($value);
$readValue = $byteBuffer->readString();
assertEqual($value, $readValue);
}
function boolArrayTest($value)
{
$byteBuffer = new ByteBuffer();
$byteBuffer->writeBoolArray($value);
$readValue = $byteBuffer->readBoolArray();
assertEqual($value, $readValue);
}
byteTest(22);
byteTest(-22);
boolTest(true);
shortTest(32767);
shortTest(-32768);
rawIntTest(2147483647);
rawIntTest(-2147483648);
intTest(2147483647);
intTest(-2147483648);
intTest(9223372036854775807);
intTest(PHP_INT_MIN);
floatTest(1.0);
floatTest(99.0);
floatTest(-99.0);
doubleTest(PHP_FLOAT_MAX);
doubleTest(PHP_FLOAT_MIN);
stringTest("hello world!");
stringTest("你好啊");
boolArrayTest([true, false, true]);
ProtocolManager::initProtocol();
//$file = 'D:\Project\zfoo\protocol\src\test\resources\compatible\normal-inner-compatible.bytes';
//$file = 'D:\Project\zfoo\protocol\src\test\resources\compatible\normal-no-compatible.bytes';
//$file = 'D:\Project\zfoo\protocol\src\test\resources\compatible\normal-out-compatible.bytes';
//$file = 'D:\Project\zfoo\protocol\src\test\resources\compatible\normal-out-inner-compatible.bytes';
$file = 'D:\Project\zfoo\protocol\src\test\resources\compatible\normal-out-inner-inner-compatible.bytes';
$data = file_get_contents($file);
//echo "file length: " . strlen($data) . "\n";
$buffer = new ByteBuffer();
$buffer->writeBytes($data);
$packet = ProtocolManager::read($buffer);
echo json_encode($packet);
@@ -0,0 +1,949 @@
<?php
namespace zfoophp;
use Exception;
class ByteBuffer
{
private string $buffer;
private int $writeOffset = 0;
private int $readOffset = 0;
private bool $bigEndian = true;
public function __construct()
{
$this->buffer = str_pad("", 128);
// 大端序还是小端序
$this->bigEndian = pack("L", 1) === "\x00\x00\x00\x01";
}
public function adjustPadding(int $predictionLength, int $beforewriteIndex): void
{
// 因为写入的是可变长的int,如果预留的位置过多,则清除多余的位置
$currentwriteIndex = $this->writeOffset;
$predictionCount = $this->writeIntCount($predictionLength);
$length = $currentwriteIndex - $beforewriteIndex - $predictionCount;
$lengthCount = $this->writeIntCount($length);
$padding = $lengthCount - $predictionCount;
if ($padding == 0) {
$this->writeOffset = $beforewriteIndex;
$this->writeInt($length);
$this->writeOffset = $currentwriteIndex;
} else {
$bytes = substr($this->buffer, $currentwriteIndex - $length, $length);
$this->writeOffset = $beforewriteIndex;
$this->writeInt($length);
$this->writeBytes($bytes);
}
}
public function compatibleRead(int $beforereadIndex, int $length): bool
{
return $length != -1 && $this->readOffset < $length + $beforereadIndex;
}
// -------------------------------------------------get/set-------------------------------------------------
public function getBuffer(): string
{
return $this->buffer;
}
public function getWriteOffset(): int
{
return $this->writeOffset;
}
/**
* @throws Exception
*/
public function setWriteOffset(int $writeIndex): void
{
if ($writeIndex > strlen($this->buffer)) {
throw new Exception("writeIndex[" . $writeIndex . "] out of bounds exception: readerIndex: " . $this->readOffset .
", writerIndex: " . $this->writeOffset . "(expected: 0 <= readerIndex <= writerIndex <= capacity:" . strlen($this->buffer));
}
$this->writeOffset = $writeIndex;
}
public function getReadOffset(): int
{
return $this->readOffset;
}
/**
* @throws Exception
*/
public function setReadOffset(int $readIndex): void
{
if ($readIndex > $this->writeOffset) {
throw new Exception("readIndex[" . $readIndex . "] out of bounds exception: readerIndex: " . $this->readOffset .
", writerIndex: " . $this->writeOffset . "(expected: 0 <= readerIndex <= writerIndex <= capacity:" . strlen($this->buffer));
}
$this->readOffset = $readIndex;
}
public function toBytes(): string
{
return substr($this->buffer, 0, $this->writeOffset);
}
public function isReadable(): bool
{
return $this->writeOffset > $this->readOffset;
}
public function getCapacity(): int
{
return strlen($this->buffer) - $this->writeOffset;
}
// -------------------------------------------------write/read-------------------------------------------------
public function writeBytes(string $bytes): void
{
// 如果容量不够则扩容一倍
$length = strlen($bytes);
while ($length > $this->getCapacity()) {
$this->buffer = str_pad($this->buffer, strlen($this->buffer) * 2);
}
for ($i = 0; $i < $length; $i++) {
$this->buffer[$this->writeOffset] = $bytes[$i];
$this->writeOffset++;
}
}
public function readBytes(int $count): string
{
$bytes = substr($this->buffer, $this->readOffset, $count);
$this->readOffset += $count;
return $bytes;
}
public function writeBytesBigEndian(string $bytes): void
{
if ($this->bigEndian) {
$this->writeBytes($bytes);
} else {
$this->writeBytes(strrev($bytes));
}
}
public function readBytesBigEndian(int $count): string
{
if ($this->bigEndian) {
return $this->readBytes($count);
} else {
return strrev($this->readBytes($count));
}
}
public function writeByte(int $value): void
{
$this->writeBytes(pack('c', $value));
}
public function readByte(): int
{
return unpack('c', $this->readBytes(1))[1];
}
public function writeUByte(int $value): void
{
$this->writeBytes(pack('C', $value));
}
public function readUByte(): int
{
return unpack('c', $this->readBytes(1))[1];
}
public function writeBool(bool $value): void
{
$this->writeBytes(pack('C', $value ? 1 : 0));
}
public function readBool(): bool
{
return unpack('C', $this->readBytes(1))[1] == 1;
}
public function writeShort(int $value): void
{
$this->writeBytesBigEndian(pack('s', $value));
}
public function readShort(): int
{
return unpack('s', $this->readBytesBigEndian(2))[1];
}
public function writeRawInt(int $value): void
{
$this->writeBytes(pack('i', $value));
}
public function readRawInt(): int
{
return unpack('i', $this->readBytes(4))[1];
}
public function writeInt(int $value): void
{
$this->writeLong($value);
}
public function readInt(): int
{
return $this->readLong();
}
public function writeIntCount(int $value): int
{
$value = ($value << 1) ^ ($value >> 31);
if ($value >> 7 == 0) {
return 1;
}
if ($value >> 14 == 0) {
return 2;
}
if ($value >> 21 == 0) {
return 3;
}
if ($value >> 28 == 0) {
return 4;
}
return 5;
}
public function writeLong(int $longValue): void
{
$value = ($longValue << 1) ^ ($longValue >> 63);
if ($value < 0) {
$this->writeByte($value & 0xFF | 0x80);
$this->writeByte($value >> 7 & 0xFF | 0x80);
$this->writeByte($value >> 14 & 0xFF | 0x80);
$this->writeByte($value >> 21 & 0xFF | 0x80);
$this->writeByte($value >> 28 & 0xFF | 0x80);
$this->writeByte($value >> 35 & 0xFF | 0x80);
$this->writeByte($value >> 42 & 0xFF | 0x80);
$this->writeByte($value >> 49 & 0xFF | 0x80);
$this->writeByte($value >> 56 & 0xFF);
return;
}
if ($value >> 7 == 0) {
$this->writeByte($value);
return;
}
if ($value >> 14 == 0) {
$this->writeByte($value | 0x80);
$this->writeByte($value >> 7);
return;
}
if ($value >> 21 == 0) {
$this->writeByte($value | 0x80);
$this->writeByte($value >> 7 | 0x80);
$this->writeByte($value >> 14);
return;
}
if ($value >> 28 == 0) {
$this->writeByte($value | 0x80);
$this->writeByte($value >> 7 | 0x80);
$this->writeByte($value >> 14 | 0x80);
$this->writeByte($value >> 21);
return;
}
if ($value >> 35 == 0) {
$this->writeByte($value | 0x80);
$this->writeByte($value >> 7 | 0x80);
$this->writeByte($value >> 14 | 0x80);
$this->writeByte($value >> 21 | 0x80);
$this->writeByte($value >> 28);
return;
}
if ($value >> 42 == 0) {
$this->writeByte($value | 0x80);
$this->writeByte($value >> 7 | 0x80);
$this->writeByte($value >> 14 | 0x80);
$this->writeByte($value >> 21 | 0x80);
$this->writeByte($value >> 28 | 0x80);
$this->writeByte($value >> 35);
return;
}
if ($value >> 49 == 0) {
$this->writeByte($value | 0x80);
$this->writeByte($value >> 7 | 0x80);
$this->writeByte($value >> 14 | 0x80);
$this->writeByte($value >> 21 | 0x80);
$this->writeByte($value >> 28 | 0x80);
$this->writeByte($value >> 35 | 0x80);
$this->writeByte($value >> 42);
return;
}
if (($value >> 56) == 0) {
$this->writeByte($value | 0x80);
$this->writeByte($value >> 7 | 0x80);
$this->writeByte($value >> 14 | 0x80);
$this->writeByte($value >> 21 | 0x80);
$this->writeByte($value >> 28 | 0x80);
$this->writeByte($value >> 35 | 0x80);
$this->writeByte($value >> 42 | 0x80);
$this->writeByte($value >> 49);
return;
}
$this->writeByte($value | 0x80);
$this->writeByte($value >> 7 | 0x80);
$this->writeByte($value >> 14 | 0x80);
$this->writeByte($value >> 21 | 0x80);
$this->writeByte($value >> 28 | 0x80);
$this->writeByte($value >> 35 | 0x80);
$this->writeByte($value >> 42 | 0x80);
$this->writeByte($value >> 49 | 0x80);
$this->writeByte($value >> 56);
}
public function readLong(): int
{
$b = $this->readByte();
$value = $b;
if ($b < 0) {
$b = $this->readByte();
$value = $value & 0x00000000_0000007F | $b << 7;
if ($b < 0) {
$b = $this->readByte();
$value = $value & 0x00000000_00003FFF | $b << 14;
if ($b < 0) {
$b = $this->readByte();
$value = $value & 0x00000000_001FFFFF | $b << 21;
if ($b < 0) {
$b = $this->readByte();
$value = $value & 0x00000000_0FFFFFFF | $b << 28;
if ($b < 0) {
$b = $this->readByte();
$value = $value & 0x00000007_FFFFFFFF | $b << 35;
if ($b < 0) {
$b = $this->readByte();
$value = $value & 0x000003FF_FFFFFFFF | $b << 42;
if ($b < 0) {
$b = $this->readByte();
$value = $value & 0x0001FFFF_FFFFFFFF | $b << 49;
if ($b < 0) {
$b = $this->readByte();
$value = $value & 0x00FFFFFF_FFFFFFFF | $b << 56;
}
}
}
}
}
}
}
}
return (($value >> 1 & 0x7FFFFFFF_FFFFFFFF) ^ -($value & 1));
}
public function writeFloat(float $value): void
{
$this->writeBytes(pack('f', $value));
}
public function readFloat(): float
{
return unpack('f', $this->readBytes(4))[1];
}
public function writeDouble(float $value): void
{
$this->writeBytes(pack('d', $value));
}
public function readDouble(): float
{
return unpack('d', $this->readBytes(8))[1];
}
public function writeString(string $value): void
{
$this->writeInt(strlen($value));
$this->writeBytes($value);
}
public function readString(): string
{
$length = $this->readInt();
return $this->readBytes($length);
}
public function writePacket(mixed $value, int $protocolId): void
{
$protocolRegistration = ProtocolManager::getProtocol($protocolId);
$protocolRegistration->write($this, $value);
}
public function readPacket(int $protocolId): mixed
{
$protocolRegistration = ProtocolManager::getProtocol($protocolId);
return $protocolRegistration->read($this);
}
public function writeBoolArray(array $array): void
{
if (empty($array)) {
$this->writeInt(0);
} else {
$this->writeInt(count($array));
$length = count($array);
for ($index = 0; $index < $length; $index++) {
$this->writeBool($array[$index]);
}
}
}
public function readBoolArray(): array
{
$size = $this->readInt();
$array = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
array_push($array, $this->readBool());
}
}
return $array;
}
public function writeByteArray(array $array): void
{
if (empty($array)) {
$this->writeInt(0);
} else {
$this->writeInt(count($array));
$length = count($array);
for ($index = 0; $index < $length; $index++) {
$this->writeByte($array[$index]);
}
}
}
public function readByteArray(): array
{
$size = $this->readInt();
$array = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
array_push($array, $this->readByte());
}
}
return $array;
}
public function writeShortArray(array $array): void
{
if (empty($array)) {
$this->writeInt(0);
} else {
$this->writeInt(count($array));
$length = count($array);
for ($index = 0; $index < $length; $index++) {
$this->writeShort($array[$index]);
}
}
}
public function readShortArray(): array
{
$size = $this->readInt();
$array = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
array_push($array, $this->readShort());
}
}
return $array;
}
public function writeIntArray(array $array): void
{
if (empty($array)) {
$this->writeInt(0);
} else {
$this->writeInt(count($array));
$length = count($array);
for ($index = 0; $index < $length; $index++) {
$this->writeInt($array[$index]);
}
}
}
public function readIntArray(): array
{
$size = $this->readInt();
$array = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
array_push($array, $this->readInt());
}
}
return $array;
}
public function writeLongArray(array $array): void
{
if (empty($array)) {
$this->writeInt(0);
} else {
$this->writeInt(count($array));
$length = count($array);
for ($index = 0; $index < $length; $index++) {
$this->writeLong($array[$index]);
}
}
}
public function readLongArray(): array
{
$size = $this->readInt();
$array = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
array_push($array, $this->readLong());
}
}
return $array;
}
public function writeFloatArray(array $array): void
{
if (empty($array)) {
$this->writeInt(0);
} else {
$this->writeInt(count($array));
$length = count($array);
for ($index = 0; $index < $length; $index++) {
$this->writeFloat($array[$index]);
}
}
}
public function readFloatArray(): array
{
$size = $this->readInt();
$array = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
array_push($array, $this->readFloat());
}
}
return $array;
}
public function writeDoubleArray(array $array): void
{
if (empty($array)) {
$this->writeInt(0);
} else {
$this->writeInt(count($array));
$length = count($array);
for ($index = 0; $index < $length; $index++) {
$this->writeDouble($array[$index]);
}
}
}
public function readDoubleArray(): array
{
$size = $this->readInt();
$array = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
array_push($array, $this->readDouble());
}
}
return $array;
}
public function writeStringArray(array $array): void
{
if (empty($array)) {
$this->writeInt(0);
} else {
$this->writeInt(count($array));
$length = count($array);
for ($index = 0; $index < $length; $index++) {
$this->writeString($array[$index]);
}
}
}
public function readStringArray(): array
{
$size = $this->readInt();
$array = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
array_push($array, $this->readString());
}
}
return $array;
}
public function writePacketArray(array $array, int $protocolId): void
{
if (empty($array)) {
$this->writeInt(0);
} else {
$this->writeInt(count($array));
$length = count($array);
for ($index = 0; $index < $length; $index++) {
$this->writePacket($array[$index], $protocolId);
}
}
}
public function readPacketArray(int $protocolId): array
{
$size = $this->readInt();
$array = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
array_push($array, $this->readPacket($protocolId));
}
}
return $array;
}
public function writeIntIntMap(array $map): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeInt($key);
$this->writeInt($value);
}
}
}
public function readIntIntMap(): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readInt();
$value = $this->readInt();
$map[$key] = $value;
}
}
return $map;
}
public function writeIntLongMap(array $map): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeInt($key);
$this->writeLong($value);
}
}
}
public function readIntLongMap(): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readInt();
$value = $this->readLong();
$map[$key] = $value;
}
}
return $map;
}
public function writeIntStringMap(array $map): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeInt($key);
$this->writeString($value);
}
}
}
public function readIntStringMap(): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readInt();
$value = $this->readString();
$map[$key] = $value;
}
}
return $map;
}
public function writeIntPacketMap(array $map, int $protocolId): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeInt($key);
$this->writePacket($value, $protocolId);
}
}
}
public function readIntPacketMap(int $protocolId): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readInt();
$value = $this->readPacket($protocolId);
$map[$key] = $value;
}
}
return $map;
}
public function writeLongIntMap(array $map): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeLong($key);
$this->writeInt($value);
}
}
}
public function readLongIntMap(): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readLong();
$value = $this->readInt();
$map[$key] = $value;
}
}
return $map;
}
public function writeLongLongMap(array $map): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeLong($key);
$this->writeLong($value);
}
}
}
public function readLongLongMap(): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readLong();
$value = $this->readLong();
$map[$key] = $value;
}
}
return $map;
}
public function writeLongStringMap(array $map): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeLong($key);
$this->writeString($value);
}
}
}
public function readLongStringMap(): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readLong();
$value = $this->readString();
$map[$key] = $value;
}
}
return $map;
}
public function writeLongPacketMap(array $map, int $protocolId): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeLong($key);
$this->writePacket($value, $protocolId);
}
}
}
public function readLongPacketMap(int $protocolId): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readLong();
$value = $this->readPacket($protocolId);
$map[$key] = $value;
}
}
return $map;
}
public function writeStringIntMap(array $map): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeString($key);
$this->writeInt($value);
}
}
}
public function readStringIntMap(): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readString();
$value = $this->readInt();
$map[$key] = $value;
}
}
return $map;
}
public function writeStringLongMap(array $map): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeString($key);
$this->writeLong($value);
}
}
}
public function readStringLongMap(): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readString();
$value = $this->readLong();
$map[$key] = $value;
}
}
return $map;
}
public function writeStringStringMap(array $map): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeString($key);
$this->writeString($value);
}
}
}
public function readStringStringMap(): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readString();
$value = $this->readString();
$map[$key] = $value;
}
}
return $map;
}
public function writeStringPacketMap(array $map, int $protocolId): void
{
if (empty($map)) {
$this->writeInt(0);
} else {
$this->writeInt(count($map));
foreach ($map as $key => $value) {
$this->writeString($key);
$this->writePacket($value, $protocolId);
}
}
}
public function readStringPacketMap(int $protocolId): array
{
$size = $this->readInt();
$map = array();
if ($size > 0) {
for ($index = 0; $index < $size; $index++) {
$key = $this->readString();
$value = $this->readPacket($protocolId);
$map[$key] = $value;
}
}
return $map;
}
}
@@ -0,0 +1,13 @@
<?php
namespace zfoophp;
interface IProtocolRegistration
{
public function protocolId(): int;
public function write(ByteBuffer $buffer, mixed $packet): void;
public function read(ByteBuffer $buffer): mixed;
}
@@ -0,0 +1,56 @@
<?php
namespace zfoophp;
include_once 'IProtocolRegistration.php';
include_once 'packet/EmptyObject.php';
include_once 'packet/NormalObject.php';
include_once 'packet/ObjectA.php';
include_once 'packet/ObjectB.php';
include_once 'packet/SimpleObject.php';
class ProtocolManager
{
private static array $protocols = array();
private static array $protocolIdMap = array();
public static function initProtocol(): void
{
self::$protocols[0] = new EmptyObjectRegistration();
self::$protocolIdMap[EmptyObject::class] = 0;
self::$protocols[101] = new NormalObjectRegistration();
self::$protocolIdMap[NormalObject::class] = 101;
self::$protocols[102] = new ObjectARegistration();
self::$protocolIdMap[ObjectA::class] = 102;
self::$protocols[103] = new ObjectBRegistration();
self::$protocolIdMap[ObjectB::class] = 103;
self::$protocols[104] = new SimpleObjectRegistration();
self::$protocolIdMap[SimpleObject::class] = 104;;
}
public static function getProtocolId(mixed $clazz): int
{
return self::$protocolIdMap[$clazz];
}
public static function getProtocol(int $protocolId): IProtocolRegistration
{
return self::$protocols[$protocolId];
}
public static function write(ByteBuffer $buffer, mixed $packet): void
{
$protocolId = self::getProtocolId($packet::class);
// write protocol id to buffer
$buffer->writeShort($protocolId);
// write packet
self::getProtocol($protocolId)->write($buffer, $packet);
}
public static function read(ByteBuffer $buffer): mixed
{
$protocolId = $buffer->readShort();
return self::getProtocol($protocolId)->read($buffer);
}
}
@@ -0,0 +1,40 @@
<?php
namespace zfoophp;
class EmptyObject {
}
class EmptyObjectRegistration implements IProtocolRegistration {
public function protocolId(): int
{
return 0;
}
public function write(ByteBuffer $buffer, mixed $packet): void
{
if ($packet == null)
{
$buffer->writeInt(0);
return;
}
$buffer->writeInt(-1);
}
public function read(ByteBuffer $buffer): mixed
{
$length = $buffer->readInt();
$packet = new EmptyObject();
if ($length == 0) {
return $packet;
}
$beforeReadIndex = $buffer->getReadOffset();
if ($length > 0) {
$buffer->setReadOffset($beforeReadIndex + $length);
}
return $packet;
}
}
@@ -0,0 +1,125 @@
<?php
namespace zfoophp;
// 常规的对象,取所有语言语法的交集,基本上所有语言都支持下面的语法
class NormalObject {
var int $a = 0;
var array $aaa = array();
var int $b = 0;
// 整数类型
var int $c = 0;
var int $d = 0;
var float $e = 0;
var float $f = 0;
var bool $g = false;
var string $jj = "";
var mixed $kk = null;
var array $l = array();
var array $ll = array();
var array $lll = array();
var array $llll = array();
var array $m = array();
var array $mm = array();
var array $s = array();
var array $ssss = array();
var int $outCompatibleValue = 0;
var int $outCompatibleValue2 = 0;
}
class NormalObjectRegistration implements IProtocolRegistration {
public function protocolId(): int
{
return 101;
}
public function write(ByteBuffer $buffer, mixed $packet): void
{
if ($packet == null)
{
$buffer->writeInt(0);
return;
}
$beforeWriteIndex = $buffer->getWriteOffset();
$buffer->writeInt(857);
$buffer->writeByte($packet->a);
$buffer->writeByteArray($packet->aaa);
$buffer->writeShort($packet->b);
$buffer->writeInt($packet->c);
$buffer->writeLong($packet->d);
$buffer->writeFloat($packet->e);
$buffer->writeDouble($packet->f);
$buffer->writeBool($packet->g);
$buffer->writeString($packet->jj);
$buffer->writePacket($packet->kk, 102);
$buffer->writeIntArray($packet->l);
$buffer->writeLongArray($packet->ll);
$buffer->writePacketArray($packet->lll, 102);
$buffer->writeStringArray($packet->llll);
$buffer->writeIntStringMap($packet->m);
$buffer->writeIntPacketMap($packet->mm, 102);
$buffer->writeIntArray($packet->s);
$buffer->writeStringArray($packet->ssss);
$buffer->writeInt($packet->outCompatibleValue);
$buffer->writeInt($packet->outCompatibleValue2);
$buffer->adjustPadding(857, $beforeWriteIndex);
}
public function read(ByteBuffer $buffer): mixed
{
$length = $buffer->readInt();
$packet = new NormalObject();
if ($length == 0) {
return $packet;
}
$beforeReadIndex = $buffer->getReadOffset();
$result0 = $buffer->readByte();
$packet->a = $result0;
$array1 = $buffer->readByteArray();
$packet->aaa = $array1;
$result2 = $buffer->readShort();
$packet->b = $result2;
$result3 = $buffer->readInt();
$packet->c = $result3;
$result4 = $buffer->readLong();
$packet->d = $result4;
$result5 = $buffer->readFloat();
$packet->e = $result5;
$result6 = $buffer->readDouble();
$packet->f = $result6;
$result7 = $buffer->readBool();
$packet->g = $result7;
$result8 = $buffer->readString();
$packet->jj = $result8;
$result9 = $buffer->readPacket(102);
$packet->kk = $result9;
$list10 = $buffer->readIntArray();
$packet->l = $list10;
$list11 = $buffer->readLongArray();
$packet->ll = $list11;
$list12 = $buffer->readPacketArray(102);
$packet->lll = $list12;
$list13 = $buffer->readStringArray();
$packet->llll = $list13;
$map14 = $buffer->readIntStringMap();
$packet->m = $map14;
$map15 = $buffer->readIntPacketMap(102);
$packet->mm = $map15;
$set16 = $buffer->readIntArray();
$packet->s = $set16;
$set17 = $buffer->readStringArray();
$packet->ssss = $set17;
if ($buffer->compatibleRead($beforeReadIndex, $length)) {
$result18 = $buffer->readInt();
$packet->outCompatibleValue = $result18;
}
if ($buffer->compatibleRead($beforeReadIndex, $length)) {
$result19 = $buffer->readInt();
$packet->outCompatibleValue2 = $result19;
}
if ($length > 0) {
$buffer->setReadOffset($beforeReadIndex + $length);
}
return $packet;
}
}
@@ -0,0 +1,58 @@
<?php
namespace zfoophp;
class ObjectA {
var int $a = 0;
var array $m = array();
var mixed $objectB = null;
var int $innerCompatibleValue = 0;
}
class ObjectARegistration implements IProtocolRegistration {
public function protocolId(): int
{
return 102;
}
public function write(ByteBuffer $buffer, mixed $packet): void
{
if ($packet == null)
{
$buffer->writeInt(0);
return;
}
$beforeWriteIndex = $buffer->getWriteOffset();
$buffer->writeInt(201);
$buffer->writeInt($packet->a);
$buffer->writeIntStringMap($packet->m);
$buffer->writePacket($packet->objectB, 103);
$buffer->writeInt($packet->innerCompatibleValue);
$buffer->adjustPadding(201, $beforeWriteIndex);
}
public function read(ByteBuffer $buffer): mixed
{
$length = $buffer->readInt();
$packet = new ObjectA();
if ($length == 0) {
return $packet;
}
$beforeReadIndex = $buffer->getReadOffset();
$result0 = $buffer->readInt();
$packet->a = $result0;
$map1 = $buffer->readIntStringMap();
$packet->m = $map1;
$result2 = $buffer->readPacket(103);
$packet->objectB = $result2;
if ($buffer->compatibleRead($beforeReadIndex, $length)) {
$result3 = $buffer->readInt();
$packet->innerCompatibleValue = $result3;
}
if ($length > 0) {
$buffer->setReadOffset($beforeReadIndex + $length);
}
return $packet;
}
}
@@ -0,0 +1,50 @@
<?php
namespace zfoophp;
class ObjectB {
var bool $flag = false;
var int $innerCompatibleValue = 0;
}
class ObjectBRegistration implements IProtocolRegistration {
public function protocolId(): int
{
return 103;
}
public function write(ByteBuffer $buffer, mixed $packet): void
{
if ($packet == null)
{
$buffer->writeInt(0);
return;
}
$beforeWriteIndex = $buffer->getWriteOffset();
$buffer->writeInt(4);
$buffer->writeBool($packet->flag);
$buffer->writeInt($packet->innerCompatibleValue);
$buffer->adjustPadding(4, $beforeWriteIndex);
}
public function read(ByteBuffer $buffer): mixed
{
$length = $buffer->readInt();
$packet = new ObjectB();
if ($length == 0) {
return $packet;
}
$beforeReadIndex = $buffer->getReadOffset();
$result0 = $buffer->readBool();
$packet->flag = $result0;
if ($buffer->compatibleRead($beforeReadIndex, $length)) {
$result1 = $buffer->readInt();
$packet->innerCompatibleValue = $result1;
}
if ($length > 0) {
$buffer->setReadOffset($beforeReadIndex + $length);
}
return $packet;
}
}
@@ -0,0 +1,46 @@
<?php
namespace zfoophp;
class SimpleObject {
var int $c = 0;
var bool $g = false;
}
class SimpleObjectRegistration implements IProtocolRegistration {
public function protocolId(): int
{
return 104;
}
public function write(ByteBuffer $buffer, mixed $packet): void
{
if ($packet == null)
{
$buffer->writeInt(0);
return;
}
$buffer->writeInt(-1);
$buffer->writeInt($packet->c);
$buffer->writeBool($packet->g);
}
public function read(ByteBuffer $buffer): mixed
{
$length = $buffer->readInt();
$packet = new SimpleObject();
if ($length == 0) {
return $packet;
}
$beforeReadIndex = $buffer->getReadOffset();
$result0 = $buffer->readInt();
$packet->c = $result0;
$result1 = $buffer->readBool();
$packet->g = $result1;
if ($length > 0) {
$buffer->setReadOffset($beforeReadIndex + $length);
}
return $packet;
}
}