updated plugin WP-WebAuthn
version 1.3.1
This commit is contained in:
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Spomky-Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "spomky-labs/cbor-php",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"keywords": ["CBOR", "Concise Binary Object Representation", "RFC7049"],
|
||||
"description": "CBOR Encoder/Decoder for PHP",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Florent Morselli",
|
||||
"homepage": "https://github.com/Spomky"
|
||||
},{
|
||||
"name": "All contributors",
|
||||
"homepage": "https://github.com/Spomky-Labs/cbor-php/contributors"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"CBOR\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"CBOR\\Test\\": "tests/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.3",
|
||||
"brick/math": "^0.8.15|^0.9.0",
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-json": "*",
|
||||
"ekino/phpstan-banned-code": "^1.0",
|
||||
"infection/infection": "^0.18|^0.25",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"phpstan/phpstan-beberlei-assert": "^1.0",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"rector/rector": "^0.12",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"symplify/easy-coding-standard": "^10.0"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gmp": "GMP or BCMath extensions will drastically improve the library performance",
|
||||
"ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags"
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use function chr;
|
||||
|
||||
abstract class AbstractCBORObject implements CBORObject
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $additionalInformation;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $majorType;
|
||||
|
||||
public function __construct(int $majorType, int $additionalInformation)
|
||||
{
|
||||
$this->majorType = $majorType;
|
||||
$this->additionalInformation = $additionalInformation;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return chr($this->majorType << 5 | $this->additionalInformation);
|
||||
}
|
||||
|
||||
public function getMajorType(): int
|
||||
{
|
||||
return $this->majorType;
|
||||
}
|
||||
|
||||
public function getAdditionalInformation(): int
|
||||
{
|
||||
return $this->additionalInformation;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
final class ByteStringObject extends AbstractCBORObject implements Normalizable
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_BYTE_STRING;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $length;
|
||||
|
||||
public function __construct(string $data)
|
||||
{
|
||||
[$additionalInformation, $length] = LengthCalculator::getLengthOfString($data);
|
||||
|
||||
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
|
||||
$this->length = $length;
|
||||
$this->value = $data;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if ($this->length !== null) {
|
||||
$result .= $this->length;
|
||||
}
|
||||
|
||||
return $result . $this->value;
|
||||
}
|
||||
|
||||
public static function create(string $data): self
|
||||
{
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function getLength(): int
|
||||
{
|
||||
return mb_strlen($this->value, '8bit');
|
||||
}
|
||||
|
||||
public function normalize(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in v3.0. Please use IndefiniteLengthByteStringObject instead
|
||||
*/
|
||||
final class ByteStringWithChunkObject extends IndefiniteLengthByteStringObject
|
||||
{
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
interface CBORObject
|
||||
{
|
||||
public const MAJOR_TYPE_UNSIGNED_INTEGER = 0b000;
|
||||
|
||||
public const MAJOR_TYPE_NEGATIVE_INTEGER = 0b001;
|
||||
|
||||
public const MAJOR_TYPE_BYTE_STRING = 0b010;
|
||||
|
||||
public const MAJOR_TYPE_TEXT_STRING = 0b011;
|
||||
|
||||
public const MAJOR_TYPE_LIST = 0b100;
|
||||
|
||||
public const MAJOR_TYPE_MAP = 0b101;
|
||||
|
||||
public const MAJOR_TYPE_TAG = 0b110;
|
||||
|
||||
public const MAJOR_TYPE_OTHER_TYPE = 0b111;
|
||||
|
||||
public const LENGTH_1_BYTE = 0b00011000;
|
||||
|
||||
public const LENGTH_2_BYTES = 0b00011001;
|
||||
|
||||
public const LENGTH_4_BYTES = 0b00011010;
|
||||
|
||||
public const LENGTH_8_BYTES = 0b00011011;
|
||||
|
||||
public const LENGTH_INDEFINITE = 0b00011111;
|
||||
|
||||
public const FUTURE_USE_1 = 0b00011100;
|
||||
|
||||
public const FUTURE_USE_2 = 0b00011101;
|
||||
|
||||
public const FUTURE_USE_3 = 0b00011110;
|
||||
|
||||
public const OBJECT_FALSE = 20;
|
||||
|
||||
public const OBJECT_TRUE = 21;
|
||||
|
||||
public const OBJECT_NULL = 22;
|
||||
|
||||
public const OBJECT_UNDEFINED = 23;
|
||||
|
||||
public const OBJECT_SIMPLE_VALUE = 24;
|
||||
|
||||
public const OBJECT_HALF_PRECISION_FLOAT = 25;
|
||||
|
||||
public const OBJECT_SINGLE_PRECISION_FLOAT = 26;
|
||||
|
||||
public const OBJECT_DOUBLE_PRECISION_FLOAT = 27;
|
||||
|
||||
public const OBJECT_BREAK = 0b00011111;
|
||||
|
||||
public const TAG_STANDARD_DATETIME = 0;
|
||||
|
||||
public const TAG_EPOCH_DATETIME = 1;
|
||||
|
||||
public const TAG_UNSIGNED_BIG_NUM = 2;
|
||||
|
||||
public const TAG_NEGATIVE_BIG_NUM = 3;
|
||||
|
||||
public const TAG_DECIMAL_FRACTION = 4;
|
||||
|
||||
public const TAG_BIG_FLOAT = 5;
|
||||
|
||||
public const TAG_ENCODED_BASE64_URL = 21;
|
||||
|
||||
public const TAG_ENCODED_BASE64 = 22;
|
||||
|
||||
public const TAG_ENCODED_BASE16 = 23;
|
||||
|
||||
public const TAG_ENCODED_CBOR = 24;
|
||||
|
||||
public const TAG_URI = 32;
|
||||
|
||||
public const TAG_BASE64_URL = 33;
|
||||
|
||||
public const TAG_BASE64 = 34;
|
||||
|
||||
public const TAG_MIME = 36;
|
||||
|
||||
public const TAG_CBOR = 55799;
|
||||
|
||||
public function __toString(): string;
|
||||
|
||||
public function getMajorType(): int;
|
||||
|
||||
public function getAdditionalInformation(): int;
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false);
|
||||
}
|
@ -0,0 +1,268 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use CBOR\OtherObject\BreakObject;
|
||||
use CBOR\OtherObject\DoublePrecisionFloatObject;
|
||||
use CBOR\OtherObject\FalseObject;
|
||||
use CBOR\OtherObject\HalfPrecisionFloatObject;
|
||||
use CBOR\OtherObject\NullObject;
|
||||
use CBOR\OtherObject\OtherObjectManager;
|
||||
use CBOR\OtherObject\OtherObjectManagerInterface;
|
||||
use CBOR\OtherObject\SimpleObject;
|
||||
use CBOR\OtherObject\SinglePrecisionFloatObject;
|
||||
use CBOR\OtherObject\TrueObject;
|
||||
use CBOR\OtherObject\UndefinedObject;
|
||||
use CBOR\Tag\Base16EncodingTag;
|
||||
use CBOR\Tag\Base64EncodingTag;
|
||||
use CBOR\Tag\Base64Tag;
|
||||
use CBOR\Tag\Base64UrlEncodingTag;
|
||||
use CBOR\Tag\Base64UrlTag;
|
||||
use CBOR\Tag\BigFloatTag;
|
||||
use CBOR\Tag\CBOREncodingTag;
|
||||
use CBOR\Tag\CBORTag;
|
||||
use CBOR\Tag\DatetimeTag;
|
||||
use CBOR\Tag\DecimalFractionTag;
|
||||
use CBOR\Tag\MimeTag;
|
||||
use CBOR\Tag\NegativeBigIntegerTag;
|
||||
use CBOR\Tag\TagManager;
|
||||
use CBOR\Tag\TagManagerInterface;
|
||||
use CBOR\Tag\TimestampTag;
|
||||
use CBOR\Tag\UnsignedBigIntegerTag;
|
||||
use CBOR\Tag\UriTag;
|
||||
use InvalidArgumentException;
|
||||
use function ord;
|
||||
use RuntimeException;
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
final class Decoder implements DecoderInterface
|
||||
{
|
||||
/**
|
||||
* @var Tag\TagManagerInterface
|
||||
*/
|
||||
private $tagManager;
|
||||
|
||||
/**
|
||||
* @var OtherObject\OtherObjectManagerInterface
|
||||
*/
|
||||
private $otherObjectManager;
|
||||
|
||||
public function __construct(
|
||||
?TagManagerInterface $tagManager = null,
|
||||
?OtherObjectManagerInterface $otherTypeManager = null
|
||||
) {
|
||||
$this->tagManager = $tagManager ?? $this->generateTagManager();
|
||||
$this->otherObjectManager = $otherTypeManager ?? $this->generateOtherObjectManager();
|
||||
}
|
||||
|
||||
public static function create(
|
||||
?TagManagerInterface $tagManager = null,
|
||||
?OtherObjectManagerInterface $otherObjectManager = null
|
||||
): self {
|
||||
return new self($tagManager, $otherObjectManager);
|
||||
}
|
||||
|
||||
public function withTagManager(TagManagerInterface $tagManager): self
|
||||
{
|
||||
$this->tagManager = $tagManager;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withOtherObjectManager(OtherObjectManagerInterface $otherObjectManager): self
|
||||
{
|
||||
$this->otherObjectManager = $otherObjectManager;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function decode(Stream $stream): CBORObject
|
||||
{
|
||||
return $this->process($stream, false);
|
||||
}
|
||||
|
||||
private function process(Stream $stream, bool $breakable): CBORObject
|
||||
{
|
||||
$ib = ord($stream->read(1));
|
||||
$mt = $ib >> 5;
|
||||
$ai = $ib & 0b00011111;
|
||||
$val = null;
|
||||
switch ($ai) {
|
||||
case CBORObject::LENGTH_1_BYTE: //24
|
||||
case CBORObject::LENGTH_2_BYTES: //25
|
||||
case CBORObject::LENGTH_4_BYTES: //26
|
||||
case CBORObject::LENGTH_8_BYTES: //27
|
||||
$val = $stream->read(2 ** ($ai & 0b00000111));
|
||||
break;
|
||||
case CBORObject::FUTURE_USE_1: //28
|
||||
case CBORObject::FUTURE_USE_2: //29
|
||||
case CBORObject::FUTURE_USE_3: //30
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Cannot parse the data. Found invalid Additional Information "%s" (%d).',
|
||||
str_pad(decbin($ai), 8, '0', STR_PAD_LEFT),
|
||||
$ai
|
||||
));
|
||||
case CBORObject::LENGTH_INDEFINITE: //31
|
||||
return $this->processInfinite($stream, $mt, $breakable);
|
||||
}
|
||||
|
||||
return $this->processFinite($stream, $mt, $ai, $val);
|
||||
}
|
||||
|
||||
private function processFinite(Stream $stream, int $mt, int $ai, ?string $val): CBORObject
|
||||
{
|
||||
switch ($mt) {
|
||||
case CBORObject::MAJOR_TYPE_UNSIGNED_INTEGER: //0
|
||||
return UnsignedIntegerObject::createObjectForValue($ai, $val);
|
||||
case CBORObject::MAJOR_TYPE_NEGATIVE_INTEGER: //1
|
||||
return NegativeIntegerObject::createObjectForValue($ai, $val);
|
||||
case CBORObject::MAJOR_TYPE_BYTE_STRING: //2
|
||||
$length = $val === null ? $ai : Utils::binToInt($val);
|
||||
|
||||
return ByteStringObject::create($stream->read($length));
|
||||
case CBORObject::MAJOR_TYPE_TEXT_STRING: //3
|
||||
$length = $val === null ? $ai : Utils::binToInt($val);
|
||||
|
||||
return TextStringObject::create($stream->read($length));
|
||||
case CBORObject::MAJOR_TYPE_LIST: //4
|
||||
$object = ListObject::create();
|
||||
$nbItems = $val === null ? $ai : Utils::binToInt($val);
|
||||
for ($i = 0; $i < $nbItems; ++$i) {
|
||||
$object->add($this->process($stream, false));
|
||||
}
|
||||
|
||||
return $object;
|
||||
case CBORObject::MAJOR_TYPE_MAP: //5
|
||||
$object = MapObject::create();
|
||||
$nbItems = $val === null ? $ai : Utils::binToInt($val);
|
||||
for ($i = 0; $i < $nbItems; ++$i) {
|
||||
$object->add($this->process($stream, false), $this->process($stream, false));
|
||||
}
|
||||
|
||||
return $object;
|
||||
case CBORObject::MAJOR_TYPE_TAG: //6
|
||||
return $this->tagManager->createObjectForValue($ai, $val, $this->process($stream, false));
|
||||
case CBORObject::MAJOR_TYPE_OTHER_TYPE: //7
|
||||
return $this->otherObjectManager->createObjectForValue($ai, $val);
|
||||
default:
|
||||
throw new RuntimeException(sprintf(
|
||||
'Unsupported major type "%s" (%d).',
|
||||
str_pad(decbin($mt), 5, '0', STR_PAD_LEFT),
|
||||
$mt
|
||||
)); // Should never append
|
||||
}
|
||||
}
|
||||
|
||||
private function processInfinite(Stream $stream, int $mt, bool $breakable): CBORObject
|
||||
{
|
||||
switch ($mt) {
|
||||
case CBORObject::MAJOR_TYPE_BYTE_STRING: //2
|
||||
$object = IndefiniteLengthByteStringObject::create();
|
||||
while (! ($it = $this->process($stream, true)) instanceof BreakObject) {
|
||||
if (! $it instanceof ByteStringObject) {
|
||||
throw new RuntimeException(
|
||||
'Unable to parse the data. Infinite Byte String object can only get Byte String objects.'
|
||||
);
|
||||
}
|
||||
$object->add($it);
|
||||
}
|
||||
|
||||
return $object;
|
||||
case CBORObject::MAJOR_TYPE_TEXT_STRING: //3
|
||||
$object = IndefiniteLengthTextStringObject::create();
|
||||
while (! ($it = $this->process($stream, true)) instanceof BreakObject) {
|
||||
if (! $it instanceof TextStringObject) {
|
||||
throw new RuntimeException(
|
||||
'Unable to parse the data. Infinite Text String object can only get Text String objects.'
|
||||
);
|
||||
}
|
||||
$object->add($it);
|
||||
}
|
||||
|
||||
return $object;
|
||||
case CBORObject::MAJOR_TYPE_LIST: //4
|
||||
$object = IndefiniteLengthListObject::create();
|
||||
$it = $this->process($stream, true);
|
||||
while (! $it instanceof BreakObject) {
|
||||
$object->add($it);
|
||||
$it = $this->process($stream, true);
|
||||
}
|
||||
|
||||
return $object;
|
||||
case CBORObject::MAJOR_TYPE_MAP: //5
|
||||
$object = IndefiniteLengthMapObject::create();
|
||||
while (! ($it = $this->process($stream, true)) instanceof BreakObject) {
|
||||
$object->add($it, $this->process($stream, false));
|
||||
}
|
||||
|
||||
return $object;
|
||||
case CBORObject::MAJOR_TYPE_OTHER_TYPE: //7
|
||||
if (! $breakable) {
|
||||
throw new InvalidArgumentException('Cannot parse the data. No enclosing indefinite.');
|
||||
}
|
||||
|
||||
return BreakObject::create();
|
||||
case CBORObject::MAJOR_TYPE_UNSIGNED_INTEGER: //0
|
||||
case CBORObject::MAJOR_TYPE_NEGATIVE_INTEGER: //1
|
||||
case CBORObject::MAJOR_TYPE_TAG: //6
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Cannot parse the data. Found infinite length for Major Type "%s" (%d).',
|
||||
str_pad(decbin($mt), 5, '0', STR_PAD_LEFT),
|
||||
$mt
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private function generateTagManager(): TagManagerInterface
|
||||
{
|
||||
return TagManager::create()
|
||||
->add(DatetimeTag::class)
|
||||
->add(TimestampTag::class)
|
||||
|
||||
->add(UnsignedBigIntegerTag::class)
|
||||
->add(NegativeBigIntegerTag::class)
|
||||
|
||||
->add(DecimalFractionTag::class)
|
||||
->add(BigFloatTag::class)
|
||||
|
||||
->add(Base64UrlEncodingTag::class)
|
||||
->add(Base64EncodingTag::class)
|
||||
->add(Base16EncodingTag::class)
|
||||
->add(CBOREncodingTag::class)
|
||||
|
||||
->add(UriTag::class)
|
||||
->add(Base64UrlTag::class)
|
||||
->add(Base64Tag::class)
|
||||
->add(MimeTag::class)
|
||||
|
||||
->add(CBORTag::class)
|
||||
;
|
||||
}
|
||||
|
||||
private function generateOtherObjectManager(): OtherObjectManagerInterface
|
||||
{
|
||||
return OtherObjectManager::create()
|
||||
->add(BreakObject::class)
|
||||
->add(SimpleObject::class)
|
||||
->add(FalseObject::class)
|
||||
->add(TrueObject::class)
|
||||
->add(NullObject::class)
|
||||
->add(UndefinedObject::class)
|
||||
->add(HalfPrecisionFloatObject::class)
|
||||
->add(SinglePrecisionFloatObject::class)
|
||||
->add(DoublePrecisionFloatObject::class)
|
||||
;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
interface DecoderInterface
|
||||
{
|
||||
public function decode(Stream $stream): CBORObject;
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class IndefiniteLengthByteStringObject extends AbstractCBORObject implements Normalizable
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_BYTE_STRING;
|
||||
|
||||
private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
|
||||
|
||||
/**
|
||||
* @var ByteStringObject[]
|
||||
*/
|
||||
private $chunks = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
foreach ($this->chunks as $chunk) {
|
||||
$result .= $chunk->__toString();
|
||||
}
|
||||
|
||||
return $result . "\xFF";
|
||||
}
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function add(ByteStringObject $chunk): self
|
||||
{
|
||||
$this->chunks[] = $chunk;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function append(string $chunk): self
|
||||
{
|
||||
$this->add(ByteStringObject::create($chunk));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
$result = '';
|
||||
foreach ($this->chunks as $chunk) {
|
||||
$result .= $chunk->getValue();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getLength(): int
|
||||
{
|
||||
$length = 0;
|
||||
foreach ($this->chunks as $chunk) {
|
||||
$length += $chunk->getLength();
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
|
||||
public function normalize(): string
|
||||
{
|
||||
$result = '';
|
||||
foreach ($this->chunks as $chunk) {
|
||||
$result .= $chunk->normalize();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): string
|
||||
{
|
||||
$result = '';
|
||||
foreach ($this->chunks as $chunk) {
|
||||
$result .= $chunk->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use function array_key_exists;
|
||||
use ArrayAccess;
|
||||
use ArrayIterator;
|
||||
use function count;
|
||||
use Countable;
|
||||
use InvalidArgumentException;
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* @phpstan-implements ArrayAccess<int, CBORObject>
|
||||
* @phpstan-implements IteratorAggregate<int, CBORObject>
|
||||
* @final
|
||||
*/
|
||||
class IndefiniteLengthListObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_LIST;
|
||||
|
||||
private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
|
||||
|
||||
/**
|
||||
* @var CBORObject[]
|
||||
*/
|
||||
private $data = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
foreach ($this->data as $object) {
|
||||
$result .= (string) $object;
|
||||
}
|
||||
|
||||
return $result . "\xFF";
|
||||
}
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function normalize(): array
|
||||
{
|
||||
return array_map(static function (CBORObject $object) {
|
||||
return $object instanceof Normalizable ? $object->normalize() : $object;
|
||||
}, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): array
|
||||
{
|
||||
return array_map(static function (CBORObject $object) use ($ignoreTags) {
|
||||
return $object->getNormalizedData($ignoreTags);
|
||||
}, $this->data);
|
||||
}
|
||||
|
||||
public function add(CBORObject $item): self
|
||||
{
|
||||
$this->data[] = $item;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function has(int $index): bool
|
||||
{
|
||||
return array_key_exists($index, $this->data);
|
||||
}
|
||||
|
||||
public function remove(int $index): self
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
return $this;
|
||||
}
|
||||
unset($this->data[$index]);
|
||||
$this->data = array_values($this->data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function get(int $index): CBORObject
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
throw new InvalidArgumentException('Index not found.');
|
||||
}
|
||||
|
||||
return $this->data[$index];
|
||||
}
|
||||
|
||||
public function set(int $index, CBORObject $object): self
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
throw new InvalidArgumentException('Index not found.');
|
||||
}
|
||||
|
||||
$this->data[$index] = $object;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. No replacement
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<int, CBORObject>
|
||||
*/
|
||||
public function getIterator(): Iterator
|
||||
{
|
||||
return new ArrayIterator($this->data);
|
||||
}
|
||||
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return $this->has($offset);
|
||||
}
|
||||
|
||||
public function offsetGet($offset): CBORObject
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($offset === null) {
|
||||
$this->add($value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->set($offset, $value);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
$this->remove($offset);
|
||||
}
|
||||
}
|
@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use function array_key_exists;
|
||||
use ArrayAccess;
|
||||
use ArrayIterator;
|
||||
use function count;
|
||||
use Countable;
|
||||
use InvalidArgumentException;
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* @phpstan-implements ArrayAccess<int, CBORObject>
|
||||
* @phpstan-implements IteratorAggregate<int, MapItem>
|
||||
* @final
|
||||
*/
|
||||
class IndefiniteLengthMapObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_MAP;
|
||||
|
||||
private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
|
||||
|
||||
/**
|
||||
* @var MapItem[]
|
||||
*/
|
||||
private $data = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
foreach ($this->data as $object) {
|
||||
$result .= (string) $object->getKey();
|
||||
$result .= (string) $object->getValue();
|
||||
}
|
||||
|
||||
return $result . "\xFF";
|
||||
}
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please use "add" instead
|
||||
*/
|
||||
public function append(CBORObject $key, CBORObject $value): self
|
||||
{
|
||||
return $this->add($key, $value);
|
||||
}
|
||||
|
||||
public function add(CBORObject $key, CBORObject $value): self
|
||||
{
|
||||
if (! $key instanceof Normalizable) {
|
||||
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
|
||||
}
|
||||
$this->data[$key->normalize()] = MapItem::create($key, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $key
|
||||
*/
|
||||
public function has($key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $index
|
||||
*/
|
||||
public function remove($index): self
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
return $this;
|
||||
}
|
||||
unset($this->data[$index]);
|
||||
$this->data = array_values($this->data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $index
|
||||
*/
|
||||
public function get($index): CBORObject
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
throw new InvalidArgumentException('Index not found.');
|
||||
}
|
||||
|
||||
return $this->data[$index]->getValue();
|
||||
}
|
||||
|
||||
public function set(MapItem $object): self
|
||||
{
|
||||
$key = $object->getKey();
|
||||
if (! $key instanceof Normalizable) {
|
||||
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
|
||||
}
|
||||
|
||||
$this->data[$key->normalize()] = $object;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. No replacement
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<int, MapItem>
|
||||
*/
|
||||
public function getIterator(): Iterator
|
||||
{
|
||||
return new ArrayIterator($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function normalize(): array
|
||||
{
|
||||
return array_reduce($this->data, static function (array $carry, MapItem $item): array {
|
||||
$key = $item->getKey();
|
||||
if (! $key instanceof Normalizable) {
|
||||
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
|
||||
}
|
||||
$valueObject = $item->getValue();
|
||||
$carry[$key->normalize()] = $valueObject instanceof Normalizable ? $valueObject->normalize() : $valueObject;
|
||||
|
||||
return $carry;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): array
|
||||
{
|
||||
return array_reduce($this->data, static function (array $carry, MapItem $item) use ($ignoreTags): array {
|
||||
$key = $item->getKey();
|
||||
$valueObject = $item->getValue();
|
||||
$carry[$key->getNormalizedData($ignoreTags)] = $valueObject->getNormalizedData($ignoreTags);
|
||||
|
||||
return $carry;
|
||||
}, []);
|
||||
}
|
||||
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return $this->has($offset);
|
||||
}
|
||||
|
||||
public function offsetGet($offset): CBORObject
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if (! $offset instanceof CBORObject) {
|
||||
throw new InvalidArgumentException('Invalid key');
|
||||
}
|
||||
if (! $value instanceof CBORObject) {
|
||||
throw new InvalidArgumentException('Invalid value');
|
||||
}
|
||||
|
||||
$this->set(MapItem::create($offset, $value));
|
||||
}
|
||||
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
$this->remove($offset);
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class IndefiniteLengthTextStringObject extends AbstractCBORObject implements Normalizable
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_TEXT_STRING;
|
||||
|
||||
private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
|
||||
|
||||
/**
|
||||
* @var TextStringObject[]
|
||||
*/
|
||||
private $data = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
foreach ($this->data as $object) {
|
||||
$result .= (string) $object;
|
||||
}
|
||||
|
||||
return $result . "\xFF";
|
||||
}
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function add(TextStringObject $chunk): self
|
||||
{
|
||||
$this->data[] = $chunk;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function append(string $chunk): self
|
||||
{
|
||||
$this->add(TextStringObject::create($chunk));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
$result = '';
|
||||
foreach ($this->data as $object) {
|
||||
$result .= $object->getValue();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getLength(): int
|
||||
{
|
||||
$length = 0;
|
||||
foreach ($this->data as $object) {
|
||||
$length += $object->getLength();
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
|
||||
public function normalize(): string
|
||||
{
|
||||
$result = '';
|
||||
foreach ($this->data as $object) {
|
||||
$result .= $object->normalize();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): string
|
||||
{
|
||||
$result = '';
|
||||
foreach ($this->data as $object) {
|
||||
$result .= $object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in v3.0. Please use IndefiniteLengthListObject instead
|
||||
*/
|
||||
final class InfiniteListObject extends IndefiniteLengthListObject
|
||||
{
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in v3.0. Please use IndefiniteLengthMapObject instead
|
||||
*/
|
||||
final class InfiniteMapObject extends IndefiniteLengthMapObject
|
||||
{
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
use function chr;
|
||||
use function count;
|
||||
use InvalidArgumentException;
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
final class LengthCalculator
|
||||
{
|
||||
/**
|
||||
* @return array{int, null|string}
|
||||
*/
|
||||
public static function getLengthOfString(string $data): array
|
||||
{
|
||||
$length = mb_strlen($data, '8bit');
|
||||
|
||||
return self::computeLength($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int|string, mixed> $data
|
||||
*
|
||||
* @return array{int, null|string}
|
||||
*/
|
||||
public static function getLengthOfArray(array $data): array
|
||||
{
|
||||
$length = count($data);
|
||||
|
||||
return self::computeLength($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{int, null|string}
|
||||
*/
|
||||
private static function computeLength(int $length): array
|
||||
{
|
||||
switch (true) {
|
||||
case $length <= 23:
|
||||
return [$length, null];
|
||||
case $length <= 0xFF:
|
||||
return [CBORObject::LENGTH_1_BYTE, chr($length)];
|
||||
case $length <= 0xFFFF:
|
||||
return [CBORObject::LENGTH_2_BYTES, self::hex2bin(dechex($length))];
|
||||
case $length <= 0xFFFFFFFF:
|
||||
return [CBORObject::LENGTH_4_BYTES, self::hex2bin(dechex($length))];
|
||||
case BigInteger::of($length)->isLessThanOrEqualTo(BigInteger::fromBase('FFFFFFFFFFFFFFFF', 16)):
|
||||
return [CBORObject::LENGTH_8_BYTES, self::hex2bin(dechex($length))];
|
||||
default:
|
||||
return [CBORObject::LENGTH_INDEFINITE, null];
|
||||
}
|
||||
}
|
||||
|
||||
private static function hex2bin(string $data): string
|
||||
{
|
||||
$data = str_pad($data, (int) (2 ** ceil(log(mb_strlen($data, '8bit'), 2))), '0', STR_PAD_LEFT);
|
||||
$result = hex2bin($data);
|
||||
if ($result === false) {
|
||||
throw new InvalidArgumentException('Unable to convert the data');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use function array_key_exists;
|
||||
use ArrayAccess;
|
||||
use ArrayIterator;
|
||||
use function count;
|
||||
use Countable;
|
||||
use InvalidArgumentException;
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* @phpstan-implements ArrayAccess<int, CBORObject>
|
||||
* @phpstan-implements IteratorAggregate<int, CBORObject>
|
||||
*/
|
||||
class ListObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_LIST;
|
||||
|
||||
/**
|
||||
* @var CBORObject[]
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $length;
|
||||
|
||||
/**
|
||||
* @param CBORObject[] $data
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
[$additionalInformation, $length] = LengthCalculator::getLengthOfArray($data);
|
||||
array_map(static function ($item): void {
|
||||
if (! $item instanceof CBORObject) {
|
||||
throw new InvalidArgumentException('The list must contain only CBORObject objects.');
|
||||
}
|
||||
}, $data);
|
||||
|
||||
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
|
||||
$this->data = array_values($data);
|
||||
$this->length = $length;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if ($this->length !== null) {
|
||||
$result .= $this->length;
|
||||
}
|
||||
foreach ($this->data as $object) {
|
||||
$result .= (string) $object;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CBORObject[] $data
|
||||
*/
|
||||
public static function create(array $data = []): self
|
||||
{
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
public function add(CBORObject $object): self
|
||||
{
|
||||
$this->data[] = $object;
|
||||
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function has(int $index): bool
|
||||
{
|
||||
return array_key_exists($index, $this->data);
|
||||
}
|
||||
|
||||
public function remove(int $index): self
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
return $this;
|
||||
}
|
||||
unset($this->data[$index]);
|
||||
$this->data = array_values($this->data);
|
||||
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function get(int $index): CBORObject
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
throw new InvalidArgumentException('Index not found.');
|
||||
}
|
||||
|
||||
return $this->data[$index];
|
||||
}
|
||||
|
||||
public function set(int $index, CBORObject $object): self
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
throw new InvalidArgumentException('Index not found.');
|
||||
}
|
||||
|
||||
$this->data[$index] = $object;
|
||||
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, mixed>
|
||||
*/
|
||||
public function normalize(): array
|
||||
{
|
||||
return array_map(static function (CBORObject $object) {
|
||||
return $object instanceof Normalizable ? $object->normalize() : $object;
|
||||
}, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): array
|
||||
{
|
||||
return array_map(static function (CBORObject $object) use ($ignoreTags) {
|
||||
return $object->getNormalizedData($ignoreTags);
|
||||
}, $this->data);
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<int, CBORObject>
|
||||
*/
|
||||
public function getIterator(): Iterator
|
||||
{
|
||||
return new ArrayIterator($this->data);
|
||||
}
|
||||
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return $this->has($offset);
|
||||
}
|
||||
|
||||
public function offsetGet($offset): CBORObject
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($offset === null) {
|
||||
$this->add($value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->set($offset, $value);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
$this->remove($offset);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
class MapItem
|
||||
{
|
||||
/**
|
||||
* @var CBORObject
|
||||
*/
|
||||
private $key;
|
||||
|
||||
/**
|
||||
* @var CBORObject
|
||||
*/
|
||||
private $value;
|
||||
|
||||
public function __construct(CBORObject $key, CBORObject $value)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public static function create(CBORObject $key, CBORObject $value): self
|
||||
{
|
||||
return new self($key, $value);
|
||||
}
|
||||
|
||||
public function getKey(): CBORObject
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function getValue(): CBORObject
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use function array_key_exists;
|
||||
use ArrayAccess;
|
||||
use ArrayIterator;
|
||||
use function count;
|
||||
use Countable;
|
||||
use InvalidArgumentException;
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* @phpstan-implements ArrayAccess<int, CBORObject>
|
||||
* @phpstan-implements IteratorAggregate<int, MapItem>
|
||||
*/
|
||||
final class MapObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_MAP;
|
||||
|
||||
/**
|
||||
* @var MapItem[]
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $length;
|
||||
|
||||
/**
|
||||
* @param MapItem[] $data
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
[$additionalInformation, $length] = LengthCalculator::getLengthOfArray($data);
|
||||
array_map(static function ($item): void {
|
||||
if (! $item instanceof MapItem) {
|
||||
throw new InvalidArgumentException('The list must contain only MapItem objects.');
|
||||
}
|
||||
}, $data);
|
||||
|
||||
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
|
||||
$this->data = $data;
|
||||
$this->length = $length;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if ($this->length !== null) {
|
||||
$result .= $this->length;
|
||||
}
|
||||
foreach ($this->data as $object) {
|
||||
$result .= $object->getKey()
|
||||
->__toString()
|
||||
;
|
||||
$result .= $object->getValue()
|
||||
->__toString()
|
||||
;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MapItem[] $data
|
||||
*/
|
||||
public static function create(array $data = []): self
|
||||
{
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
public function add(CBORObject $key, CBORObject $value): self
|
||||
{
|
||||
if (! $key instanceof Normalizable) {
|
||||
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
|
||||
}
|
||||
$this->data[$key->normalize()] = MapItem::create($key, $value);
|
||||
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $key
|
||||
*/
|
||||
public function has($key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $index
|
||||
*/
|
||||
public function remove($index): self
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
return $this;
|
||||
}
|
||||
unset($this->data[$index]);
|
||||
$this->data = array_values($this->data);
|
||||
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $index
|
||||
*/
|
||||
public function get($index): CBORObject
|
||||
{
|
||||
if (! $this->has($index)) {
|
||||
throw new InvalidArgumentException('Index not found.');
|
||||
}
|
||||
|
||||
return $this->data[$index]->getValue();
|
||||
}
|
||||
|
||||
public function set(MapItem $object): self
|
||||
{
|
||||
$key = $object->getKey();
|
||||
if (! $key instanceof Normalizable) {
|
||||
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
|
||||
}
|
||||
|
||||
$this->data[$key->normalize()] = $object;
|
||||
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<int, MapItem>
|
||||
*/
|
||||
public function getIterator(): Iterator
|
||||
{
|
||||
return new ArrayIterator($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
public function normalize(): array
|
||||
{
|
||||
return array_reduce($this->data, static function (array $carry, MapItem $item): array {
|
||||
$key = $item->getKey();
|
||||
if (! $key instanceof Normalizable) {
|
||||
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
|
||||
}
|
||||
$valueObject = $item->getValue();
|
||||
$carry[$key->normalize()] = $valueObject instanceof Normalizable ? $valueObject->normalize() : $valueObject;
|
||||
|
||||
return $carry;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): array
|
||||
{
|
||||
return array_reduce($this->data, static function (array $carry, MapItem $item) use ($ignoreTags): array {
|
||||
$key = $item->getKey();
|
||||
$valueObject = $item->getValue();
|
||||
$carry[$key->getNormalizedData($ignoreTags)] = $valueObject->getNormalizedData($ignoreTags);
|
||||
|
||||
return $carry;
|
||||
}, []);
|
||||
}
|
||||
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return $this->has($offset);
|
||||
}
|
||||
|
||||
public function offsetGet($offset): CBORObject
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if (! $offset instanceof CBORObject) {
|
||||
throw new InvalidArgumentException('Invalid key');
|
||||
}
|
||||
if (! $value instanceof CBORObject) {
|
||||
throw new InvalidArgumentException('Invalid value');
|
||||
}
|
||||
|
||||
$this->set(MapItem::create($offset, $value));
|
||||
}
|
||||
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
$this->remove($offset);
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
use InvalidArgumentException;
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class NegativeIntegerObject extends AbstractCBORObject implements Normalizable
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_NEGATIVE_INTEGER;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $data;
|
||||
|
||||
public function __construct(int $additionalInformation, ?string $data)
|
||||
{
|
||||
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if ($this->data !== null) {
|
||||
$result .= $this->data;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function createObjectForValue(int $additionalInformation, ?string $data): self
|
||||
{
|
||||
return new self($additionalInformation, $data);
|
||||
}
|
||||
|
||||
public static function create(int $value): self
|
||||
{
|
||||
return self::createFromString((string) $value);
|
||||
}
|
||||
|
||||
public static function createFromString(string $value): self
|
||||
{
|
||||
$integer = BigInteger::of($value);
|
||||
|
||||
return self::createBigInteger($integer);
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
if ($this->data === null) {
|
||||
return (string) (-1 - $this->additionalInformation);
|
||||
}
|
||||
|
||||
$result = Utils::binToBigInteger($this->data);
|
||||
$minusOne = BigInteger::of(-1);
|
||||
|
||||
return $minusOne->minus($result)
|
||||
->toBase(10)
|
||||
;
|
||||
}
|
||||
|
||||
public function normalize(): string
|
||||
{
|
||||
return $this->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): string
|
||||
{
|
||||
return $this->getValue();
|
||||
}
|
||||
|
||||
private static function createBigInteger(BigInteger $integer): self
|
||||
{
|
||||
if ($integer->isGreaterThanOrEqualTo(BigInteger::zero())) {
|
||||
throw new InvalidArgumentException('The value must be a negative integer.');
|
||||
}
|
||||
|
||||
$minusOne = BigInteger::of(-1);
|
||||
$computed_value = $minusOne->minus($integer);
|
||||
|
||||
switch (true) {
|
||||
case $computed_value->isLessThan(BigInteger::of(24)):
|
||||
$ai = $computed_value->toInt();
|
||||
$data = null;
|
||||
break;
|
||||
case $computed_value->isLessThan(BigInteger::fromBase('FF', 16)):
|
||||
$ai = 24;
|
||||
$data = self::hex2bin(str_pad($computed_value->toBase(16), 2, '0', STR_PAD_LEFT));
|
||||
break;
|
||||
case $computed_value->isLessThan(BigInteger::fromBase('FFFF', 16)):
|
||||
$ai = 25;
|
||||
$data = self::hex2bin(str_pad($computed_value->toBase(16), 4, '0', STR_PAD_LEFT));
|
||||
break;
|
||||
case $computed_value->isLessThan(BigInteger::fromBase('FFFFFFFF', 16)):
|
||||
$ai = 26;
|
||||
$data = self::hex2bin(str_pad($computed_value->toBase(16), 8, '0', STR_PAD_LEFT));
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException(
|
||||
'Out of range. Please use NegativeBigIntegerTag tag with ByteStringObject object instead.'
|
||||
);
|
||||
}
|
||||
|
||||
return new self($ai, $data);
|
||||
}
|
||||
|
||||
private static function hex2bin(string $data): string
|
||||
{
|
||||
$result = hex2bin($data);
|
||||
if ($result === false) {
|
||||
throw new InvalidArgumentException('Unable to convert the data');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
interface Normalizable
|
||||
{
|
||||
/**
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function normalize();
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
abstract class OtherObject extends AbstractCBORObject
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_OTHER_TYPE;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
public function __construct(int $additionalInformation, ?string $data)
|
||||
{
|
||||
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if ($this->data !== null) {
|
||||
$result .= $this->data;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getContent(): ?string
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
abstract public static function supportedAdditionalInformation(): array;
|
||||
|
||||
abstract public static function createFromLoadedData(int $additionalInformation, ?string $data): self;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use CBOR\OtherObject as Base;
|
||||
|
||||
final class BreakObject extends Base
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::OBJECT_BREAK, null);
|
||||
}
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return [self::OBJECT_BREAK];
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\OtherObject as Base;
|
||||
use CBOR\Utils;
|
||||
use const INF;
|
||||
use InvalidArgumentException;
|
||||
use const NAN;
|
||||
|
||||
final class DoublePrecisionFloatObject extends Base implements Normalizable
|
||||
{
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return [self::OBJECT_DOUBLE_PRECISION_FLOAT];
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
return new self($additionalInformation, $data);
|
||||
}
|
||||
|
||||
public static function create(string $value): self
|
||||
{
|
||||
if (mb_strlen($value, '8bit') !== 8) {
|
||||
throw new InvalidArgumentException('The value is not a valid double precision floating point');
|
||||
}
|
||||
|
||||
return new self(self::OBJECT_DOUBLE_PRECISION_FLOAT, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float|int
|
||||
*/
|
||||
public function normalize()
|
||||
{
|
||||
$exponent = $this->getExponent();
|
||||
$mantissa = $this->getMantissa();
|
||||
$sign = $this->getSign();
|
||||
|
||||
if ($exponent === 0) {
|
||||
$val = $mantissa * 2 ** (-(1022 + 52));
|
||||
} elseif ($exponent !== 0b11111111111) {
|
||||
$val = ($mantissa + (1 << 52)) * 2 ** ($exponent - (1023 + 52));
|
||||
} else {
|
||||
$val = $mantissa === 0 ? INF : NAN;
|
||||
}
|
||||
|
||||
return $sign * $val;
|
||||
}
|
||||
|
||||
public function getExponent(): int
|
||||
{
|
||||
$data = $this->data;
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
|
||||
return Utils::binToBigInteger($data)->shiftedRight(52)->and(Utils::hexToBigInteger('7ff'))->toInt();
|
||||
}
|
||||
|
||||
public function getMantissa(): int
|
||||
{
|
||||
$data = $this->data;
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
|
||||
return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('fffffffffffff'))->toInt();
|
||||
}
|
||||
|
||||
public function getSign(): int
|
||||
{
|
||||
$data = $this->data;
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
$sign = Utils::binToBigInteger($data)->shiftedRight(63);
|
||||
|
||||
return $sign->isEqualTo(BigInteger::one()) ? -1 : 1;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\OtherObject as Base;
|
||||
|
||||
final class FalseObject extends Base implements Normalizable
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::OBJECT_FALSE, null);
|
||||
}
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return [self::OBJECT_FALSE];
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function normalize(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): bool
|
||||
{
|
||||
return $this->normalize();
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use CBOR\OtherObject as Base;
|
||||
use InvalidArgumentException;
|
||||
use function ord;
|
||||
|
||||
final class GenericObject extends Base
|
||||
{
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
if ($data !== null && ord($data) < 32) {
|
||||
throw new InvalidArgumentException('Invalid simple value. Content data should not be present.');
|
||||
}
|
||||
|
||||
return new self($additionalInformation, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\OtherObject as Base;
|
||||
use CBOR\Utils;
|
||||
use const INF;
|
||||
use InvalidArgumentException;
|
||||
use const NAN;
|
||||
|
||||
final class HalfPrecisionFloatObject extends Base implements Normalizable
|
||||
{
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return [self::OBJECT_HALF_PRECISION_FLOAT];
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
return new self($additionalInformation, $data);
|
||||
}
|
||||
|
||||
public static function create(string $value): self
|
||||
{
|
||||
if (mb_strlen($value, '8bit') !== 2) {
|
||||
throw new InvalidArgumentException('The value is not a valid half precision floating point');
|
||||
}
|
||||
|
||||
return new self(self::OBJECT_HALF_PRECISION_FLOAT, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float|int
|
||||
*/
|
||||
public function normalize()
|
||||
{
|
||||
$exponent = $this->getExponent();
|
||||
$mantissa = $this->getMantissa();
|
||||
$sign = $this->getSign();
|
||||
|
||||
if ($exponent === 0) {
|
||||
$val = $mantissa * 2 ** (-24);
|
||||
} elseif ($exponent !== 0b11111) {
|
||||
$val = ($mantissa + (1 << 10)) * 2 ** ($exponent - 25);
|
||||
} else {
|
||||
$val = $mantissa === 0 ? INF : NAN;
|
||||
}
|
||||
|
||||
return $sign * $val;
|
||||
}
|
||||
|
||||
public function getExponent(): int
|
||||
{
|
||||
$data = $this->data;
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
|
||||
return Utils::binToBigInteger($data)->shiftedRight(10)->and(Utils::hexToBigInteger('1f'))->toInt();
|
||||
}
|
||||
|
||||
public function getMantissa(): int
|
||||
{
|
||||
$data = $this->data;
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
|
||||
return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('3ff'))->toInt();
|
||||
}
|
||||
|
||||
public function getSign(): int
|
||||
{
|
||||
$data = $this->data;
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
$sign = Utils::binToBigInteger($data)->shiftedRight(15);
|
||||
|
||||
return $sign->isEqualTo(BigInteger::one()) ? -1 : 1;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\OtherObject as Base;
|
||||
|
||||
final class NullObject extends Base implements Normalizable
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::OBJECT_NULL, null);
|
||||
}
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return [self::OBJECT_NULL];
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function normalize(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->normalize();
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use function array_key_exists;
|
||||
use CBOR\OtherObject;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class OtherObjectManager implements OtherObjectManagerInterface
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $classes = [];
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function add(string $class): self
|
||||
{
|
||||
foreach ($class::supportedAdditionalInformation() as $ai) {
|
||||
if ($ai < 0) {
|
||||
throw new InvalidArgumentException('Invalid additional information.');
|
||||
}
|
||||
$this->classes[$ai] = $class;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getClassForValue(int $value): string
|
||||
{
|
||||
return array_key_exists($value, $this->classes) ? $this->classes[$value] : GenericObject::class;
|
||||
}
|
||||
|
||||
public function createObjectForValue(int $value, ?string $data): OtherObject
|
||||
{
|
||||
/** @var OtherObject $class */
|
||||
$class = $this->getClassForValue($value);
|
||||
|
||||
return $class::createFromLoadedData($value, $data);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use CBOR\OtherObject;
|
||||
|
||||
interface OtherObjectManagerInterface
|
||||
{
|
||||
public function createObjectForValue(int $value, ?string $data): OtherObject;
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\OtherObject as Base;
|
||||
use CBOR\Utils;
|
||||
use function chr;
|
||||
use InvalidArgumentException;
|
||||
use function ord;
|
||||
|
||||
final class SimpleObject extends Base implements Normalizable
|
||||
{
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return array_merge(range(0, 19), [24]);
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
if ($additionalInformation === 24) {
|
||||
if ($data === null) {
|
||||
throw new InvalidArgumentException('Invalid simple value. Content data is missing.');
|
||||
}
|
||||
if (mb_strlen($data, '8bit') !== 1) {
|
||||
throw new InvalidArgumentException('Invalid simple value. Content data is too long.');
|
||||
}
|
||||
if (ord($data) < 32) {
|
||||
throw new InvalidArgumentException('Invalid simple value. Content data must be between 32 and 255.');
|
||||
}
|
||||
} elseif ($additionalInformation < 20) {
|
||||
if ($data !== null) {
|
||||
throw new InvalidArgumentException('Invalid simple value. Content data should not be present.');
|
||||
}
|
||||
}
|
||||
|
||||
return new self($additionalInformation, $data);
|
||||
}
|
||||
|
||||
public function normalize(): int
|
||||
{
|
||||
if ($this->data === null) {
|
||||
return $this->getAdditionalInformation();
|
||||
}
|
||||
|
||||
return Utils::binToInt($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): int
|
||||
{
|
||||
return $this->normalize();
|
||||
}
|
||||
|
||||
public static function create(int $value): self
|
||||
{
|
||||
switch (true) {
|
||||
case $value < 32:
|
||||
return new self($value, null);
|
||||
case $value < 256:
|
||||
return new self(24, chr($value));
|
||||
default:
|
||||
throw new InvalidArgumentException('The value is not a valid simple value.');
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
use CBOR\OtherObject as Base;
|
||||
use CBOR\Utils;
|
||||
use const INF;
|
||||
use InvalidArgumentException;
|
||||
use const NAN;
|
||||
|
||||
final class SinglePrecisionFloatObject extends Base
|
||||
{
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return [self::OBJECT_SINGLE_PRECISION_FLOAT];
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
return new self($additionalInformation, $data);
|
||||
}
|
||||
|
||||
public static function create(string $value): self
|
||||
{
|
||||
if (mb_strlen($value, '8bit') !== 4) {
|
||||
throw new InvalidArgumentException('The value is not a valid single precision floating point');
|
||||
}
|
||||
|
||||
return new self(self::OBJECT_SINGLE_PRECISION_FLOAT, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float|int
|
||||
*/
|
||||
public function normalize()
|
||||
{
|
||||
$exponent = $this->getExponent();
|
||||
$mantissa = $this->getMantissa();
|
||||
$sign = $this->getSign();
|
||||
|
||||
if ($exponent === 0) {
|
||||
$val = $mantissa * 2 ** (-(126 + 23));
|
||||
} elseif ($exponent !== 0b11111111) {
|
||||
$val = ($mantissa + (1 << 23)) * 2 ** ($exponent - (127 + 23));
|
||||
} else {
|
||||
$val = $mantissa === 0 ? INF : NAN;
|
||||
}
|
||||
|
||||
return $sign * $val;
|
||||
}
|
||||
|
||||
public function getExponent(): int
|
||||
{
|
||||
$data = $this->data;
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
|
||||
return Utils::binToBigInteger($data)->shiftedRight(23)->and(Utils::hexToBigInteger('ff'))->toInt();
|
||||
}
|
||||
|
||||
public function getMantissa(): int
|
||||
{
|
||||
$data = $this->data;
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
|
||||
return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('7fffff'))->toInt();
|
||||
}
|
||||
|
||||
public function getSign(): int
|
||||
{
|
||||
$data = $this->data;
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
$sign = Utils::binToBigInteger($data)->shiftedRight(31);
|
||||
|
||||
return $sign->isEqualTo(BigInteger::one()) ? -1 : 1;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\OtherObject as Base;
|
||||
|
||||
final class TrueObject extends Base implements Normalizable
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::OBJECT_TRUE, null);
|
||||
}
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return [self::OBJECT_TRUE];
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function normalize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): bool
|
||||
{
|
||||
return $this->normalize();
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\OtherObject;
|
||||
|
||||
use CBOR\OtherObject as Base;
|
||||
|
||||
final class UndefinedObject extends Base
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(self::OBJECT_UNDEFINED, null);
|
||||
}
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public static function supportedAdditionalInformation(): array
|
||||
{
|
||||
return [self::OBJECT_UNDEFINED];
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return 'undefined';
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in v3.0. Please use NegativeIntegerObject instead
|
||||
*/
|
||||
final class SignedIntegerObject extends NegativeIntegerObject
|
||||
{
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
interface Stream
|
||||
{
|
||||
public function read(int $length): string;
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
final class StringStream implements Stream
|
||||
{
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $resource;
|
||||
|
||||
public function __construct(string $data)
|
||||
{
|
||||
$resource = fopen('php://memory', 'rb+');
|
||||
if ($resource === false) {
|
||||
throw new RuntimeException('Unable to open the memory');
|
||||
}
|
||||
$result = fwrite($resource, $data);
|
||||
if ($result === false) {
|
||||
throw new RuntimeException('Unable to write the memory');
|
||||
}
|
||||
$result = rewind($resource);
|
||||
if ($result === false) {
|
||||
throw new RuntimeException('Unable to rewind the memory');
|
||||
}
|
||||
$this->resource = $resource;
|
||||
}
|
||||
|
||||
public static function create(string $data): self
|
||||
{
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
public function read(int $length): string
|
||||
{
|
||||
if ($length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$alreadyRead = 0;
|
||||
$data = '';
|
||||
while ($alreadyRead < $length) {
|
||||
$left = $length - $alreadyRead;
|
||||
$sizeToRead = $left < 1024 && $left > 0 ? $left : 1024;
|
||||
$newData = fread($this->resource, $sizeToRead);
|
||||
$alreadyRead += $sizeToRead;
|
||||
|
||||
if ($newData === false) {
|
||||
throw new RuntimeException('Unable to read the memory');
|
||||
}
|
||||
if (mb_strlen($newData, '8bit') < $sizeToRead) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Out of range. Expected: %d, read: %d.',
|
||||
$length,
|
||||
mb_strlen($data, '8bit')
|
||||
));
|
||||
}
|
||||
$data .= $newData;
|
||||
}
|
||||
|
||||
if (mb_strlen($data, '8bit') !== $length) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Out of range. Expected: %d, read: %d.',
|
||||
$length,
|
||||
mb_strlen($data, '8bit')
|
||||
));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
abstract class Tag extends AbstractCBORObject
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_TAG;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @var CBORObject
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
|
||||
$this->data = $data;
|
||||
$this->object = $object;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if ($this->data !== null) {
|
||||
$result .= $this->data;
|
||||
}
|
||||
|
||||
return $result . $this->object;
|
||||
}
|
||||
|
||||
public function getData(): ?string
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
abstract public static function getTagId(): int;
|
||||
|
||||
abstract public static function createFromLoadedData(
|
||||
int $additionalInformation,
|
||||
?string $data,
|
||||
CBORObject $object
|
||||
): self;
|
||||
|
||||
public function getValue(): CBORObject
|
||||
{
|
||||
return $this->object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{int, null|string}
|
||||
*/
|
||||
protected static function determineComponents(int $tag): array
|
||||
{
|
||||
switch (true) {
|
||||
case $tag < 0:
|
||||
throw new InvalidArgumentException('The value must be a positive integer.');
|
||||
case $tag < 24:
|
||||
return [$tag, null];
|
||||
case $tag < 0xFF:
|
||||
return [24, self::hex2bin(dechex($tag))];
|
||||
case $tag < 0xFFFF:
|
||||
return [25, self::hex2bin(dechex($tag))];
|
||||
case $tag < 0xFFFFFFFF:
|
||||
return [26, self::hex2bin(dechex($tag))];
|
||||
default:
|
||||
throw new InvalidArgumentException(
|
||||
'Out of range. Please use PositiveBigIntegerTag tag with ByteStringObject object instead.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static function hex2bin(string $data): string
|
||||
{
|
||||
$result = hex2bin($data);
|
||||
if ($result === false) {
|
||||
throw new InvalidArgumentException('Unable to convert the data');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\ByteStringObject;
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthByteStringObject;
|
||||
use CBOR\IndefiniteLengthTextStringObject;
|
||||
use CBOR\Tag;
|
||||
use CBOR\TextStringObject;
|
||||
|
||||
final class Base16EncodingTag extends Tag
|
||||
{
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_ENCODED_BASE16;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_ENCODED_BASE16);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
if ($ignoreTags) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
if (! $this->object instanceof ByteStringObject && ! $this->object instanceof IndefiniteLengthByteStringObject && ! $this->object instanceof TextStringObject && ! $this->object instanceof IndefiniteLengthTextStringObject) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
return bin2hex($this->object->getNormalizedData($ignoreTags));
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\ByteStringObject;
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthByteStringObject;
|
||||
use CBOR\IndefiniteLengthTextStringObject;
|
||||
use CBOR\Tag;
|
||||
use CBOR\TextStringObject;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class Base64EncodingTag extends Tag
|
||||
{
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_ENCODED_BASE64;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_ENCODED_BASE64);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
if ($ignoreTags) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
if (! $this->object instanceof ByteStringObject && ! $this->object instanceof IndefiniteLengthByteStringObject && ! $this->object instanceof TextStringObject && ! $this->object instanceof IndefiniteLengthTextStringObject) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
$result = base64_decode($this->object->getNormalizedData($ignoreTags), true);
|
||||
if ($result === false) {
|
||||
throw new InvalidArgumentException('Unable to decode the data');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthTextStringObject;
|
||||
use CBOR\Tag;
|
||||
use CBOR\TextStringObject;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class Base64Tag extends Tag
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
|
||||
throw new InvalidArgumentException('This tag only accepts a Text String object.');
|
||||
}
|
||||
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_BASE64;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_BASE64);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\ByteStringObject;
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthByteStringObject;
|
||||
use CBOR\IndefiniteLengthTextStringObject;
|
||||
use CBOR\Tag;
|
||||
use CBOR\TextStringObject;
|
||||
use CBOR\Utils;
|
||||
|
||||
final class Base64UrlEncodingTag extends Tag
|
||||
{
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_ENCODED_BASE64_URL;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_ENCODED_BASE64_URL);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
if ($ignoreTags) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
if (! $this->object instanceof ByteStringObject && ! $this->object instanceof IndefiniteLengthByteStringObject && ! $this->object instanceof TextStringObject && ! $this->object instanceof IndefiniteLengthTextStringObject) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
return Utils::decode($this->object->getNormalizedData($ignoreTags));
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthTextStringObject;
|
||||
use CBOR\Tag;
|
||||
use CBOR\TextStringObject;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class Base64UrlTag extends Tag
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
|
||||
throw new InvalidArgumentException('This tag only accepts a Text String object.');
|
||||
}
|
||||
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_BASE64_URL;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_BASE64_URL);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\ListObject;
|
||||
use CBOR\NegativeIntegerObject;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\Tag;
|
||||
use CBOR\UnsignedIntegerObject;
|
||||
use function count;
|
||||
use function extension_loaded;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
final class BigFloatTag extends Tag implements Normalizable
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! extension_loaded('bcmath')) {
|
||||
throw new RuntimeException('The extension "bcmath" is required to use this tag');
|
||||
}
|
||||
|
||||
if (! $object instanceof ListObject || count($object) !== 2) {
|
||||
throw new InvalidArgumentException(
|
||||
'This tag only accepts a ListObject object that contains an exponent and a mantissa.'
|
||||
);
|
||||
}
|
||||
$e = $object->get(0);
|
||||
if (! $e instanceof UnsignedIntegerObject && ! $e instanceof NegativeIntegerObject) {
|
||||
throw new InvalidArgumentException('The exponent must be a Signed Integer or an Unsigned Integer object.');
|
||||
}
|
||||
$m = $object->get(1);
|
||||
if (! $m instanceof UnsignedIntegerObject && ! $m instanceof NegativeIntegerObject && ! $m instanceof NegativeBigIntegerTag && ! $m instanceof UnsignedBigIntegerTag) {
|
||||
throw new InvalidArgumentException(
|
||||
'The mantissa must be a Positive or Negative Signed Integer or an Unsigned Integer object.'
|
||||
);
|
||||
}
|
||||
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_BIG_FLOAT;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_BIG_FLOAT);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
public static function createFromExponentAndMantissa(CBORObject $e, CBORObject $m): Tag
|
||||
{
|
||||
$object = ListObject::create()
|
||||
->add($e)
|
||||
->add($m)
|
||||
;
|
||||
|
||||
return self::create($object);
|
||||
}
|
||||
|
||||
public function normalize()
|
||||
{
|
||||
/** @var ListObject $object */
|
||||
$object = $this->object;
|
||||
/** @var UnsignedIntegerObject|NegativeIntegerObject $e */
|
||||
$e = $object->get(0);
|
||||
/** @var UnsignedIntegerObject|NegativeIntegerObject|NegativeBigIntegerTag|UnsignedBigIntegerTag $m */
|
||||
$m = $object->get(1);
|
||||
|
||||
return rtrim(bcmul($m->normalize(), bcpow('2', $e->normalize(), 100), 100), '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
if ($ignoreTags) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
if (! $this->object instanceof ListObject || count($this->object) !== 2) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
return $this->normalize();
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\ByteStringObject;
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthByteStringObject;
|
||||
use CBOR\Tag;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class CBOREncodingTag extends Tag
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! $object instanceof ByteStringObject && ! $object instanceof IndefiniteLengthByteStringObject) {
|
||||
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
|
||||
}
|
||||
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_ENCODED_CBOR;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_ENCODED_CBOR);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\Tag;
|
||||
|
||||
final class CBORTag extends Tag implements Normalizable
|
||||
{
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_CBOR;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_CBOR);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|CBORObject|null
|
||||
*/
|
||||
public function normalize()
|
||||
{
|
||||
return $this->object instanceof Normalizable ? $this->object->normalize() : $this->object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthTextStringObject;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\Tag;
|
||||
use CBOR\TextStringObject;
|
||||
use const DATE_RFC3339;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class DatetimeTag extends Tag implements Normalizable
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
|
||||
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
|
||||
}
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_STANDARD_DATETIME;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_STANDARD_DATETIME);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
public function normalize(): DateTimeInterface
|
||||
{
|
||||
/** @var TextStringObject|IndefiniteLengthTextStringObject $object */
|
||||
$object = $this->object;
|
||||
$result = DateTimeImmutable::createFromFormat(DATE_RFC3339, $object->normalize());
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$formatted = DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s.uP', $object->normalize());
|
||||
if ($formatted === false) {
|
||||
throw new InvalidArgumentException('Invalid data. Cannot be converted into a datetime object');
|
||||
}
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
if ($ignoreTags) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
return $this->normalize();
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\ListObject;
|
||||
use CBOR\NegativeIntegerObject;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\Tag;
|
||||
use CBOR\UnsignedIntegerObject;
|
||||
use function count;
|
||||
use function extension_loaded;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
final class DecimalFractionTag extends Tag implements Normalizable
|
||||
{
|
||||
public function __construct(CBORObject $object)
|
||||
{
|
||||
if (! extension_loaded('bcmath')) {
|
||||
throw new RuntimeException('The extension "bcmath" is required to use this tag');
|
||||
}
|
||||
if (! $object instanceof ListObject || count($object) !== 2) {
|
||||
throw new InvalidArgumentException(
|
||||
'This tag only accepts a ListObject object that contains an exponent and a mantissa.'
|
||||
);
|
||||
}
|
||||
$e = $object->get(0);
|
||||
if (! $e instanceof UnsignedIntegerObject && ! $e instanceof NegativeIntegerObject) {
|
||||
throw new InvalidArgumentException('The exponent must be a Signed Integer or an Unsigned Integer object.');
|
||||
}
|
||||
$m = $object->get(1);
|
||||
if (! $m instanceof UnsignedIntegerObject && ! $m instanceof NegativeIntegerObject && ! $m instanceof NegativeBigIntegerTag && ! $m instanceof UnsignedBigIntegerTag) {
|
||||
throw new InvalidArgumentException(
|
||||
'The mantissa must be a Positive or Negative Signed Integer or an Unsigned Integer object.'
|
||||
);
|
||||
}
|
||||
|
||||
parent::__construct(self::TAG_DECIMAL_FRACTION, null, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): self
|
||||
{
|
||||
return new self($object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_DECIMAL_FRACTION;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($object);
|
||||
}
|
||||
|
||||
public static function createFromExponentAndMantissa(CBORObject $e, CBORObject $m): Tag
|
||||
{
|
||||
$object = ListObject::create()
|
||||
->add($e)
|
||||
->add($m)
|
||||
;
|
||||
|
||||
return self::create($object);
|
||||
}
|
||||
|
||||
public function normalize()
|
||||
{
|
||||
/** @var ListObject $object */
|
||||
$object = $this->object;
|
||||
/** @var UnsignedIntegerObject|NegativeIntegerObject $e */
|
||||
$e = $object->get(0);
|
||||
/** @var UnsignedIntegerObject|NegativeIntegerObject|NegativeBigIntegerTag|UnsignedBigIntegerTag $m */
|
||||
$m = $object->get(1);
|
||||
|
||||
return rtrim(bcmul($m->normalize(), bcpow('10', $e->normalize(), 100), 100), '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
if ($ignoreTags) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
if (! $this->object instanceof ListObject || count($this->object) !== 2) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
$e = $this->object->get(0);
|
||||
$m = $this->object->get(1);
|
||||
|
||||
if (! $e instanceof UnsignedIntegerObject && ! $e instanceof NegativeIntegerObject) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
if (! $m instanceof UnsignedIntegerObject && ! $m instanceof NegativeIntegerObject && ! $m instanceof NegativeBigIntegerTag && ! $m instanceof UnsignedBigIntegerTag) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
return $this->normalize();
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
/**
|
||||
* @deprecated The class EpochTag is deprecated and will be removed in v3.0. Please use DatetimeTag instead
|
||||
*/
|
||||
final class EpochTag extends DatetimeTag
|
||||
{
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\Tag;
|
||||
|
||||
final class GenericTag extends Tag
|
||||
{
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->object;
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthTextStringObject;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\Tag;
|
||||
use CBOR\TextStringObject;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class MimeTag extends Tag implements Normalizable
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
|
||||
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
|
||||
}
|
||||
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_MIME;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_MIME);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
public function normalize(): string
|
||||
{
|
||||
/** @var TextStringObject|IndefiniteLengthTextStringObject $object */
|
||||
$object = $this->object;
|
||||
|
||||
return $object->normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
use CBOR\ByteStringObject;
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthByteStringObject;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\Tag;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class NegativeBigIntegerTag extends Tag implements Normalizable
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! $object instanceof ByteStringObject && ! $object instanceof IndefiniteLengthByteStringObject) {
|
||||
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
|
||||
}
|
||||
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_NEGATIVE_BIG_NUM;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_NEGATIVE_BIG_NUM);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
public function normalize(): string
|
||||
{
|
||||
/** @var ByteStringObject|IndefiniteLengthByteStringObject $object */
|
||||
$object = $this->object;
|
||||
$integer = BigInteger::fromBase(bin2hex($object->getValue()), 16);
|
||||
$minusOne = BigInteger::of(-1);
|
||||
|
||||
return $minusOne->minus($integer)
|
||||
->toBase(10)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
if ($ignoreTags) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
if (! $this->object instanceof ByteStringObject) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
$integer = BigInteger::fromBase(bin2hex($this->object->getValue()), 16);
|
||||
$minusOne = BigInteger::of(-1);
|
||||
|
||||
return $minusOne->minus($integer)
|
||||
->toBase(10)
|
||||
;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in v3.0. Please use UnsignedBigIntegerTag instead
|
||||
*/
|
||||
final class PositiveBigIntegerTag extends UnsignedBigIntegerTag
|
||||
{
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use function array_key_exists;
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\Tag;
|
||||
use CBOR\Utils;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class TagManager implements TagManagerInterface
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $classes = [];
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function add(string $class): self
|
||||
{
|
||||
if ($class::getTagId() < 0) {
|
||||
throw new InvalidArgumentException('Invalid tag ID.');
|
||||
}
|
||||
$this->classes[$class::getTagId()] = $class;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getClassForValue(int $value): string
|
||||
{
|
||||
return array_key_exists($value, $this->classes) ? $this->classes[$value] : GenericTag::class;
|
||||
}
|
||||
|
||||
public function createObjectForValue(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
$value = $additionalInformation;
|
||||
if ($additionalInformation >= 24) {
|
||||
Utils::assertString($data, 'Invalid data');
|
||||
$value = Utils::binToInt($data);
|
||||
}
|
||||
/** @var Tag $class */
|
||||
$class = $this->getClassForValue($value);
|
||||
|
||||
return $class::createFromLoadedData($additionalInformation, $data, $object);
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\Tag;
|
||||
|
||||
interface TagManagerInterface
|
||||
{
|
||||
public function createObjectForValue(int $additionalInformation, ?string $data, CBORObject $object): Tag;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in v3.0. Please use TagManager instead
|
||||
*/
|
||||
class TagObjectManager extends TagManager
|
||||
{
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\NegativeIntegerObject;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\OtherObject\DoublePrecisionFloatObject;
|
||||
use CBOR\OtherObject\HalfPrecisionFloatObject;
|
||||
use CBOR\OtherObject\SinglePrecisionFloatObject;
|
||||
use CBOR\Tag;
|
||||
use CBOR\UnsignedIntegerObject;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use InvalidArgumentException;
|
||||
use const STR_PAD_RIGHT;
|
||||
|
||||
final class TimestampTag extends Tag implements Normalizable
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! $object instanceof UnsignedIntegerObject && ! $object instanceof NegativeIntegerObject && ! $object instanceof HalfPrecisionFloatObject && ! $object instanceof SinglePrecisionFloatObject && ! $object instanceof DoublePrecisionFloatObject) {
|
||||
throw new InvalidArgumentException('This tag only accepts integer-based or float-based objects.');
|
||||
}
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_EPOCH_DATETIME;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_EPOCH_DATETIME);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
public function normalize(): DateTimeInterface
|
||||
{
|
||||
$object = $this->object;
|
||||
|
||||
switch (true) {
|
||||
case $object instanceof UnsignedIntegerObject:
|
||||
case $object instanceof NegativeIntegerObject:
|
||||
$formatted = DateTimeImmutable::createFromFormat('U', $object->normalize());
|
||||
|
||||
break;
|
||||
case $object instanceof HalfPrecisionFloatObject:
|
||||
case $object instanceof SinglePrecisionFloatObject:
|
||||
case $object instanceof DoublePrecisionFloatObject:
|
||||
$value = (string) $object->normalize();
|
||||
$parts = explode('.', $value);
|
||||
if (isset($parts[1])) {
|
||||
if (mb_strlen($parts[1], '8bit') > 6) {
|
||||
$parts[1] = mb_substr($parts[1], 0, 6, '8bit');
|
||||
} else {
|
||||
$parts[1] = str_pad($parts[1], 6, '0', STR_PAD_RIGHT);
|
||||
}
|
||||
}
|
||||
$formatted = DateTimeImmutable::createFromFormat('U.u', implode('.', $parts));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException('Unable to normalize the object');
|
||||
}
|
||||
|
||||
if ($formatted === false) {
|
||||
throw new InvalidArgumentException('Invalid data. Cannot be converted into a datetime object');
|
||||
}
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
if ($ignoreTags) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
switch (true) {
|
||||
case $this->object instanceof UnsignedIntegerObject:
|
||||
case $this->object instanceof NegativeIntegerObject:
|
||||
case $this->object instanceof HalfPrecisionFloatObject:
|
||||
case $this->object instanceof SinglePrecisionFloatObject:
|
||||
case $this->object instanceof DoublePrecisionFloatObject:
|
||||
return $this->normalize();
|
||||
default:
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\ByteStringObject;
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthByteStringObject;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\Tag;
|
||||
use CBOR\Utils;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class UnsignedBigIntegerTag extends Tag implements Normalizable
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! $object instanceof ByteStringObject && ! $object instanceof IndefiniteLengthByteStringObject) {
|
||||
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
|
||||
}
|
||||
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_UNSIGNED_BIG_NUM;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_UNSIGNED_BIG_NUM);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
public function normalize(): string
|
||||
{
|
||||
/** @var ByteStringObject|IndefiniteLengthByteStringObject $object */
|
||||
$object = $this->object;
|
||||
|
||||
return Utils::hexToString($object->normalize());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
if ($ignoreTags) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
if (! $this->object instanceof ByteStringObject) {
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
|
||||
return Utils::hexToString($this->object->getValue());
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR\Tag;
|
||||
|
||||
use CBOR\CBORObject;
|
||||
use CBOR\IndefiniteLengthTextStringObject;
|
||||
use CBOR\Normalizable;
|
||||
use CBOR\Tag;
|
||||
use CBOR\TextStringObject;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class UriTag extends Tag implements Normalizable
|
||||
{
|
||||
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
|
||||
{
|
||||
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
|
||||
throw new InvalidArgumentException('This tag only accepts a Text String object.');
|
||||
}
|
||||
|
||||
parent::__construct($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function getTagId(): int
|
||||
{
|
||||
return self::TAG_URI;
|
||||
}
|
||||
|
||||
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
|
||||
{
|
||||
return new self($additionalInformation, $data, $object);
|
||||
}
|
||||
|
||||
public static function create(CBORObject $object): Tag
|
||||
{
|
||||
[$ai, $data] = self::determineComponents(self::TAG_URI);
|
||||
|
||||
return new self($ai, $data, $object);
|
||||
}
|
||||
|
||||
public function normalize(): string
|
||||
{
|
||||
/** @var TextStringObject|IndefiniteLengthTextStringObject $object */
|
||||
$object = $this->object;
|
||||
|
||||
return $object->normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false)
|
||||
{
|
||||
return $this->object->getNormalizedData($ignoreTags);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in v3.0. Please use Tag instead
|
||||
*/
|
||||
abstract class TagObject extends Tag
|
||||
{
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
final class TextStringObject extends AbstractCBORObject implements Normalizable
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_TEXT_STRING;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $length;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $data;
|
||||
|
||||
public function __construct(string $data)
|
||||
{
|
||||
[$additionalInformation, $length] = LengthCalculator::getLengthOfString($data);
|
||||
|
||||
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
|
||||
$this->data = $data;
|
||||
$this->length = $length;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if ($this->length !== null) {
|
||||
$result .= $this->length;
|
||||
}
|
||||
|
||||
return $result . $this->data;
|
||||
}
|
||||
|
||||
public static function create(string $data): self
|
||||
{
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function getLength(): int
|
||||
{
|
||||
return mb_strlen($this->data, 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): string
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function normalize()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
/**
|
||||
* @deprecated Will be removed in v3.0. Please use IndefiniteLengthTextStringObject instead
|
||||
*/
|
||||
final class TextStringWithChunkObject extends IndefiniteLengthTextStringObject
|
||||
{
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
use InvalidArgumentException;
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
final class UnsignedIntegerObject extends AbstractCBORObject implements Normalizable
|
||||
{
|
||||
private const MAJOR_TYPE = self::MAJOR_TYPE_UNSIGNED_INTEGER;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $data;
|
||||
|
||||
public function __construct(int $additionalInformation, ?string $data)
|
||||
{
|
||||
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if ($this->data !== null) {
|
||||
$result .= $this->data;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function createObjectForValue(int $additionalInformation, ?string $data): self
|
||||
{
|
||||
return new self($additionalInformation, $data);
|
||||
}
|
||||
|
||||
public static function create(int $value): self
|
||||
{
|
||||
return self::createFromString((string) $value);
|
||||
}
|
||||
|
||||
public static function createFromHex(string $value): self
|
||||
{
|
||||
$integer = BigInteger::fromBase($value, 16);
|
||||
|
||||
return self::createBigInteger($integer);
|
||||
}
|
||||
|
||||
public static function createFromString(string $value): self
|
||||
{
|
||||
$integer = BigInteger::of($value);
|
||||
|
||||
return self::createBigInteger($integer);
|
||||
}
|
||||
|
||||
public function getMajorType(): int
|
||||
{
|
||||
return self::MAJOR_TYPE;
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
if ($this->data === null) {
|
||||
return (string) $this->additionalInformation;
|
||||
}
|
||||
|
||||
$integer = BigInteger::fromBase(bin2hex($this->data), 16);
|
||||
|
||||
return $integer->toBase(10);
|
||||
}
|
||||
|
||||
public function normalize(): string
|
||||
{
|
||||
return $this->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
|
||||
*/
|
||||
public function getNormalizedData(bool $ignoreTags = false): string
|
||||
{
|
||||
return $this->getValue();
|
||||
}
|
||||
|
||||
private static function createBigInteger(BigInteger $integer): self
|
||||
{
|
||||
if ($integer->isLessThan(BigInteger::zero())) {
|
||||
throw new InvalidArgumentException('The value must be a positive integer.');
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case $integer->isLessThan(BigInteger::of(24)):
|
||||
$ai = $integer->toInt();
|
||||
$data = null;
|
||||
break;
|
||||
case $integer->isLessThan(BigInteger::fromBase('FF', 16)):
|
||||
$ai = 24;
|
||||
$data = self::hex2bin(str_pad($integer->toBase(16), 2, '0', STR_PAD_LEFT));
|
||||
break;
|
||||
case $integer->isLessThan(BigInteger::fromBase('FFFF', 16)):
|
||||
$ai = 25;
|
||||
$data = self::hex2bin(str_pad($integer->toBase(16), 4, '0', STR_PAD_LEFT));
|
||||
break;
|
||||
case $integer->isLessThan(BigInteger::fromBase('FFFFFFFF', 16)):
|
||||
$ai = 26;
|
||||
$data = self::hex2bin(str_pad($integer->toBase(16), 8, '0', STR_PAD_LEFT));
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException(
|
||||
'Out of range. Please use PositiveBigIntegerTag tag with ByteStringObject object instead.'
|
||||
);
|
||||
}
|
||||
|
||||
return new self($ai, $data);
|
||||
}
|
||||
|
||||
private static function hex2bin(string $data): string
|
||||
{
|
||||
$result = hex2bin($data);
|
||||
if ($result === false) {
|
||||
throw new InvalidArgumentException('Unable to convert the data');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace CBOR;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
use InvalidArgumentException;
|
||||
use function is_string;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
abstract class Utils
|
||||
{
|
||||
public static function binToInt(string $value): int
|
||||
{
|
||||
return self::binToBigInteger($value)->toInt();
|
||||
}
|
||||
|
||||
public static function binToBigInteger(string $value): BigInteger
|
||||
{
|
||||
return self::hexToBigInteger(bin2hex($value));
|
||||
}
|
||||
|
||||
public static function hexToInt(string $value): int
|
||||
{
|
||||
return self::hexToBigInteger($value)->toInt();
|
||||
}
|
||||
|
||||
public static function hexToBigInteger(string $value): BigInteger
|
||||
{
|
||||
return BigInteger::fromBase($value, 16);
|
||||
}
|
||||
|
||||
public static function hexToString(string $value): string
|
||||
{
|
||||
return BigInteger::fromBase(bin2hex($value), 16)->toBase(10);
|
||||
}
|
||||
|
||||
public static function decode(string $data): string
|
||||
{
|
||||
$decoded = base64_decode(strtr($data, '-_', '+/'), true);
|
||||
if ($decoded === false) {
|
||||
throw new InvalidArgumentException('Invalid data provided');
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed|null $data
|
||||
*/
|
||||
public static function assertString($data, ?string $message = null): void
|
||||
{
|
||||
if (! is_string($data)) {
|
||||
throw new InvalidArgumentException($message ?? '');
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user