diff --git a/README.md b/README.md index f420ade..5a64616 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ See the examples below for more information, or check out [`Encoder`](./src/Enco namespace PetrKnap\Binary; $data = base64_decode('hmlpFnFwbchsoQARSibVpfbWVfuwAHLbGxjFl9eC8fiGaWkWcXBtyGyhABFKJtWl9tZV+7AActsbGMWX14Lx+A=='); -$encoded = Binary::encode($data)->checksum()->zlib()->base64(urlSafe: true)->getData(); -$decoded = Binary::decode($encoded)->base64()->zlib()->checksum()->getData(); +$encoded = Binary::encode($data)->checksum()->zlib()->base64(urlSafe: true)->data; +$decoded = Binary::decode($encoded)->base64()->zlib()->checksum()->data; printf('Data was coded into `%s` %s.', $encoded, $decoded === $data ? 'successfully' : 'unsuccessfully'); ``` diff --git a/composer.json b/composer.json index 5728ad9..2a29746 100755 --- a/composer.json +++ b/composer.json @@ -41,7 +41,7 @@ "require": { "php": ">=8.1", "petrknap/optional": "^3.1", - "petrknap/shorts": "^2.0" + "petrknap/shorts": "^3.0" }, "require-dev": { "ext-igbinary": "*", @@ -63,7 +63,7 @@ "phpcs --colors --standard=PSR12 --exclude=Generic.Files.LineLength src tests", "phpstan analyse --level max src --ansi --no-interaction", "phpstan analyse --level 5 tests --ansi --no-interaction", - "phpinsights analyse src --ansi --no-interaction" + "phpinsights analyse src tests --ansi --no-interaction --format=github-action | sed -e \"s#::error file=$PWD/#::notice file=#g\"" ], "check-requirements": [ "composer update \"petrknap/*\"", diff --git a/src/Binary.php b/src/Binary.php index f28d3b7..f75c004 100644 --- a/src/Binary.php +++ b/src/Binary.php @@ -6,12 +6,12 @@ final class Binary { - public static function encode(string $data): EncoderInterface + public static function encode(string $data): Encoder { return new Encoder($data); } - public static function decode(string $data): DecoderInterface + public static function decode(string $data): Decoder { return new Decoder($data); } diff --git a/src/Byter.php b/src/Byter.php index 9049063..7d081fc 100644 --- a/src/Byter.php +++ b/src/Byter.php @@ -7,7 +7,7 @@ use PetrKnap\Shorts\HasRequirements; use RuntimeException; -class Byter +final class Byter { use HasRequirements; @@ -28,7 +28,7 @@ functions: [ * * @return array bites of specified sizes; and remains, if any * - * @throws Exception\CouldNotBiteData + * @throws Exception\ByterCouldNotBiteData */ public function bite(string $data, int $size1, int ...$sizeN): array { @@ -36,7 +36,7 @@ public function bite(string $data, int $size1, int ...$sizeN): array $bites = []; foreach ([$size1, ...$sizeN] as $size) { if (abs($size) > $this->size($remains)) { - throw new Exception\CouldNotBiteData(__METHOD__, $data, new RuntimeException( + throw new Exception\ByterCouldNotBiteData(__METHOD__, $data, new RuntimeException( 'Remains are smaller than bite', )); } diff --git a/src/Coder.php b/src/Coder.php index ea14e4e..58da67a 100644 --- a/src/Coder.php +++ b/src/Coder.php @@ -4,34 +4,54 @@ namespace PetrKnap\Binary; -use PetrKnap\Shorts\Exception; - /** - * @internal please use subclass - * - * @phpstan-consistent-constructor override {@see self::create()} if not - * - * @implements CoderInterface + * @internal shared logic */ -abstract class Coder implements CoderInterface +abstract class Coder { - public function __construct( - protected readonly string $data = '', + final public function __construct( + public readonly string $data = '', ) { } - public function withData(string $data): static + final public function withData(string $data): static { - return static::create($this, $data); + return new static($data); } - public function getData(): string + /** + * @deprecated use readonly property $data + */ + final public function getData(): string { return $this->data; } - protected static function create(self $coder, string $data): static - { - return new static($data); - } + /** + * @see Coder\Base64 + * + * @throws Coder\Exception\CoderException + */ + abstract public function base64(): static; + + /** + * @see Coder\Checksum + * + * @throws Coder\Exception\CoderException + */ + abstract public function checksum(string|null $algorithm = null): static; + + /** + * @see Coder\Hex + * + * @throws Coder\Exception\CoderException + */ + abstract public function hex(): static; + + /** + * @see Coder\zlib + * + * @throws Coder\Exception\CoderException + */ + abstract public function zlib(): static; } diff --git a/src/Coder/Base64.php b/src/Coder/Base64.php index 001f61b..dfc23a8 100644 --- a/src/Coder/Base64.php +++ b/src/Coder/Base64.php @@ -12,8 +12,6 @@ */ final class Base64 extends Coder { - public const URL_SAFE = false; - private const URL_REPLACE_TABLE = [ ['+', '/', '='], ['-', '_', ''], @@ -21,9 +19,9 @@ final class Base64 extends Coder private bool $urlSafe; - public function encode(string $decoded, ?bool $urlSafe = null): string + public function encode(string $decoded, bool|null $urlSafe = null): string { - $this->urlSafe = $urlSafe ?? self::URL_SAFE; + $this->urlSafe = $urlSafe ?? false; return parent::encode($decoded); } @@ -42,7 +40,7 @@ protected function doDecode(string $encoded): string str_replace(self::URL_REPLACE_TABLE[1], self::URL_REPLACE_TABLE[0], $encoded), strict: true, ))->orElseThrow( - static fn () => new Exception\CouldNotDecodeData(__METHOD__, $encoded), + static fn () => new Exception\CoderCouldNotDecodeData(__METHOD__, $encoded), ); } } diff --git a/src/Coder/Checksum.php b/src/Coder/Checksum.php index 989d19c..802c99e 100644 --- a/src/Coder/Checksum.php +++ b/src/Coder/Checksum.php @@ -13,7 +13,10 @@ */ final class Checksum extends Coder { - public const ALGORITHM = 'crc32'; + /** + * @internal public for testing purposes only + */ + public const DEFAULT_ALGORITHM = 'crc32'; private string $algorithm; private readonly Byter $byter; @@ -23,15 +26,15 @@ public function __construct() $this->byter = new Byter(); } - public function encode(string $decoded, ?string $algorithm = null): string + public function encode(string $decoded, string|null $algorithm = null): string { - $this->algorithm = $algorithm ?? self::ALGORITHM; + $this->algorithm = $algorithm ?? self::DEFAULT_ALGORITHM; return parent::encode($decoded); } - public function decode(string $encoded, ?string $algorithm = null): string + public function decode(string $encoded, string|null $algorithm = null): string { - $this->algorithm = $algorithm ?? self::ALGORITHM; + $this->algorithm = $algorithm ?? self::DEFAULT_ALGORITHM; return parent::decode($encoded); } @@ -46,7 +49,7 @@ protected function doDecode(string $encoded): string $checksumLength = $this->byter->size(hash($this->algorithm, '', binary: true)); [,$decoded] = $this->byter->bite($encoded, -$checksumLength); if ($this->doEncode($decoded) !== $encoded) { - throw new Exception\CouldNotDecodeData(__METHOD__, $encoded); + throw new Exception\CoderCouldNotDecodeData(__METHOD__, $encoded); } return $decoded; } diff --git a/src/Coder/Coder.php b/src/Coder/Coder.php index 865b5a1..a8d5e8c 100644 --- a/src/Coder/Coder.php +++ b/src/Coder/Coder.php @@ -6,17 +6,19 @@ use Throwable; +/** + * @internal shared logic + */ abstract class Coder implements CoderInterface { public function encode(string $decoded): string { try { return $this->doEncode($decoded); + } catch (Exception\CoderCouldNotEncodeData $exception) { + throw $exception; } catch (Throwable $reason) { - if ($reason instanceof Exception\CouldNotEncodeData) { - throw $reason; - } - throw new Exception\CouldNotEncodeData(__METHOD__, $decoded, $reason); + throw new Exception\CoderCouldNotEncodeData(__METHOD__, $decoded, $reason); } } @@ -24,11 +26,10 @@ public function decode(string $encoded): string { try { return $this->doDecode($encoded); + } catch (Exception\CoderCouldNotDecodeData $exception) { + throw $exception; } catch (Throwable $reason) { - if ($reason instanceof Exception\CouldNotDecodeData) { - throw $reason; - } - throw new Exception\CouldNotDecodeData(__METHOD__, $encoded, $reason); + throw new Exception\CoderCouldNotDecodeData(__METHOD__, $encoded, $reason); } } diff --git a/src/Coder/CoderInterface.php b/src/Coder/CoderInterface.php index d1c6d87..675c4d0 100644 --- a/src/Coder/CoderInterface.php +++ b/src/Coder/CoderInterface.php @@ -7,12 +7,12 @@ interface CoderInterface { /** - * @throws Exception\CouldNotEncodeData + * @throws Exception\CoderCouldNotEncodeData */ public function encode(string $decoded): string; /** - * @throws Exception\CouldNotDecodeData + * @throws Exception\CoderCouldNotDecodeData */ public function decode(string $encoded): string; } diff --git a/src/Coder/Exception/CouldNotDecodeData.php b/src/Coder/Exception/CoderCouldNotDecodeData.php similarity index 66% rename from src/Coder/Exception/CouldNotDecodeData.php rename to src/Coder/Exception/CoderCouldNotDecodeData.php index ba935a5..81fce31 100644 --- a/src/Coder/Exception/CouldNotDecodeData.php +++ b/src/Coder/Exception/CoderCouldNotDecodeData.php @@ -9,6 +9,6 @@ /** * @extends CouldNotProcessData */ -final class CouldNotDecodeData extends CouldNotProcessData implements CoderException +final class CoderCouldNotDecodeData extends CouldNotProcessData implements CoderException { } diff --git a/src/Coder/Exception/CouldNotEncodeData.php b/src/Coder/Exception/CoderCouldNotEncodeData.php similarity index 66% rename from src/Coder/Exception/CouldNotEncodeData.php rename to src/Coder/Exception/CoderCouldNotEncodeData.php index e5a362b..d3bf0f3 100644 --- a/src/Coder/Exception/CouldNotEncodeData.php +++ b/src/Coder/Exception/CoderCouldNotEncodeData.php @@ -9,6 +9,6 @@ /** * @extends CouldNotProcessData */ -final class CouldNotEncodeData extends CouldNotProcessData implements CoderException +final class CoderCouldNotEncodeData extends CouldNotProcessData implements CoderException { } diff --git a/src/Coder/Exception/CoderException.php b/src/Coder/Exception/CoderException.php index d56d36f..a65321f 100644 --- a/src/Coder/Exception/CoderException.php +++ b/src/Coder/Exception/CoderException.php @@ -4,8 +4,8 @@ namespace PetrKnap\Binary\Coder\Exception; -use PetrKnap\Binary\Exception\BinaryException; +use PetrKnap\Binary\Exception\Exception; -interface CoderException extends BinaryException +interface CoderException extends Exception { } diff --git a/src/Coder/Hex.php b/src/Coder/Hex.php index 6a510dc..b360d59 100644 --- a/src/Coder/Hex.php +++ b/src/Coder/Hex.php @@ -20,7 +20,7 @@ protected function doEncode(string $decoded): string protected function doDecode(string $encoded): string { return OptionalString::ofFalsable(hex2bin($encoded))->orElseThrow( - static fn () => new Exception\CouldNotDecodeData(__METHOD__, $encoded), + static fn () => new Exception\CoderCouldNotDecodeData(__METHOD__, $encoded), ); } } diff --git a/src/Coder/Zlib.php b/src/Coder/Zlib.php index 8be15fe..8c4cdf4 100644 --- a/src/Coder/Zlib.php +++ b/src/Coder/Zlib.php @@ -15,13 +15,9 @@ final class Zlib extends Coder { use HasRequirements; - public const ENCODING = ZLIB_ENCODING_RAW; - public const LEVEL = -1; - public const MAX_LENGTH = 0; - private int $encoding; - private int $level; - private int $maxLength; + private int|null $level; + private int|null $maxLength; public function __construct() { @@ -36,30 +32,43 @@ functions: [ ); } - public function encode(string $decoded, ?int $encoding = null, ?int $level = null): string + public function encode(string $decoded, int|null $encoding = null, int|null $level = null): string { - $this->encoding = $encoding ?? self::ENCODING; - $this->level = $level ?? self::LEVEL; + $this->encoding = $encoding ?? ZLIB_ENCODING_RAW; + $this->level = $level; return parent::encode($decoded); } - public function decode(string $encoded, ?int $maxLength = null): string + public function decode(string $encoded, int|null $maxLength = null): string { - $this->maxLength = $maxLength ?? self::MAX_LENGTH; + $this->maxLength = $maxLength; return parent::decode($encoded); } protected function doEncode(string $decoded): string { - return OptionalString::ofFalsable(zlib_encode($decoded, $this->encoding, $this->level))->orElseThrow( - static fn () => new Exception\CouldNotEncodeData(__METHOD__, $decoded), + $encodeArgs = [ + 'data' => $decoded, + 'encoding' => $this->encoding, + ]; + if ($this->level !== null) { + $encodeArgs['level'] = $this->level; + } + return OptionalString::ofFalsable(zlib_encode(...$encodeArgs))->orElseThrow( + static fn () => new Exception\CoderCouldNotEncodeData(__METHOD__, $decoded), ); } protected function doDecode(string $encoded): string { - return OptionalString::ofFalsable(zlib_decode($encoded, $this->maxLength))->orElseThrow( - static fn () => new Exception\CouldNotDecodeData(__METHOD__, $encoded), + $decodeArgs = [ + 'data' => $encoded, + ]; + if ($this->maxLength !== null) { + $decodeArgs['max_length'] = $this->maxLength; + } + return OptionalString::ofFalsable(zlib_decode(...$decodeArgs))->orElseThrow( + static fn () => new Exception\CoderCouldNotDecodeData(__METHOD__, $encoded), ); } } diff --git a/src/CoderInterface.php b/src/CoderInterface.php deleted file mode 100644 index 7d6dd36..0000000 --- a/src/CoderInterface.php +++ /dev/null @@ -1,47 +0,0 @@ -decode( + return $this->withData((new Coder\Base64())->decode( $this->data, )); } - public function checksum(?string $algorithm = null): static + public function checksum(string|null $algorithm = null): static { - return static::create($this, (new Coder\Checksum())->decode( + return $this->withData((new Coder\Checksum())->decode( $this->data, algorithm: $algorithm, )); @@ -23,14 +23,14 @@ public function checksum(?string $algorithm = null): static public function hex(): static { - return static::create($this, (new Coder\Hex())->decode( + return $this->withData((new Coder\Hex())->decode( $this->data, )); } - public function zlib(?int $maxLength = null): static + public function zlib(int|null $maxLength = null): static { - return static::create($this, (new Coder\Zlib())->decode( + return $this->withData((new Coder\Zlib())->decode( $this->data, maxLength: $maxLength, )); diff --git a/src/DecoderInterface.php b/src/DecoderInterface.php deleted file mode 100644 index 76fb8b8..0000000 --- a/src/DecoderInterface.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -interface DecoderInterface extends CoderInterface -{ - public function zlib(?int $maxLength = null): static; -} diff --git a/src/Encoder.php b/src/Encoder.php index 3575691..5878e45 100644 --- a/src/Encoder.php +++ b/src/Encoder.php @@ -4,19 +4,19 @@ namespace PetrKnap\Binary; -class Encoder extends Coder implements EncoderInterface +final class Encoder extends Coder { - public function base64(?bool $urlSafe = null): static + public function base64(bool|null $urlSafe = null): static { - return static::create($this, (new Coder\Base64())->encode( + return $this->withData((new Coder\Base64())->encode( $this->data, urlSafe: $urlSafe, )); } - public function checksum(?string $algorithm = null): static + public function checksum(string|null $algorithm = null): static { - return static::create($this, (new Coder\Checksum())->encode( + return $this->withData((new Coder\Checksum())->encode( $this->data, algorithm: $algorithm, )); @@ -24,14 +24,14 @@ public function checksum(?string $algorithm = null): static public function hex(): static { - return static::create($this, (new Coder\Hex())->encode( + return $this->withData((new Coder\Hex())->encode( $this->data, )); } - public function zlib(?int $encoding = null, ?int $level = null): static + public function zlib(int|null $encoding = null, int|null $level = null): static { - return static::create($this, (new Coder\Zlib())->encode( + return $this->withData((new Coder\Zlib())->encode( $this->data, encoding: $encoding, level: $level, diff --git a/src/EncoderInterface.php b/src/EncoderInterface.php deleted file mode 100644 index 2f85f8e..0000000 --- a/src/EncoderInterface.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -interface EncoderInterface extends CoderInterface -{ - public function base64(?bool $urlSafe = null): static; - - public function zlib(?int $encoding = null, ?int $level = null): static; -} diff --git a/src/Exception/CouldNotBiteData.php b/src/Exception/ByterCouldNotBiteData.php similarity index 66% rename from src/Exception/CouldNotBiteData.php rename to src/Exception/ByterCouldNotBiteData.php index 5836611..e9c7067 100644 --- a/src/Exception/CouldNotBiteData.php +++ b/src/Exception/ByterCouldNotBiteData.php @@ -9,6 +9,6 @@ /** * @extends CouldNotProcessData */ -final class CouldNotBiteData extends CouldNotProcessData implements ByterException +final class ByterCouldNotBiteData extends CouldNotProcessData implements ByterException { } diff --git a/src/Exception/ByterException.php b/src/Exception/ByterException.php index 080c7ae..7d52ab8 100644 --- a/src/Exception/ByterException.php +++ b/src/Exception/ByterException.php @@ -4,6 +4,6 @@ namespace PetrKnap\Binary\Exception; -interface ByterException extends BinaryException +interface ByterException extends Exception { } diff --git a/src/Exception/BinaryException.php b/src/Exception/Exception.php similarity index 55% rename from src/Exception/BinaryException.php rename to src/Exception/Exception.php index 839f4fe..60eab32 100644 --- a/src/Exception/BinaryException.php +++ b/src/Exception/Exception.php @@ -6,6 +6,9 @@ use Throwable; -interface BinaryException extends Throwable +/** + * @internal root exception + */ +interface Exception extends Throwable { } diff --git a/src/Serializer.php b/src/Serializer.php index fa03b75..9f3686a 100644 --- a/src/Serializer.php +++ b/src/Serializer.php @@ -8,14 +8,14 @@ * @see Coder\Zlib * @see Serializer\Php */ -class Serializer extends Serializer\Serializer +final class Serializer extends Serializer\Serializer { protected readonly Coder\CoderInterface $coder; protected readonly Serializer\SerializerInterface $serializer; public function __construct( - ?Coder\CoderInterface $coder = null, - ?Serializer\SerializerInterface $serializer = null, + Coder\CoderInterface|null $coder = null, + Serializer\SerializerInterface|null $serializer = null, ) { $this->coder = $coder ?? new Coder\Zlib(); $this->serializer = $serializer ?? new Serializer\Php(); diff --git a/src/Serializer/Exception/CouldNotSerializeData.php b/src/Serializer/Exception/SerializerCouldNotSerializeData.php similarity index 64% rename from src/Serializer/Exception/CouldNotSerializeData.php rename to src/Serializer/Exception/SerializerCouldNotSerializeData.php index 083fd45..0f32668 100644 --- a/src/Serializer/Exception/CouldNotSerializeData.php +++ b/src/Serializer/Exception/SerializerCouldNotSerializeData.php @@ -9,6 +9,6 @@ /** * @extends CouldNotProcessData */ -final class CouldNotSerializeData extends CouldNotProcessData implements SerializerException +final class SerializerCouldNotSerializeData extends CouldNotProcessData implements SerializerException { } diff --git a/src/Serializer/Exception/CouldNotUnserializeData.php b/src/Serializer/Exception/SerializerCouldNotUnserializeData.php similarity index 63% rename from src/Serializer/Exception/CouldNotUnserializeData.php rename to src/Serializer/Exception/SerializerCouldNotUnserializeData.php index 3074ea7..91475c9 100644 --- a/src/Serializer/Exception/CouldNotUnserializeData.php +++ b/src/Serializer/Exception/SerializerCouldNotUnserializeData.php @@ -9,6 +9,6 @@ /** * @extends CouldNotProcessData */ -final class CouldNotUnserializeData extends CouldNotProcessData implements SerializerException +final class SerializerCouldNotUnserializeData extends CouldNotProcessData implements SerializerException { } diff --git a/src/Serializer/Exception/SerializerException.php b/src/Serializer/Exception/SerializerException.php index 8b6d769..ec3ebea 100644 --- a/src/Serializer/Exception/SerializerException.php +++ b/src/Serializer/Exception/SerializerException.php @@ -4,8 +4,8 @@ namespace PetrKnap\Binary\Serializer\Exception; -use PetrKnap\Binary\Exception\BinaryException; +use PetrKnap\Binary\Exception\Exception; -interface SerializerException extends BinaryException +interface SerializerException extends Exception { } diff --git a/src/Serializer/Igbinary.php b/src/Serializer/Igbinary.php index 2a5102f..0a3c6db 100644 --- a/src/Serializer/Igbinary.php +++ b/src/Serializer/Igbinary.php @@ -29,14 +29,14 @@ functions: [ protected function doSerialize(mixed $serializable): string { return OptionalString::ofFalsable(igbinary_serialize($serializable) ?? false)->orElseThrow( - static fn () => new Exception\CouldNotSerializeData(__METHOD__, $serializable), + static fn () => new Exception\SerializerCouldNotSerializeData(__METHOD__, $serializable), ); } protected function doUnserialize(string $serialized): mixed { return Optional::ofFalsable(igbinary_unserialize($serialized) ?? false)->orElseThrow( - static fn () => new Exception\CouldNotUnserializeData(__METHOD__, $serialized), + static fn () => new Exception\SerializerCouldNotUnserializeData(__METHOD__, $serialized), ); } } diff --git a/src/Serializer/OneWaySelfSerializerInterface.php b/src/Serializer/OneWaySelfSerializerInterface.php index f72c2b5..c361bb7 100644 --- a/src/Serializer/OneWaySelfSerializerInterface.php +++ b/src/Serializer/OneWaySelfSerializerInterface.php @@ -9,7 +9,7 @@ interface OneWaySelfSerializerInterface /** * @return string binary representation of this instance * - * @throws Exception\CouldNotSerializeData + * @throws Exception\SerializerCouldNotSerializeData */ public function toBinary(): string; } diff --git a/src/Serializer/Php.php b/src/Serializer/Php.php index 7ab95ae..b101e21 100644 --- a/src/Serializer/Php.php +++ b/src/Serializer/Php.php @@ -20,7 +20,7 @@ protected function doSerialize(mixed $serializable): string protected function doUnserialize(string $serialized): mixed { return Optional::ofFalsable(unserialize($serialized))->orElseThrow( - static fn () => new Exception\CouldNotUnserializeData(__METHOD__, $serialized), + static fn () => new Exception\SerializerCouldNotUnserializeData(__METHOD__, $serialized), ); } } diff --git a/src/Serializer/SelfSerializerInterface.php b/src/Serializer/SelfSerializerInterface.php index 2926aaa..6fc3da9 100644 --- a/src/Serializer/SelfSerializerInterface.php +++ b/src/Serializer/SelfSerializerInterface.php @@ -9,7 +9,7 @@ interface SelfSerializerInterface extends OneWaySelfSerializerInterface /** * @param string $data binary representation of an instance * - * @throws Exception\CouldNotUnserializeData + * @throws Exception\SerializerCouldNotUnserializeData */ public static function fromBinary(string $data): self; } diff --git a/src/Serializer/Serializer.php b/src/Serializer/Serializer.php index fd42da0..dc04275 100644 --- a/src/Serializer/Serializer.php +++ b/src/Serializer/Serializer.php @@ -6,17 +6,19 @@ use Throwable; +/** + * @internal shared logic + */ abstract class Serializer implements SerializerInterface { public function serialize(mixed $serializable): string { try { return $this->doSerialize($serializable); + } catch (Exception\SerializerCouldNotSerializeData $exception) { + throw $exception; } catch (Throwable $reason) { - if ($reason instanceof Exception\CouldNotSerializeData) { - throw $reason; - } - throw new Exception\CouldNotSerializeData(__METHOD__, $serializable, $reason); + throw new Exception\SerializerCouldNotSerializeData(__METHOD__, $serializable, $reason); } } @@ -24,11 +26,10 @@ public function unserialize(string $serialized): mixed { try { return $this->doUnserialize($serialized); + } catch (Exception\SerializerCouldNotUnserializeData $exception) { + throw $exception; } catch (Throwable $reason) { - if ($reason instanceof Exception\CouldNotUnserializeData) { - throw $reason; - } - throw new Exception\CouldNotUnserializeData(__METHOD__, $serialized, $reason); + throw new Exception\SerializerCouldNotUnserializeData(__METHOD__, $serialized, $reason); } } diff --git a/src/Serializer/SerializerInterface.php b/src/Serializer/SerializerInterface.php index 56b4694..305b79f 100644 --- a/src/Serializer/SerializerInterface.php +++ b/src/Serializer/SerializerInterface.php @@ -7,12 +7,12 @@ interface SerializerInterface { /** - * @throws Exception\CouldNotSerializeData + * @throws Exception\SerializerCouldNotSerializeData */ public function serialize(mixed $serializable): string; /** - * @throws Exception\CouldNotUnserializeData + * @throws Exception\SerializerCouldNotUnserializeData */ public function unserialize(string $serialized): mixed; } diff --git a/tests/BinariableTest.php b/tests/BinariableTest.php index 1df65b7..b90e748 100644 --- a/tests/BinariableTest.php +++ b/tests/BinariableTest.php @@ -5,7 +5,6 @@ namespace PetrKnap\Binary; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\TestCase; final class BinariableTest extends TestCase { @@ -13,7 +12,7 @@ final class BinariableTest extends TestCase public function testNativeConversionWorks(): void { - self::assertSame( + self::assertBinarySame( self::BINARY, (string) self::getInstance(), ); @@ -27,7 +26,7 @@ public function testNativeComparisonWorks(): void #[DataProvider('unionTypeDataProvider')] public function testConversionHelperWorks(BinariableInterface|string $data): void { - self::assertSame( + self::assertBinarySame( self::BINARY, Binary::asBinary($data), ); diff --git a/tests/ByterTest.php b/tests/ByterTest.php index f858e4b..935c6f3 100644 --- a/tests/ByterTest.php +++ b/tests/ByterTest.php @@ -5,7 +5,6 @@ namespace PetrKnap\Binary; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\TestCase; final class ByterTest extends TestCase { @@ -31,7 +30,7 @@ public static function dataBitesData(): array public function testBiteThrowsWhenThereIsNotEnoughData(): void { - self::expectException(Exception\CouldNotBiteData::class); + self::expectException(Exception\ByterCouldNotBiteData::class); $data = self::getData(); $byter = new Byter(); @@ -43,7 +42,7 @@ public function testBiteThrowsWhenThereIsNotEnoughData(): void public function testUnbitesBites(): void { - self::assertSame( + self::assertBinarySame( self::getData(), (new Byter())->unbite(hex2bin('0102'), hex2bin('030405')), ); diff --git a/tests/Coder/Base64Test.php b/tests/Coder/Base64Test.php index d021e59..7b0af36 100644 --- a/tests/Coder/Base64Test.php +++ b/tests/Coder/Base64Test.php @@ -20,7 +20,7 @@ public static function data(): array #[DataProvider('data')] public function testEncodes(string $decoded, string $encoded, bool $urlSafe): void { - self::assertSame( + self::assertBinarySame( $encoded, (new Base64())->encode( $decoded, @@ -32,7 +32,7 @@ public function testEncodes(string $decoded, string $encoded, bool $urlSafe): vo #[DataProvider('data')] public function testDecodes(string $decoded, string $encoded): void { - self::assertSame( + self::assertBinarySame( $decoded, (new Base64())->decode( $encoded, @@ -43,7 +43,7 @@ public function testDecodes(string $decoded, string $encoded): void #[DataProvider('dataDecodeThrows')] public function testDecodeThrows(string $data): void { - self::expectException(Exception\CouldNotDecodeData::class); + self::expectException(Exception\CoderCouldNotDecodeData::class); (new Base64())->decode( $data, diff --git a/tests/Coder/ChecksumTest.php b/tests/Coder/ChecksumTest.php index d2f6c1e..14ef879 100644 --- a/tests/Coder/ChecksumTest.php +++ b/tests/Coder/ChecksumTest.php @@ -4,7 +4,6 @@ namespace PetrKnap\Binary\Coder; -use PetrKnap\Shorts\Exception\MissingRequirement; use PHPUnit\Framework\Attributes\DataProvider; final class ChecksumTest extends CoderTestCase @@ -21,9 +20,9 @@ public static function data(): array #[DataProvider('data')] public function testEncodes(string $decoded, string $encoded, string $algorithm): void { - self::assertSame( + self::assertBinarySame( $encoded, - self::getChecksum()->encode( + (new Checksum())->encode( $decoded, algorithm: $algorithm, ), @@ -33,9 +32,9 @@ public function testEncodes(string $decoded, string $encoded, string $algorithm) #[DataProvider('dataEncodeThrows')] public function testEncodeThrows(string $algorithm): void { - self::expectException(Exception\CouldNotEncodeData::class); + self::expectException(Exception\CoderCouldNotEncodeData::class); - self::getChecksum()->encode( + (new Checksum())->encode( self::getDecodedData(), algorithm: $algorithm, ); @@ -51,9 +50,9 @@ public static function dataEncodeThrows(): array #[DataProvider('data')] public function testDecodes(string $decoded, string $encoded, string $algorithm): void { - self::assertSame( + self::assertBinarySame( $decoded, - self::getChecksum()->decode( + (new Checksum())->decode( $encoded, algorithm: $algorithm, ), @@ -63,9 +62,9 @@ public function testDecodes(string $decoded, string $encoded, string $algorithm) #[DataProvider('dataDecodeThrows')] public function testDecodeThrows(string $data, string $algorithm): void { - self::expectException(Exception\CouldNotDecodeData::class); + self::expectException(Exception\CoderCouldNotDecodeData::class); - self::getChecksum()->decode( + (new Checksum())->decode( $data, algorithm: $algorithm, ); @@ -75,18 +74,9 @@ public static function dataDecodeThrows(): array { return [ 'wrong algorithm' => [self::getEncodedData(), '?'], - 'short data' => ['?', Checksum::ALGORITHM], - 'wrong data' => [self::getDecodedData(), Checksum::ALGORITHM], - 'wrong checksum' => ['?' . self::getEncodedData(), Checksum::ALGORITHM], + 'short data' => ['?', Checksum::DEFAULT_ALGORITHM], + 'wrong data' => [self::getDecodedData(), Checksum::DEFAULT_ALGORITHM], + 'wrong checksum' => ['?' . self::getEncodedData(), Checksum::DEFAULT_ALGORITHM], ]; } - - private static function getChecksum(): Checksum - { - try { - return new Checksum(); - } catch (MissingRequirement $reason) { - self::markTestSkipped($reason->getMessage()); - } - } } diff --git a/tests/Coder/CoderTestCase.php b/tests/Coder/CoderTestCase.php index b8623c3..710152f 100644 --- a/tests/Coder/CoderTestCase.php +++ b/tests/Coder/CoderTestCase.php @@ -5,17 +5,25 @@ namespace PetrKnap\Binary\Coder; use LogicException; -use PHPUnit\Framework\TestCase; +use PetrKnap\Binary\DecoderTest; +use PetrKnap\Binary\EncoderTest; +use PetrKnap\Binary\TestCase; abstract class CoderTestCase extends TestCase { - public const DATA_BASE64 = '2jmj7l5rSw0yVb/vlWAYkK/YBwnaOaPuXmtLDTJVv++VYBiQr9gHCdo5o+5ea0sNMlW/75VgGJCv2AcJ'; + protected const DATA_BASE64 = '2jmj7l5rSw0yVb/vlWAYkK/YBwnaOaPuXmtLDTJVv++VYBiQr9gHCdo5o+5ea0sNMlW/75VgGJCv2AcJ'; + /** + * @internal reused in {@see EncoderTest} and {@see DecoderTest} + */ public static function getDecodedData(): string { return base64_decode(self::DATA_BASE64); } + /** + * @internal reused in {@see EncoderTest} and {@see DecoderTest} + */ public static function getEncodedData(): string { foreach (static::data() as $data) { diff --git a/tests/Coder/HexTest.php b/tests/Coder/HexTest.php index 9d73b23..150ab00 100644 --- a/tests/Coder/HexTest.php +++ b/tests/Coder/HexTest.php @@ -21,7 +21,7 @@ public static function data(): array #[DataProvider('data')] public function testEncodes(string $decoded, string $encoded): void { - self::assertSame( + self::assertBinarySame( $encoded, (new Hex())->encode( $decoded, @@ -32,7 +32,7 @@ public function testEncodes(string $decoded, string $encoded): void #[DataProvider('data')] public function testDecodes(string $decoded, string $encoded): void { - self::assertSame( + self::assertBinarySame( $decoded, (new Hex())->decode( $encoded, @@ -43,7 +43,7 @@ public function testDecodes(string $decoded, string $encoded): void #[DataProvider('dataDecodeThrows')] public function testDecodeThrows(string $data): void { - self::expectException(Exception\CouldNotDecodeData::class); + self::expectException(Exception\CoderCouldNotDecodeData::class); (new Hex())->decode( $data, diff --git a/tests/Coder/NoCoderTest.php b/tests/Coder/NoCoderTest.php index dc9782f..0017115 100644 --- a/tests/Coder/NoCoderTest.php +++ b/tests/Coder/NoCoderTest.php @@ -16,7 +16,7 @@ public static function data(): array #[DataProvider('data')] public function testEncodes(string $data): void { - self::assertSame( + self::assertBinarySame( $data, (new NoCoder())->encode($data), ); @@ -25,7 +25,7 @@ public function testEncodes(string $data): void #[DataProvider('data')] public function testDecodes(string $data): void { - self::assertSame( + self::assertBinarySame( $data, (new NoCoder())->decode($data), ); diff --git a/tests/Coder/ZlibTest.php b/tests/Coder/ZlibTest.php index e6c305b..c44f84d 100644 --- a/tests/Coder/ZlibTest.php +++ b/tests/Coder/ZlibTest.php @@ -22,9 +22,9 @@ public static function data(): array #[DataProvider('data')] public function testEncodes(string $decoded, string $encoded, int $encoding): void { - self::assertSame( + self::assertBinarySame( $encoded, - self::getZlib()->encode( + (new Zlib())->encode( $decoded, encoding: $encoding, ), @@ -32,11 +32,11 @@ public function testEncodes(string $decoded, string $encoded, int $encoding): vo } #[DataProvider('dataEncodeThrows')] - public function testEncodeThrows(?int $encoding, ?int $level): void + public function testEncodeThrows(int|null $encoding, int|null $level): void { - self::expectException(Exception\CouldNotEncodeData::class); + self::expectException(Exception\CoderCouldNotEncodeData::class); - self::getZlib()->encode( + (new Zlib())->encode( self::getDecodedData(), encoding: $encoding, level: $level, @@ -54,20 +54,20 @@ public static function dataEncodeThrows(): array #[DataProvider('data')] public function testDecodes(string $decoded, string $encoded): void { - self::assertSame( + self::assertBinarySame( $decoded, - self::getZlib()->decode( + (new Zlib())->decode( $encoded, ), ); } #[DataProvider('dataDecodeThrows')] - public function testDecodeThrows(string $data, ?int $maxLength): void + public function testDecodeThrows(string $data, int|null $maxLength): void { - self::expectException(Exception\CouldNotDecodeData::class); + self::expectException(Exception\CoderCouldNotDecodeData::class); - self::getZlib()->decode( + (new Zlib())->decode( $data, maxLength: $maxLength, ); @@ -80,13 +80,4 @@ public static function dataDecodeThrows(): array 'wrong maximal length' => [base64_decode('AwA='), -1], ]; } - - private static function getZlib(): Zlib - { - try { - return new Zlib(); - } catch (MissingRequirement $reason) { - self::markTestSkipped($reason->getMessage()); - } - } } diff --git a/tests/DecoderTest.php b/tests/DecoderTest.php index 57ea075..56b0948 100644 --- a/tests/DecoderTest.php +++ b/tests/DecoderTest.php @@ -4,39 +4,37 @@ namespace PetrKnap\Binary; -use PHPUnit\Framework\TestCase; - final class DecoderTest extends TestCase { public function testDecodesBase64(): void { - self::assertSame( + self::assertBinarySame( Coder\Base64Test::getDecodedData(), - (new Decoder(Coder\Base64Test::getEncodedData()))->base64()->getData(), + (new Decoder(Coder\Base64Test::getEncodedData()))->base64()->data, ); } public function testDecodesChecksum(): void { - self::assertSame( + self::assertBinarySame( Coder\ChecksumTest::getDecodedData(), - (new Decoder(Coder\ChecksumTest::getEncodedData()))->checksum()->getData(), + (new Decoder(Coder\ChecksumTest::getEncodedData()))->checksum()->data, ); } public function testDecodesHex(): void { - self::assertSame( + self::assertBinarySame( Coder\HexTest::getDecodedData(), - (new Decoder(Coder\HexTest::getEncodedData()))->hex()->getData(), + (new Decoder(Coder\HexTest::getEncodedData()))->hex()->data, ); } public function testDecodesZlib(): void { - self::assertSame( + self::assertBinarySame( Coder\ZlibTest::getDecodedData(), - (new Decoder(Coder\ZlibTest::getEncodedData()))->zlib()->getData(), + (new Decoder(Coder\ZlibTest::getEncodedData()))->zlib()->data, ); } } diff --git a/tests/EncoderTest.php b/tests/EncoderTest.php index cc1be0a..9d64a7b 100644 --- a/tests/EncoderTest.php +++ b/tests/EncoderTest.php @@ -4,39 +4,37 @@ namespace PetrKnap\Binary; -use PHPUnit\Framework\TestCase; - final class EncoderTest extends TestCase { public function testEncodesBase64(): void { - self::assertSame( + self::assertBinarySame( Coder\Base64Test::getEncodedData(), - (new Encoder(Coder\Base64Test::getDecodedData()))->base64()->getData(), + (new Encoder(Coder\Base64Test::getDecodedData()))->base64()->data, ); } public function testEncodesChecksum(): void { - self::assertSame( + self::assertBinarySame( Coder\ChecksumTest::getEncodedData(), - (new Encoder(Coder\ChecksumTest::getDecodedData()))->checksum()->getData(), + (new Encoder(Coder\ChecksumTest::getDecodedData()))->checksum()->data, ); } public function testEncodesHex(): void { - self::assertSame( + self::assertBinarySame( Coder\HexTest::getEncodedData(), - (new Encoder(Coder\HexTest::getDecodedData()))->hex()->getData(), + (new Encoder(Coder\HexTest::getDecodedData()))->hex()->data, ); } public function testEncodesZlib(): void { - self::assertSame( + self::assertBinarySame( Coder\ZlibTest::getEncodedData(), - (new Encoder(Coder\ZlibTest::getDecodedData()))->zlib()->getData(), + (new Encoder(Coder\ZlibTest::getDecodedData()))->zlib()->data, ); } } diff --git a/tests/Serializer/SelfSerializerTest.php b/tests/Serializer/SelfSerializerTest.php index 536f0f7..88c3841 100644 --- a/tests/Serializer/SelfSerializerTest.php +++ b/tests/Serializer/SelfSerializerTest.php @@ -4,23 +4,53 @@ namespace PetrKnap\Binary\Serializer; -use PHPUnit\Framework\TestCase; +use PetrKnap\Binary\TestCase; +use stdClass; final class SelfSerializerTest extends TestCase { + private const SERIALIZED_INSTANCE_B64 = 'S7QysarOtDKwzrQyBGN/KwsrpeKSFOecxOJiJStDq+piK2MrpbT8fCVrMCspsUjJujbTygjINTQxtVLy3mK0cdW5LUYbgJgpyTm7Xptbe+mjSSLP5xx5lKSq7bz6VZJ2svbSLX9qVLMNtDU3epzcJbZkz41Td454nazuvngs9Pk2iVyGpG0qz99U5ea9Xdqv1mkzv/hJ4KRV2z6/Cve8dfKW9/Y/KwPPml24dudFYdH0m0+D1fM+ro+sfHxFVt/XO9W5Njo4jNeNTXUBc8/av2uyGZWAHjG29rOuBQA='; + public function testSerializationWorks(): void { - self::assertEquals( - SelfSerializingDataObject::BINARY_B64, - base64_encode(SelfSerializingDataObject::getInstance()->toBinary()), + self::assertBinarySame( + base64_decode(self::SERIALIZED_INSTANCE_B64), + self::getInstance()->toBinary(), ); } public function testUnserializationWorks(): void { self::assertEquals( - SelfSerializingDataObject::getInstance(), - SelfSerializingDataObject::fromBinary(base64_decode(SelfSerializingDataObject::BINARY_B64)), + self::getInstance(), + Some\SelfSerializer::fromBinary(base64_decode(self::SERIALIZED_INSTANCE_B64)), ); } + + private static function getInstance(): SelfSerializerInterface + { + $stdClass = new stdClass(); + $stdClass->foo = 'bar'; + + $instance = new Some\SelfSerializer( + 1, + $stdClass, + new Some\SelfSerializer( + 2, + $stdClass, + new Some\SelfSerializer( + 3, + $stdClass, + null, + 'value', + ), + null, + ), + null, + ); + + $instance->innerInstance->innerInstance->variable = 'changed'; + + return $instance; + } } diff --git a/tests/Serializer/SelfSerializingDataObject.php b/tests/Serializer/SelfSerializingDataObject.php deleted file mode 100644 index 94ff32e..0000000 --- a/tests/Serializer/SelfSerializingDataObject.php +++ /dev/null @@ -1,58 +0,0 @@ -innerInstance = match (is_string($innerInstance)) { - true => self::fromBinary($innerInstance), - false => $innerInstance, - }; - $this->referencesToConstructorArgs = [ - $this->scalar, - $this->serializable, - $this->innerInstance, - &$this->variable, - ]; - } - - public static function getInstance(): self - { - $stdClass = new stdClass(); - $stdClass->foo = 'bar'; - - $instance = new self( - 1, - $stdClass, - new self( - 2, - $stdClass, - new self( - 3, - $stdClass, - variable: 'value', - ), - ), - ); - - $instance->innerInstance->innerInstance->variable = 'changed'; - - return $instance; - } -} diff --git a/tests/Serializer/SerializerTestCase.php b/tests/Serializer/SerializerTestCase.php index 8559156..2ff4a3c 100644 --- a/tests/Serializer/SerializerTestCase.php +++ b/tests/Serializer/SerializerTestCase.php @@ -4,39 +4,22 @@ namespace PetrKnap\Binary\Serializer; -use PHPUnit\Framework\TestCase; +use PetrKnap\Binary\TestCase; use stdClass; abstract class SerializerTestCase extends TestCase { - public static function getSerializable(): stdClass - { - $serializable = new stdClass(); - $serializable->array = []; - $serializable->binary = 0b0; - $serializable->float = .0; - $serializable->int = 0; - $serializable->null = null; - $serializable->string = ''; - - return $serializable; - } - - abstract public static function getSerialized(): string; - - abstract public static function getSerializer(): SerializerInterface; - public function testSerializesSerializable(): void { - self::assertEquals( + self::assertBinarySame( static::getSerialized(), - static::getSerializer()->serialize(static::getSerializable()), + static::getSerializer()->serialize(self::getSerializable()), ); } public function testSerializeThrowsOnNonserializable(): void { - self::expectException(Exception\CouldNotSerializeData::class); + self::expectException(Exception\SerializerCouldNotSerializeData::class); static::getSerializer()->serialize(new class () { }); @@ -45,15 +28,32 @@ public function testSerializeThrowsOnNonserializable(): void public function testUnserializesSerialized(): void { self::assertEquals( - static::getSerializable(), + self::getSerializable(), static::getSerializer()->unserialize(static::getSerialized()), ); } public function testSerializeThrowsOnNonserialized(): void { - self::expectException(Exception\CouldNotUnserializeData::class); + self::expectException(Exception\SerializerCouldNotUnserializeData::class); static::getSerializer()->unserialize('?' . static::getSerialized()); } + + private static function getSerializable(): stdClass + { + $serializable = new stdClass(); + $serializable->array = []; + $serializable->binary = 0b0; + $serializable->float = .0; + $serializable->int = 0; + $serializable->null = null; + $serializable->string = ''; + + return $serializable; + } + + abstract protected static function getSerialized(): string; + + abstract protected static function getSerializer(): SerializerInterface; } diff --git a/tests/Serializer/Some/SelfSerializer.php b/tests/Serializer/Some/SelfSerializer.php new file mode 100644 index 0000000..c6242c7 --- /dev/null +++ b/tests/Serializer/Some/SelfSerializer.php @@ -0,0 +1,34 @@ +innerInstance = match (is_string($innerInstance)) { + true => self::fromBinary($innerInstance), + false => $innerInstance, + }; + $this->referencesToConstructorArgs = [ + $this->scalar, + $this->serializable, + $this->innerInstance, + &$this->variable, + ]; + } +} diff --git a/tests/SerializerTest.php b/tests/SerializerTest.php index e78b10d..7882465 100644 --- a/tests/SerializerTest.php +++ b/tests/SerializerTest.php @@ -4,21 +4,15 @@ namespace PetrKnap\Binary; -use PetrKnap\Shorts\Exception\MissingRequirement; - final class SerializerTest extends Serializer\SerializerTestCase { - public static function getSerialized(): string + protected static function getSerialized(): string { return base64_decode('NYtJCoAwEAT/0i8IuCA9R+/6hhFRAiFCJh4k+HdDwGNVV6+cCMv7HNQMHFmMA6Ep6QNROpbXqsbmo6aqPJ205AiXZsjeuCN8zP/aE/EOAbJI+1pOPp6o4AjI+wE='); } - public static function getSerializer(): Serializer\SerializerInterface + protected static function getSerializer(): Serializer\SerializerInterface { - try { - return new Serializer(); - } catch (MissingRequirement $reason) { - self::markTestSkipped($reason->getMessage()); - } + return new Serializer(); } } diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..74ef65f --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,18 @@ +