Added ZiProto
This commit is contained in:
parent
643f49a2de
commit
7b55258e18
22 changed files with 1953 additions and 2 deletions
12
src/ncc/Exceptions/MalformedJsonException.php
Normal file
12
src/ncc/Exceptions/MalformedJsonException.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\Exceptions;
|
||||||
|
|
||||||
|
|
||||||
|
class MalformedJsonException extends \Exception
|
||||||
|
{
|
||||||
|
public function __construct(string $message = "", int $code = 0, ?Throwable $previous = null)
|
||||||
|
{
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
22
src/ncc/Extensions/ZiProto/Abstracts/Options.php
Normal file
22
src/ncc/Extensions/ZiProto/Abstracts/Options.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto\Abstracts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Options
|
||||||
|
* @package ncc\ZiProto\Abstracts
|
||||||
|
*/
|
||||||
|
abstract class Options
|
||||||
|
{
|
||||||
|
const BIGINT_AS_STR = 0b001;
|
||||||
|
const BIGINT_AS_GMP = 0b010;
|
||||||
|
const BIGINT_AS_EXCEPTION = 0b100;
|
||||||
|
const FORCE_STR = 0b00000001;
|
||||||
|
const FORCE_BIN = 0b00000010;
|
||||||
|
const DETECT_STR_BIN = 0b00000100;
|
||||||
|
const FORCE_ARR = 0b00001000;
|
||||||
|
const FORCE_MAP = 0b00010000;
|
||||||
|
const DETECT_ARR_MAP = 0b00100000;
|
||||||
|
const FORCE_FLOAT32 = 0b01000000;
|
||||||
|
const FORCE_FLOAT64 = 0b10000000;
|
||||||
|
}
|
21
src/ncc/Extensions/ZiProto/Abstracts/Regex.php
Normal file
21
src/ncc/Extensions/ZiProto/Abstracts/Regex.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto\Abstracts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Regex
|
||||||
|
* @package ncc\ZiProto\Abstracts
|
||||||
|
*/
|
||||||
|
abstract class Regex
|
||||||
|
{
|
||||||
|
const UTF8_REGEX = '/\A(?:
|
||||||
|
[\x00-\x7F]++ # ASCII
|
||||||
|
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
|
||||||
|
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
|
||||||
|
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
|
||||||
|
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
|
||||||
|
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
|
||||||
|
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
|
||||||
|
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
|
||||||
|
)*+\z/x';
|
||||||
|
}
|
795
src/ncc/Extensions/ZiProto/BufferStream.php
Normal file
795
src/ncc/Extensions/ZiProto/BufferStream.php
Normal file
|
@ -0,0 +1,795 @@
|
||||||
|
<?php
|
||||||
|
namespace ncc\ZiProto;
|
||||||
|
|
||||||
|
use function gmp_init;
|
||||||
|
use function ord;
|
||||||
|
use function sprintf;
|
||||||
|
use function substr;
|
||||||
|
use function unpack;
|
||||||
|
use ncc\ZiProto\Exception\InsufficientDataException;
|
||||||
|
use ncc\ZiProto\Exception\IntegerOverflowException;
|
||||||
|
use ncc\ZiProto\Exception\DecodingFailedException;
|
||||||
|
use ncc\ZiProto\Exception\InvalidOptionException;
|
||||||
|
use ncc\ncc\ZiProto\TypeTransformer\Extension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BufferStream
|
||||||
|
* @package ZiProto
|
||||||
|
*/
|
||||||
|
class BufferStream
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $offset = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isBigIntAsStr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isBigIntAsGmp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Extension[]|null
|
||||||
|
*/
|
||||||
|
private $transformers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $buffer
|
||||||
|
* @param DecodingOptions|int|null $options
|
||||||
|
*
|
||||||
|
* @throws InvalidOptionException
|
||||||
|
*/
|
||||||
|
public function __construct(string $buffer = '', $options = null)
|
||||||
|
{
|
||||||
|
if (null === $options)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var DecodingOptions $options
|
||||||
|
* @noinspection PhpRedundantVariableDocTypeInspection
|
||||||
|
*/
|
||||||
|
$options = DecodingOptions::fromDefaults();
|
||||||
|
}
|
||||||
|
elseif (!$options instanceof EncodingOptions)
|
||||||
|
{
|
||||||
|
$options = DecodingOptions::fromBitmask($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->isBigIntAsStr = $options->isBigIntAsStrMode();
|
||||||
|
$this->isBigIntAsGmp = $options->isBigIntAsGmpMode();
|
||||||
|
$this->buffer = $buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Extension $transformer
|
||||||
|
* @return BufferStream
|
||||||
|
*/
|
||||||
|
public function registerTransformer(Extension $transformer) : self
|
||||||
|
{
|
||||||
|
$this->transformers[$transformer->getType()] = $transformer;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $data
|
||||||
|
* @return BufferStream
|
||||||
|
*/
|
||||||
|
public function append(string $data) : self
|
||||||
|
{
|
||||||
|
$this->buffer .= $data;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $buffer
|
||||||
|
* @return BufferStream
|
||||||
|
*/
|
||||||
|
public function reset(string $buffer = '') : self
|
||||||
|
{
|
||||||
|
$this->buffer = $buffer;
|
||||||
|
$this->offset = 0;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone Method
|
||||||
|
*/
|
||||||
|
public function __clone()
|
||||||
|
{
|
||||||
|
$this->buffer = '';
|
||||||
|
$this->offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function trydecode() : array
|
||||||
|
{
|
||||||
|
$data = [];
|
||||||
|
$offset = $this->offset;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
$data[] = $this->decode();
|
||||||
|
$offset = $this->offset;
|
||||||
|
} while (isset($this->buffer[$this->offset]));
|
||||||
|
}
|
||||||
|
catch (InsufficientDataException $e)
|
||||||
|
{
|
||||||
|
$this->offset = $offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->offset)
|
||||||
|
{
|
||||||
|
$this->buffer = isset($this->buffer[$this->offset]) ? substr($this->buffer, $this->offset) : '';
|
||||||
|
$this->offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|bool|int|mixed|resource|string|Ext|null
|
||||||
|
*/
|
||||||
|
public function decode()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
// fixint
|
||||||
|
if ($c <= 0x7f)
|
||||||
|
{
|
||||||
|
return $c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixstr
|
||||||
|
if ($c >= 0xa0 && $c <= 0xbf)
|
||||||
|
{
|
||||||
|
return ($c & 0x1f) ? $this->decodeStrData($c & 0x1f) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixarray
|
||||||
|
if ($c >= 0x90 && $c <= 0x9f)
|
||||||
|
{
|
||||||
|
return ($c & 0xf) ? $this->decodeArrayData($c & 0xf) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixmap
|
||||||
|
if ($c >= 0x80 && $c <= 0x8f)
|
||||||
|
{
|
||||||
|
return ($c & 0xf) ? $this->decodeMapData($c & 0xf) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// negfixint
|
||||||
|
if ($c >= 0xe0)
|
||||||
|
{
|
||||||
|
return $c - 0x100;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($c)
|
||||||
|
{
|
||||||
|
case 0xc0: return null;
|
||||||
|
case 0xc2: return false;
|
||||||
|
case 0xc3: return true;
|
||||||
|
|
||||||
|
// bin
|
||||||
|
case 0xc4: return $this->decodeStrData($this->decodeUint8());
|
||||||
|
case 0xc5: return $this->decodeStrData($this->decodeUint16());
|
||||||
|
case 0xc6: return $this->decodeStrData($this->decodeUint32());
|
||||||
|
|
||||||
|
// float
|
||||||
|
case 0xca: return $this->decodeFloat32();
|
||||||
|
case 0xcb: return $this->decodeFloat64();
|
||||||
|
|
||||||
|
// uint
|
||||||
|
case 0xcc: return $this->decodeUint8();
|
||||||
|
case 0xcd: return $this->decodeUint16();
|
||||||
|
case 0xce: return $this->decodeUint32();
|
||||||
|
case 0xcf: return $this->decodeUint64();
|
||||||
|
|
||||||
|
// int
|
||||||
|
case 0xd0: return $this->decodeInt8();
|
||||||
|
case 0xd1: return $this->decodeInt16();
|
||||||
|
case 0xd2: return $this->decodeInt32();
|
||||||
|
case 0xd3: return $this->decodeInt64();
|
||||||
|
|
||||||
|
// str
|
||||||
|
case 0xd9: return $this->decodeStrData($this->decodeUint8());
|
||||||
|
case 0xda: return $this->decodeStrData($this->decodeUint16());
|
||||||
|
case 0xdb: return $this->decodeStrData($this->decodeUint32());
|
||||||
|
|
||||||
|
// array
|
||||||
|
case 0xdc: return $this->decodeArrayData($this->decodeUint16());
|
||||||
|
case 0xdd: return $this->decodeArrayData($this->decodeUint32());
|
||||||
|
|
||||||
|
// map
|
||||||
|
case 0xde: return $this->decodeMapData($this->decodeUint16());
|
||||||
|
case 0xdf: return $this->decodeMapData($this->decodeUint32());
|
||||||
|
|
||||||
|
// ext
|
||||||
|
case 0xd4: return $this->decodeExtData(1);
|
||||||
|
case 0xd5: return $this->decodeExtData(2);
|
||||||
|
case 0xd6: return $this->decodeExtData(4);
|
||||||
|
case 0xd7: return $this->decodeExtData(8);
|
||||||
|
case 0xd8: return $this->decodeExtData(16);
|
||||||
|
case 0xc7: return $this->decodeExtData($this->decodeUint8());
|
||||||
|
case 0xc8: return $this->decodeExtData($this->decodeUint16());
|
||||||
|
case 0xc9: return $this->decodeExtData($this->decodeUint32());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unknownCode($c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function decodeNil()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("\xc0" === $this->buffer[$this->offset])
|
||||||
|
{
|
||||||
|
++$this->offset;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unexpectedCode(ord($this->buffer[$this->offset++]), 'nil');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function decodeBool()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
if (0xc2 === $c)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xc3 === $c)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unexpectedCode($c, 'bool');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int|resource|string
|
||||||
|
*/
|
||||||
|
public function decodeInt()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
// fixint
|
||||||
|
if ($c <= 0x7f)
|
||||||
|
{
|
||||||
|
return $c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// negfixint
|
||||||
|
if ($c >= 0xe0)
|
||||||
|
{
|
||||||
|
return $c - 0x100;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($c)
|
||||||
|
{
|
||||||
|
// uint
|
||||||
|
case 0xcc: return $this->decodeUint8();
|
||||||
|
case 0xcd: return $this->decodeUint16();
|
||||||
|
case 0xce: return $this->decodeUint32();
|
||||||
|
case 0xcf: return $this->decodeUint64();
|
||||||
|
|
||||||
|
// int
|
||||||
|
case 0xd0: return $this->decodeInt8();
|
||||||
|
case 0xd1: return $this->decodeInt16();
|
||||||
|
case 0xd2: return $this->decodeInt32();
|
||||||
|
case 0xd3: return $this->decodeInt64();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unexpectedCode($c, 'int');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function decodeFloat()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
if (0xcb === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeFloat64();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xca === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeFloat32();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unexpectedCode($c, 'float');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function decodeStr()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
if ($c >= 0xa0 && $c <= 0xbf)
|
||||||
|
{
|
||||||
|
return ($c & 0x1f) ? $this->decodeStrData($c & 0x1f) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xd9 === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeStrData($this->decodeUint8());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xda === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeStrData($this->decodeUint16());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xdb === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeStrData($this->decodeUint32());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unexpectedCode($c, 'str');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function decodeBin()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
if (0xc4 === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeStrData($this->decodeUint8());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xc5 === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeStrData($this->decodeUint16());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xc6 === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeStrData($this->decodeUint32());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unexpectedCode($c, 'bin');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function decodeArray()
|
||||||
|
{
|
||||||
|
$size = $this->decodeArrayHeader();
|
||||||
|
$array = [];
|
||||||
|
|
||||||
|
while ($size--)
|
||||||
|
{
|
||||||
|
$array[] = $this->decode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function decodeArrayHeader()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
if ($c >= 0x90 && $c <= 0x9f)
|
||||||
|
{
|
||||||
|
return $c & 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xdc === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeUint16();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xdd === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeUint32();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unexpectedCode($c, 'array header');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function decodeMap()
|
||||||
|
{
|
||||||
|
$size = $this->decodeMapHeader();
|
||||||
|
$map = [];
|
||||||
|
|
||||||
|
while ($size--)
|
||||||
|
{
|
||||||
|
$map[$this->decode()] = $this->decode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function decodeMapHeader()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
if ($c >= 0x80 && $c <= 0x8f)
|
||||||
|
{
|
||||||
|
return $c & 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xde === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeUint16();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0xdf === $c)
|
||||||
|
{
|
||||||
|
return $this->decodeUint32();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unexpectedCode($c, 'map header');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed|Ext
|
||||||
|
*/
|
||||||
|
public function decodeExt()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
switch ($c)
|
||||||
|
{
|
||||||
|
case 0xd4: return $this->decodeExtData(1);
|
||||||
|
case 0xd5: return $this->decodeExtData(2);
|
||||||
|
case 0xd6: return $this->decodeExtData(4);
|
||||||
|
case 0xd7: return $this->decodeExtData(8);
|
||||||
|
case 0xd8: return $this->decodeExtData(16);
|
||||||
|
case 0xc7: return $this->decodeExtData($this->decodeUint8());
|
||||||
|
case 0xc8: return $this->decodeExtData($this->decodeUint16());
|
||||||
|
case 0xc9: return $this->decodeExtData($this->decodeUint32());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw DecodingFailedException::unexpectedCode($c, 'ext header');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function decodeUint8()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ord($this->buffer[$this->offset++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function decodeUint16()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + 1]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$hi = ord($this->buffer[$this->offset]);
|
||||||
|
$lo = ord($this->buffer[++$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
return $hi << 8 | $lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function decodeUint32()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + 3]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
$num = unpack('N', $this->buffer, $this->offset)[1];
|
||||||
|
$this->offset += 4;
|
||||||
|
|
||||||
|
return $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return resource|string
|
||||||
|
*/
|
||||||
|
private function decodeUint64()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + 7]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
$num = unpack('J', $this->buffer, $this->offset)[1];
|
||||||
|
$this->offset += 8;
|
||||||
|
|
||||||
|
return $num < 0 ? $this->handleIntOverflow($num) : $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function decodeInt8()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$num = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
return $num > 0x7f ? $num - 0x100 : $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function decodeInt16()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + 1]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$hi = ord($this->buffer[$this->offset]);
|
||||||
|
$lo = ord($this->buffer[++$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
|
||||||
|
return $hi > 0x7f ? $hi << 8 | $lo - 0x10000 : $hi << 8 | $lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function decodeInt32()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + 3]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
$num = unpack('N', $this->buffer, $this->offset)[1];
|
||||||
|
$this->offset += 4;
|
||||||
|
|
||||||
|
return $num > 0x7fffffff ? $num - 0x100000000 : $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function decodeInt64()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + 7]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
$num = unpack('J', $this->buffer, $this->offset)[1];
|
||||||
|
$this->offset += 8;
|
||||||
|
|
||||||
|
return $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function decodeFloat32()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + 3]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
$num = unpack('G', $this->buffer, $this->offset)[1];
|
||||||
|
$this->offset += 4;
|
||||||
|
|
||||||
|
return $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function decodeFloat64()
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + 7]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
$num = unpack('E', $this->buffer, $this->offset)[1];
|
||||||
|
$this->offset += 8;
|
||||||
|
|
||||||
|
return $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $length
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function decodeStrData($length)
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + $length - 1]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
$str = substr($this->buffer, $this->offset, $length);
|
||||||
|
$this->offset += $length;
|
||||||
|
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $size
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function decodeArrayData($size)
|
||||||
|
{
|
||||||
|
$array = [];
|
||||||
|
|
||||||
|
while ($size--)
|
||||||
|
{
|
||||||
|
$array[] = $this->decode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $size
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function decodeMapData($size)
|
||||||
|
{
|
||||||
|
$map = [];
|
||||||
|
|
||||||
|
while ($size--)
|
||||||
|
{
|
||||||
|
$map[$this->decode()] = $this->decode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $length
|
||||||
|
* @return mixed|Ext
|
||||||
|
*/
|
||||||
|
private function decodeExtData($length)
|
||||||
|
{
|
||||||
|
if (!isset($this->buffer[$this->offset + $length - 1]))
|
||||||
|
{
|
||||||
|
throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// int8
|
||||||
|
$num = ord($this->buffer[$this->offset]);
|
||||||
|
++$this->offset;
|
||||||
|
$type = $num > 0x7f ? $num - 0x100 : $num;
|
||||||
|
|
||||||
|
if (isset($this->transformers[$type]))
|
||||||
|
{
|
||||||
|
return $this->transformers[$type]->decode($this, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = substr($this->buffer, $this->offset, $length);
|
||||||
|
$this->offset += $length;
|
||||||
|
|
||||||
|
return new Ext($type, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $value
|
||||||
|
* @return resource|string
|
||||||
|
*/
|
||||||
|
private function handleIntOverflow($value)
|
||||||
|
{
|
||||||
|
if ($this->isBigIntAsStr)
|
||||||
|
{
|
||||||
|
return sprintf('%u', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isBigIntAsGmp)
|
||||||
|
{
|
||||||
|
return gmp_init(sprintf('%u', $value));
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IntegerOverflowException($value);
|
||||||
|
}
|
||||||
|
}
|
96
src/ncc/Extensions/ZiProto/DecodingOptions.php
Normal file
96
src/ncc/Extensions/ZiProto/DecodingOptions.php
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
<?php
|
||||||
|
namespace ncc\ZiProto;
|
||||||
|
|
||||||
|
use ncc\ZiProto\Exception\InvalidOptionException;
|
||||||
|
use ncc\ZiProto\Abstracts\Options;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class DecodingOptions
|
||||||
|
* @package ZiProto
|
||||||
|
*/
|
||||||
|
final class DecodingOptions
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
|
private $bigIntMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DecodingOptions constructor.
|
||||||
|
*/
|
||||||
|
private function __construct() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return DecodingOptions
|
||||||
|
*/
|
||||||
|
public static function fromDefaults() : self
|
||||||
|
{
|
||||||
|
$self = new self();
|
||||||
|
$self->bigIntMode = Options::BIGINT_AS_STR;
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $bitmask
|
||||||
|
* @return DecodingOptions
|
||||||
|
*/
|
||||||
|
public static function fromBitmask(int $bitmask) : self
|
||||||
|
{
|
||||||
|
$self = new self();
|
||||||
|
|
||||||
|
$self->bigIntMode = self::getSingleOption('bigint', $bitmask,
|
||||||
|
Options::BIGINT_AS_STR |
|
||||||
|
Options::BIGINT_AS_GMP |
|
||||||
|
Options::BIGINT_AS_EXCEPTION
|
||||||
|
) ?: Options::BIGINT_AS_STR;
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isBigIntAsStrMode() : bool
|
||||||
|
{
|
||||||
|
return Options::BIGINT_AS_STR === $this->bigIntMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isBigIntAsGmpMode() : bool
|
||||||
|
{
|
||||||
|
return Options::BIGINT_AS_GMP === $this->bigIntMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param int $bitmask
|
||||||
|
* @param int $validBitmask
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private static function getSingleOption(string $name, int $bitmask, int $validBitmask) : int
|
||||||
|
{
|
||||||
|
$option = $bitmask & $validBitmask;
|
||||||
|
if ($option === ($option & -$option))
|
||||||
|
{
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
|
||||||
|
static $map = [
|
||||||
|
Options::BIGINT_AS_STR => 'BIGINT_AS_STR',
|
||||||
|
Options::BIGINT_AS_GMP => 'BIGINT_AS_GMP',
|
||||||
|
Options::BIGINT_AS_EXCEPTION => 'BIGINT_AS_EXCEPTION',
|
||||||
|
];
|
||||||
|
|
||||||
|
$validOptions = [];
|
||||||
|
for ($i = $validBitmask & -$validBitmask; $i <= $validBitmask; $i <<= 1)
|
||||||
|
{
|
||||||
|
$validOptions[] = __CLASS__.'::'.$map[$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw InvalidOptionException::outOfRange($name, $validOptions);
|
||||||
|
}
|
||||||
|
}
|
171
src/ncc/Extensions/ZiProto/EncodingOptions.php
Normal file
171
src/ncc/Extensions/ZiProto/EncodingOptions.php
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto;
|
||||||
|
|
||||||
|
use ncc\ZiProto\Exception\InvalidOptionException;
|
||||||
|
use ncc\ZiProto\Abstracts\Options;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class EncodingOptions
|
||||||
|
* @package ZiProto
|
||||||
|
*/
|
||||||
|
final class EncodingOptions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $strBinMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $arrMapMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $floatMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EncodingOptions constructor.
|
||||||
|
*/
|
||||||
|
private function __construct() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return EncodingOptions
|
||||||
|
*/
|
||||||
|
public static function fromDefaults() : self
|
||||||
|
{
|
||||||
|
$self = new self();
|
||||||
|
$self->strBinMode = Options::DETECT_STR_BIN;
|
||||||
|
$self->arrMapMode = Options::DETECT_ARR_MAP;
|
||||||
|
$self->floatMode = Options::FORCE_FLOAT64;
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $bitmask
|
||||||
|
* @return EncodingOptions
|
||||||
|
*/
|
||||||
|
public static function fromBitmask(int $bitmask) : self
|
||||||
|
{
|
||||||
|
$self = new self();
|
||||||
|
|
||||||
|
if (self::getSingleOption('str/bin', $bitmask, Options::FORCE_STR | Options::FORCE_BIN | Options::DETECT_STR_BIN))
|
||||||
|
{
|
||||||
|
$self->strBinMode = self::getSingleOption('str/bin', $bitmask,
|
||||||
|
Options::FORCE_STR |
|
||||||
|
Options::FORCE_BIN |
|
||||||
|
Options::DETECT_STR_BIN
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$self->strBinMode = Options::DETECT_STR_BIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::getSingleOption('arr/map', $bitmask, Options::FORCE_ARR | Options::FORCE_MAP | Options::DETECT_ARR_MAP))
|
||||||
|
{
|
||||||
|
$self->arrMapMode = self::getSingleOption('arr/map', $bitmask,
|
||||||
|
Options::FORCE_ARR |
|
||||||
|
Options::FORCE_MAP |
|
||||||
|
Options::DETECT_ARR_MAP
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$self->arrMapMode = Options::DETECT_ARR_MAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::getSingleOption('float', $bitmask, Options::FORCE_FLOAT32 | Options::FORCE_FLOAT64))
|
||||||
|
{
|
||||||
|
$self->floatMode = self::getSingleOption('float', $bitmask,
|
||||||
|
Options::FORCE_FLOAT32 |
|
||||||
|
Options::FORCE_FLOAT64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$self->floatMode = Options::FORCE_FLOAT64;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isDetectStrBinMode() : bool
|
||||||
|
{
|
||||||
|
return Options::DETECT_STR_BIN === $this->strBinMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isForceStrMode() : bool
|
||||||
|
{
|
||||||
|
return Options::FORCE_STR === $this->strBinMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isDetectArrMapMode() : bool
|
||||||
|
{
|
||||||
|
return Options::DETECT_ARR_MAP === $this->arrMapMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isForceArrMode() : bool
|
||||||
|
{
|
||||||
|
return Options::FORCE_ARR === $this->arrMapMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isForceFloat32Mode() : bool
|
||||||
|
{
|
||||||
|
return Options::FORCE_FLOAT32 === $this->floatMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param int $bitmask
|
||||||
|
* @param int $validBitmask
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private static function getSingleOption(string $name, int $bitmask, int $validBitmask) : int
|
||||||
|
{
|
||||||
|
$option = $bitmask & $validBitmask;
|
||||||
|
|
||||||
|
if ($option === ($option & -$option))
|
||||||
|
{
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
|
||||||
|
static $map = [
|
||||||
|
Options::FORCE_STR => 'FORCE_STR',
|
||||||
|
Options::FORCE_BIN => 'FORCE_BIN',
|
||||||
|
Options::DETECT_STR_BIN => 'DETECT_STR_BIN',
|
||||||
|
Options::FORCE_ARR => 'FORCE_ARR',
|
||||||
|
Options::FORCE_MAP => 'FORCE_MAP',
|
||||||
|
Options::DETECT_ARR_MAP => 'DETECT_ARR_MAP',
|
||||||
|
Options::FORCE_FLOAT32 => 'FORCE_FLOAT32',
|
||||||
|
Options::FORCE_FLOAT64 => 'FORCE_FLOAT64',
|
||||||
|
];
|
||||||
|
|
||||||
|
$validOptions = [];
|
||||||
|
|
||||||
|
for ($i = $validBitmask & -$validBitmask; $i <= $validBitmask; $i <<= 1)
|
||||||
|
{
|
||||||
|
$validOptions[] = __CLASS__.'::'.$map[$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw InvalidOptionException::outOfRange($name, $validOptions);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto\Exception;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
use function sprintf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class DecodingFailedException
|
||||||
|
* @package ncc\ZiProto\Exception
|
||||||
|
*/
|
||||||
|
class DecodingFailedException extends RuntimeException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param int $code
|
||||||
|
* @return DecodingFailedException
|
||||||
|
*/
|
||||||
|
public static function unknownCode(int $code) : self
|
||||||
|
{
|
||||||
|
return new self(sprintf('Unknown code: 0x%x.', $code));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $code
|
||||||
|
* @param string $type
|
||||||
|
* @return DecodingFailedException
|
||||||
|
*/
|
||||||
|
public static function unexpectedCode(int $code, string $type) : self
|
||||||
|
{
|
||||||
|
return new self(sprintf('Unexpected %s code: 0x%x.', $type, $code));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto\Exception;
|
||||||
|
|
||||||
|
use function get_class;
|
||||||
|
use function gettype;
|
||||||
|
use function is_object;
|
||||||
|
use RuntimeException;
|
||||||
|
use function sprintf;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class EncodingFailedException
|
||||||
|
* @package ncc\ZiProto\Exception
|
||||||
|
*/
|
||||||
|
class EncodingFailedException extends RuntimeException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EncodingFailedException constructor.
|
||||||
|
* @param $value
|
||||||
|
* @param string $message
|
||||||
|
* @param Throwable|null $previous
|
||||||
|
*/
|
||||||
|
public function __construct($value, string $message = '', Throwable $previous = null)
|
||||||
|
{
|
||||||
|
parent::__construct($message, 0, $previous);
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getValue()
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $value
|
||||||
|
* @return EncodingFailedException
|
||||||
|
*/
|
||||||
|
public static function unsupportedType($value) : self
|
||||||
|
{
|
||||||
|
$message = sprintf('Unsupported type: %s.',
|
||||||
|
is_object($value) ? get_class($value) : gettype($value)
|
||||||
|
);
|
||||||
|
return new self($value, $message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto\Exception;
|
||||||
|
|
||||||
|
use function strlen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class InsufficientDataException
|
||||||
|
* @package ncc\ZiProto\Exception
|
||||||
|
*/
|
||||||
|
class InsufficientDataException extends DecodingFailedException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $buffer
|
||||||
|
* @param int $offset
|
||||||
|
* @param int $expectedLength
|
||||||
|
* @return InsufficientDataException
|
||||||
|
*/
|
||||||
|
public static function unexpectedLength(string $buffer, int $offset, int $expectedLength) : self
|
||||||
|
{
|
||||||
|
$actualLength = strlen($buffer) - $offset;
|
||||||
|
$message = "Not enough data to unpack: expected $expectedLength, got $actualLength.";
|
||||||
|
return new self($message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto\Exception;
|
||||||
|
|
||||||
|
use function sprintf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IntegerOverflowException
|
||||||
|
* @package ncc\ZiProto\Exception
|
||||||
|
*/
|
||||||
|
class IntegerOverflowException extends DecodingFailedException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IntegerOverflowException constructor.
|
||||||
|
* @param int $value
|
||||||
|
*/
|
||||||
|
public function __construct(int $value)
|
||||||
|
{
|
||||||
|
parent::__construct(sprintf('The value is too big: %u.', $value));
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getValue() : int
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto\Exception;
|
||||||
|
|
||||||
|
use function array_pop;
|
||||||
|
use function count;
|
||||||
|
use function implode;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use function sprintf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class InvalidOptionException
|
||||||
|
* @package ncc\ZiProto\Exception
|
||||||
|
*/
|
||||||
|
class InvalidOptionException extends InvalidArgumentException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $invalidOption
|
||||||
|
* @param array $validOptions
|
||||||
|
* @return InvalidOptionException
|
||||||
|
*/
|
||||||
|
public static function outOfRange(string $invalidOption, array $validOptions) : self
|
||||||
|
{
|
||||||
|
$use = count($validOptions) > 2
|
||||||
|
? sprintf('one of %2$s or %1$s', array_pop($validOptions), implode(', ', $validOptions))
|
||||||
|
: implode(' or ', $validOptions);
|
||||||
|
return new self("Invalid option $invalidOption, use $use.");
|
||||||
|
}
|
||||||
|
}
|
30
src/ncc/Extensions/ZiProto/Ext.php
Normal file
30
src/ncc/Extensions/ZiProto/Ext.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
namespace ncc\ZiProto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Ext
|
||||||
|
* @package ZiProto
|
||||||
|
*/
|
||||||
|
final class Ext
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ext constructor.
|
||||||
|
* @param int $type
|
||||||
|
* @param string $data
|
||||||
|
*/
|
||||||
|
public function __construct(int $type, string $data)
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
}
|
419
src/ncc/Extensions/ZiProto/Packet.php
Normal file
419
src/ncc/Extensions/ZiProto/Packet.php
Normal file
|
@ -0,0 +1,419 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto;
|
||||||
|
|
||||||
|
use function array_values;
|
||||||
|
use function chr;
|
||||||
|
use function count;
|
||||||
|
use function is_array;
|
||||||
|
use function is_bool;
|
||||||
|
use function is_float;
|
||||||
|
use function is_int;
|
||||||
|
use function is_string;
|
||||||
|
use function pack;
|
||||||
|
use function preg_match;
|
||||||
|
use function strlen;
|
||||||
|
use ncc\ZiProto\Abstracts\Regex;
|
||||||
|
use ncc\ZiProto\Exception\InvalidOptionException;
|
||||||
|
use ncc\ZiProto\Exception\EncodingFailedException;
|
||||||
|
use ncc\ncc\ZiProto\TypeTransformer\Validator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Packet
|
||||||
|
* @package ZiProto
|
||||||
|
*/
|
||||||
|
class Packet
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isDetectStrBin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isForceStr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isDetectArrMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isForceArr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isForceFloat32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Validator[]|null
|
||||||
|
*/
|
||||||
|
private $transformers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param EncodingOptions|int|null $options
|
||||||
|
*
|
||||||
|
* @throws InvalidOptionException
|
||||||
|
*/
|
||||||
|
public function __construct($options = null)
|
||||||
|
{
|
||||||
|
if (null === $options)
|
||||||
|
{
|
||||||
|
$options = EncodingOptions::fromDefaults();
|
||||||
|
}
|
||||||
|
elseif (!$options instanceof EncodingOptions)
|
||||||
|
{
|
||||||
|
$options = EncodingOptions::fromBitmask($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->isDetectStrBin = $options->isDetectStrBinMode();
|
||||||
|
$this->isForceStr = $options->isForceStrMode();
|
||||||
|
$this->isDetectArrMap = $options->isDetectArrMapMode();
|
||||||
|
$this->isForceArr = $options->isForceArrMode();
|
||||||
|
$this->isForceFloat32 = $options->isForceFloat32Mode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Validator $transformer
|
||||||
|
* @return Packet
|
||||||
|
*/
|
||||||
|
public function registerTransformer(Validator $transformer) : self
|
||||||
|
{
|
||||||
|
$this->transformers[] = $transformer;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $value
|
||||||
|
* @return false|string
|
||||||
|
*/
|
||||||
|
public function encode($value)
|
||||||
|
{
|
||||||
|
if (is_int($value))
|
||||||
|
{
|
||||||
|
return $this->encodeInt($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_string($value))
|
||||||
|
{
|
||||||
|
if ($this->isForceStr)
|
||||||
|
{
|
||||||
|
return $this->encodeStr($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isDetectStrBin)
|
||||||
|
{
|
||||||
|
return preg_match(Regex::UTF8_REGEX, $value)
|
||||||
|
? $this->encodeStr($value)
|
||||||
|
: $this->encodeBin($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->encodeBin($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value))
|
||||||
|
{
|
||||||
|
if ($this->isDetectArrMap)
|
||||||
|
{
|
||||||
|
return array_values($value) === $value
|
||||||
|
? $this->encodeArray($value)
|
||||||
|
: $this->encodeMap($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->isForceArr ? $this->encodeArray($value) : $this->encodeMap($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $value)
|
||||||
|
{
|
||||||
|
return "\xc0";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_bool($value))
|
||||||
|
{
|
||||||
|
return $value ? "\xc3" : "\xc2";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_float($value))
|
||||||
|
{
|
||||||
|
return $this->encodeFloat($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value instanceof Ext)
|
||||||
|
{
|
||||||
|
return $this->encodeExt($value->type, $value->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->transformers)
|
||||||
|
{
|
||||||
|
foreach ($this->transformers as $transformer)
|
||||||
|
{
|
||||||
|
if (null !== $encoded = $transformer->check($this, $value))
|
||||||
|
{
|
||||||
|
return $encoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw EncodingFailedException::unsupportedType($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodeNil()
|
||||||
|
{
|
||||||
|
return "\xc0";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $bool
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodeBool($bool)
|
||||||
|
{
|
||||||
|
return $bool ? "\xc3" : "\xc2";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $int
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodeInt($int)
|
||||||
|
{
|
||||||
|
if ($int >= 0)
|
||||||
|
{
|
||||||
|
if ($int <= 0x7f)
|
||||||
|
{
|
||||||
|
return chr($int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int <= 0xff)
|
||||||
|
{
|
||||||
|
return "\xcc". chr($int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int <= 0xffff)
|
||||||
|
{
|
||||||
|
return "\xcd". chr($int >> 8). chr($int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int <= 0xffffffff)
|
||||||
|
{
|
||||||
|
return pack('CN', 0xce, $int);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pack('CJ', 0xcf, $int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int >= -0x20)
|
||||||
|
{
|
||||||
|
return chr(0xe0 | $int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int >= -0x80)
|
||||||
|
{
|
||||||
|
return "\xd0". chr($int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int >= -0x8000)
|
||||||
|
{
|
||||||
|
return "\xd1". chr($int >> 8). chr($int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int >= -0x80000000)
|
||||||
|
{
|
||||||
|
return pack('CN', 0xd2, $int);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pack('CJ', 0xd3, $int);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $float
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodeFloat($float)
|
||||||
|
{
|
||||||
|
return $this->isForceFloat32
|
||||||
|
? "\xca". pack('G', $float)
|
||||||
|
: "\xcb". pack('E', $float);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $str
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodeStr($str)
|
||||||
|
{
|
||||||
|
$length = strlen($str);
|
||||||
|
|
||||||
|
if ($length < 32)
|
||||||
|
{
|
||||||
|
return chr(0xa0 | $length).$str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($length <= 0xff)
|
||||||
|
{
|
||||||
|
return "\xd9". chr($length).$str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($length <= 0xffff)
|
||||||
|
{
|
||||||
|
return "\xda". chr($length >> 8). chr($length).$str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pack('CN', 0xdb, $length).$str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $str
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodeBin($str)
|
||||||
|
{
|
||||||
|
$length = strlen($str);
|
||||||
|
|
||||||
|
if ($length <= 0xff)
|
||||||
|
{
|
||||||
|
return "\xc4". chr($length).$str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($length <= 0xffff)
|
||||||
|
{
|
||||||
|
return "\xc5". chr($length >> 8). chr($length).$str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pack('CN', 0xc6, $length).$str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $array
|
||||||
|
* @return false|string
|
||||||
|
*/
|
||||||
|
public function encodeArray($array)
|
||||||
|
{
|
||||||
|
$data = $this->encodeArrayHeader(count($array));
|
||||||
|
|
||||||
|
foreach ($array as $val)
|
||||||
|
{
|
||||||
|
$data .= $this->encode($val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $size
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodeArrayHeader($size)
|
||||||
|
{
|
||||||
|
if ($size <= 0xf)
|
||||||
|
{
|
||||||
|
return chr(0x90 | $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($size <= 0xffff)
|
||||||
|
{
|
||||||
|
return "\xdc". chr($size >> 8). chr($size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pack('CN', 0xdd, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $map
|
||||||
|
* @return false|string
|
||||||
|
*/
|
||||||
|
public function encodeMap($map)
|
||||||
|
{
|
||||||
|
$data = $this->encodeMapHeader(count($map));
|
||||||
|
|
||||||
|
if ($this->isForceStr)
|
||||||
|
{
|
||||||
|
foreach ($map as $key => $val)
|
||||||
|
{
|
||||||
|
$data .= is_string($key) ? $this->encodeStr($key) : $this->encodeInt($key);
|
||||||
|
$data .= $this->encode($val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isDetectStrBin)
|
||||||
|
{
|
||||||
|
foreach ($map as $key => $val)
|
||||||
|
{
|
||||||
|
$data .= is_string($key)
|
||||||
|
? (preg_match(Regex::UTF8_REGEX, $key) ? $this->encodeStr($key) : $this->encodeBin($key))
|
||||||
|
: $this->encodeInt($key);
|
||||||
|
$data .= $this->encode($val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($map as $key => $val)
|
||||||
|
{
|
||||||
|
$data .= is_string($key) ? $this->encodeBin($key) : $this->encodeInt($key);
|
||||||
|
$data .= $this->encode($val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $size
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodeMapHeader($size)
|
||||||
|
{
|
||||||
|
if ($size <= 0xf)
|
||||||
|
{
|
||||||
|
return chr(0x80 | $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($size <= 0xffff)
|
||||||
|
{
|
||||||
|
return "\xde". chr($size >> 8). chr($size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pack('CN', 0xdf, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $type
|
||||||
|
* @param $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodeExt($type, $data)
|
||||||
|
{
|
||||||
|
$length = strlen($data);
|
||||||
|
|
||||||
|
switch ($length)
|
||||||
|
{
|
||||||
|
case 1: return "\xd4". chr($type).$data;
|
||||||
|
case 2: return "\xd5". chr($type).$data;
|
||||||
|
case 4: return "\xd6". chr($type).$data;
|
||||||
|
case 8: return "\xd7". chr($type).$data;
|
||||||
|
case 16: return "\xd8". chr($type).$data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($length <= 0xff)
|
||||||
|
{
|
||||||
|
return "\xc7". chr($length). chr($type).$data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($length <= 0xffff)
|
||||||
|
{
|
||||||
|
return pack('CnC', 0xc8, $length, $type).$data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pack('CNC', 0xc9, $length, $type).$data;
|
||||||
|
}
|
||||||
|
}
|
24
src/ncc/Extensions/ZiProto/Type/Binary.php
Normal file
24
src/ncc/Extensions/ZiProto/Type/Binary.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto\Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Binary
|
||||||
|
* @package ncc\ZiProto\Type
|
||||||
|
*/
|
||||||
|
final class Binary
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binary constructor.
|
||||||
|
* @param string $data
|
||||||
|
*/
|
||||||
|
public function __construct(string $data)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
}
|
24
src/ncc/Extensions/ZiProto/Type/Map.php
Normal file
24
src/ncc/Extensions/ZiProto/Type/Map.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto\Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Map
|
||||||
|
* @package ncc\ZiProto\Type
|
||||||
|
*/
|
||||||
|
final class Map
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map constructor.
|
||||||
|
* @param array $map
|
||||||
|
*/
|
||||||
|
public function __construct(array $map)
|
||||||
|
{
|
||||||
|
$this->map = $map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ncc\ZiProto\TypeTransformer;
|
||||||
|
|
||||||
|
use ncc\ZiProto\Packet;
|
||||||
|
use ncc\ZiProto\Type\Binary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BinaryTransformer
|
||||||
|
* @package ncc\ncc\ZiProto\TypeTransformer
|
||||||
|
*/
|
||||||
|
abstract class BinaryTransformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Packet $packer
|
||||||
|
* @param $value
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function pack(Packet $packer, $value): ?string
|
||||||
|
{
|
||||||
|
if ($value instanceof Binary)
|
||||||
|
{
|
||||||
|
return $packer->encodeBin($value->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
24
src/ncc/Extensions/ZiProto/TypeTransformer/Extension.php
Normal file
24
src/ncc/Extensions/ZiProto/TypeTransformer/Extension.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ncc\ZiProto\TypeTransformer;
|
||||||
|
|
||||||
|
use ncc\ZiProto\BufferStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface Extension
|
||||||
|
* @package ncc\ncc\ZiProto\TypeTransformer
|
||||||
|
*/
|
||||||
|
interface Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getType() : int;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BufferStream $stream
|
||||||
|
* @param int $extLength
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function decode(BufferStream $stream, int $extLength);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
namespace ncc\ZiProto\TypeTransformer;
|
||||||
|
|
||||||
|
use ncc\ZiProto\Packet;
|
||||||
|
use ncc\ZiProto\Type\Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MapTransformer
|
||||||
|
* @package ncc\ncc\ZiProto\TypeTransformer
|
||||||
|
*/
|
||||||
|
abstract class MapTransformer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Packet $packer
|
||||||
|
* @param $value
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function encode(Packet $packer, $value): ?string
|
||||||
|
{
|
||||||
|
if ($value instanceof Map)
|
||||||
|
{
|
||||||
|
return $packer->encodeMap($value->map);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
18
src/ncc/Extensions/ZiProto/TypeTransformer/Validator.php
Normal file
18
src/ncc/Extensions/ZiProto/TypeTransformer/Validator.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
namespace ncc\ncc\ZiProto\TypeTransformer;
|
||||||
|
|
||||||
|
use ncc\ZiProto\Packet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface Validator
|
||||||
|
* @package ncc\ncc\ZiProto\TypeTransformer
|
||||||
|
*/
|
||||||
|
interface Validator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Packet $packer
|
||||||
|
* @param $value
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function check(Packet $packer, $value) :string;
|
||||||
|
}
|
44
src/ncc/Extensions/ZiProto/ZiProto.php
Normal file
44
src/ncc/Extensions/ZiProto/ZiProto.php
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ncc\ZiProto;
|
||||||
|
|
||||||
|
use ncc\ZiProto\Exception\DecodingFailedException;
|
||||||
|
use ncc\ZiProto\Exception\EncodingFailedException;
|
||||||
|
use ncc\ZiProto\Exception\InvalidOptionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZiProto Class
|
||||||
|
*
|
||||||
|
* Class ZiProto
|
||||||
|
* @package ZiProto
|
||||||
|
*/
|
||||||
|
class ZiProto
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param mixed $value
|
||||||
|
* @param EncodingOptions|int|null $options
|
||||||
|
*
|
||||||
|
* @throws InvalidOptionException
|
||||||
|
* @throws EncodingFailedException
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function encode($value, $options = null) : string
|
||||||
|
{
|
||||||
|
return (new Packet($options))->encode($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $data
|
||||||
|
* @param DecodingOptions|int|null $options
|
||||||
|
*
|
||||||
|
* @throws InvalidOptionException
|
||||||
|
* @throws DecodingFailedException
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function decode(string $data, $options = null)
|
||||||
|
{
|
||||||
|
return (new BufferStream($data, $options))->decode();
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,11 @@ spl_autoload_register(
|
||||||
'ncc\\exceptions\\filenotfoundexception' => '/Exceptions/FileNotFoundException.php',
|
'ncc\\exceptions\\filenotfoundexception' => '/Exceptions/FileNotFoundException.php',
|
||||||
'ncc\\exceptions\\invalidprojectconfigurationexception' => '/Exceptions/InvalidProjectConfigurationException.php',
|
'ncc\\exceptions\\invalidprojectconfigurationexception' => '/Exceptions/InvalidProjectConfigurationException.php',
|
||||||
'ncc\\exceptions\\invalidscopeexception' => '/Exceptions/InvalidScopeException.php',
|
'ncc\\exceptions\\invalidscopeexception' => '/Exceptions/InvalidScopeException.php',
|
||||||
|
'ncc\\exceptions\\malformedjsonexception' => '/Exceptions/MalformedJsonException.php',
|
||||||
'ncc\\ncc' => '/ncc.php',
|
'ncc\\ncc' => '/ncc.php',
|
||||||
|
'ncc\\ncc\\ziproto\\typetransformer\\binarytransformer' => '/Extensions/ZiProto/TypeTransformer/BinaryTransformer.php',
|
||||||
|
'ncc\\ncc\\ziproto\\typetransformer\\extension' => '/Extensions/ZiProto/TypeTransformer/Extension.php',
|
||||||
|
'ncc\\ncc\\ziproto\\typetransformer\\validator' => '/Extensions/ZiProto/TypeTransformer/Validator.php',
|
||||||
'ncc\\objects\\projectconfiguration' => '/Objects/ProjectConfiguration.php',
|
'ncc\\objects\\projectconfiguration' => '/Objects/ProjectConfiguration.php',
|
||||||
'ncc\\objects\\projectconfiguration\\assembly' => '/Objects/ProjectConfiguration/Assembly.php',
|
'ncc\\objects\\projectconfiguration\\assembly' => '/Objects/ProjectConfiguration/Assembly.php',
|
||||||
'ncc\\objects\\projectconfiguration\\build' => '/Objects/ProjectConfiguration/Build.php',
|
'ncc\\objects\\projectconfiguration\\build' => '/Objects/ProjectConfiguration/Build.php',
|
||||||
|
@ -104,7 +108,23 @@ spl_autoload_register(
|
||||||
'ncc\\utilities\\pathfinder' => '/Utilities/PathFinder.php',
|
'ncc\\utilities\\pathfinder' => '/Utilities/PathFinder.php',
|
||||||
'ncc\\utilities\\resolver' => '/Utilities/Resolver.php',
|
'ncc\\utilities\\resolver' => '/Utilities/Resolver.php',
|
||||||
'ncc\\utilities\\security' => '/Utilities/Security.php',
|
'ncc\\utilities\\security' => '/Utilities/Security.php',
|
||||||
'ncc\\utilities\\validate' => '/Utilities/Validate.php'
|
'ncc\\utilities\\validate' => '/Utilities/Validate.php',
|
||||||
|
'ncc\\ziproto\\abstracts\\options' => '/Extensions/ZiProto/Abstracts/Options.php',
|
||||||
|
'ncc\\ziproto\\abstracts\\regex' => '/Extensions/ZiProto/Abstracts/Regex.php',
|
||||||
|
'ncc\\ziproto\\bufferstream' => '/Extensions/ZiProto/BufferStream.php',
|
||||||
|
'ncc\\ziproto\\decodingoptions' => '/Extensions/ZiProto/DecodingOptions.php',
|
||||||
|
'ncc\\ziproto\\encodingoptions' => '/Extensions/ZiProto/EncodingOptions.php',
|
||||||
|
'ncc\\ziproto\\exception\\decodingfailedexception' => '/Extensions/ZiProto/Exception/DecodingFailedException.php',
|
||||||
|
'ncc\\ziproto\\exception\\encodingfailedexception' => '/Extensions/ZiProto/Exception/EncodingFailedException.php',
|
||||||
|
'ncc\\ziproto\\exception\\insufficientdataexception' => '/Extensions/ZiProto/Exception/InsufficientDataException.php',
|
||||||
|
'ncc\\ziproto\\exception\\integeroverflowexception' => '/Extensions/ZiProto/Exception/IntegerOverflowException.php',
|
||||||
|
'ncc\\ziproto\\exception\\invalidoptionexception' => '/Extensions/ZiProto/Exception/InvalidOptionException.php',
|
||||||
|
'ncc\\ziproto\\ext' => '/Extensions/ZiProto/Ext.php',
|
||||||
|
'ncc\\ziproto\\packet' => '/Extensions/ZiProto/Packet.php',
|
||||||
|
'ncc\\ziproto\\type\\binary' => '/Extensions/ZiProto/Type/Binary.php',
|
||||||
|
'ncc\\ziproto\\type\\map' => '/Extensions/ZiProto/Type/Map.php',
|
||||||
|
'ncc\\ziproto\\typetransformer\\maptransformer' => '/Extensions/ZiProto/TypeTransformer/MapTransformer.php',
|
||||||
|
'ncc\\ziproto\\ziproto' => '/Extensions/ZiProto/ZiProto.php'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$cn = strtolower($class);
|
$cn = strtolower($class);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
require(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoload.php');
|
require(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoload.php');
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue