diff --git a/README.md b/README.md index 78a9f21..f420ade 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Simple library for work with binary data and objects in PHP. See the examples below for more information, or check out [`Encoder`](./src/Encoder.php), [`Decoder`](./src/Decoder.php), [`Serializer`](./src/Serializer.php) and [`Byter`](./src/Byter.php). ```php -use PetrKnap\Binary\Binary; +namespace PetrKnap\Binary; $data = base64_decode('hmlpFnFwbchsoQARSibVpfbWVfuwAHLbGxjFl9eC8fiGaWkWcXBtyGyhABFKJtWl9tZV+7AActsbGMWX14Lx+A=='); $encoded = Binary::encode($data)->checksum()->zlib()->base64(urlSafe: true)->getData(); @@ -14,7 +14,7 @@ printf('Data was coded into `%s` %s.', $encoded, $decoded === $data ? 'successfu ``` ```php -use PetrKnap\Binary\Binary; +namespace PetrKnap\Binary; $data = [ 'type' => 'image/png', @@ -27,7 +27,35 @@ printf('Data was serialized into `%s` %s.', base64_encode($serialized), $unseria ``` ```php -use PetrKnap\Binary\Binary; +namespace PetrKnap\Binary; + +class DataObject implements Serializer\SelfSerializerInterface +{ + use Serializer\SelfSerializerTrait; + + public function __construct( + public string $data, + ) { + $this->referencesToConstructorArgs = [ + &$this->data, + ]; + } +} + +$instance = new DataObject('Lorem ipsum dolor sit amet, consectetur adipiscing elit.'); +$instance->data .= ' Duis venenatis ultricies elementum.'; +$binary = $instance->toBinary(); +$binaryFromHelper = Binary::asBinary($instance); + +printf( + 'Data object was serialized into `%s` %s.', + base64_encode($binary), + $binary === $binaryFromHelper && $instance == DataObject::fromBinary($binary) ? 'successfully' : 'unsuccessfully', +); +``` + +```php +namespace PetrKnap\Binary; $data = base64_decode('hmlpFnFwbchsoQARSibVpfbWVfuwAHLbGxjFl9eC8fiGaWkWcXBtyGyhABFKJtWl9tZV+7AActsbGMWX14Lx+A=='); $sha1 = sha1($data, binary: true); diff --git a/src/Binary.php b/src/Binary.php index 3db0c60..f28d3b7 100644 --- a/src/Binary.php +++ b/src/Binary.php @@ -21,7 +21,7 @@ public static function decode(string $data): DecoderInterface */ public static function serialize(mixed $data): string { - return (new Serializer())->serialize(serializable: $data); + return self::serializer()->serialize(serializable: $data); } /** @@ -29,7 +29,18 @@ public static function serialize(mixed $data): string */ public static function unserialize(string $data): mixed { - return (new Serializer())->unserialize(serialized: $data); + return self::serializer()->unserialize(serialized: $data); + } + + /** + * @see Serializer\OneWaySelfSerializerInterface::toBinary() + */ + public static function asBinary(Serializer\OneWaySelfSerializerInterface|string $data): string + { + if ($data instanceof Serializer\OneWaySelfSerializerInterface) { + return $data->toBinary(); + } + return $data; } /** @@ -39,7 +50,7 @@ public static function unserialize(string $data): mixed */ public static function bite(string $data, int $size1, int ...$sizeN): array { - return (new Byter())->bite($data, $size1, ...$sizeN); + return self::byter()->bite($data, $size1, ...$sizeN); } /** @@ -47,6 +58,18 @@ public static function bite(string $data, int $size1, int ...$sizeN): array */ public static function unbite(string $bite1, string ...$biteN): string { - return (new Byter())->unbite($bite1, ...$biteN); + return self::byter()->unbite($bite1, ...$biteN); + } + + private static function serializer(): Serializer + { + static $serializer; + return $serializer ??= new Serializer(); + } + + private static function byter(): Byter + { + static $byter; + return $byter ??= new Byter(); } } diff --git a/src/Serializer/SelfSerializerTrait.php b/src/Serializer/SelfSerializerTrait.php index a171cb8..2a0dc5f 100644 --- a/src/Serializer/SelfSerializerTrait.php +++ b/src/Serializer/SelfSerializerTrait.php @@ -4,7 +4,7 @@ namespace PetrKnap\Binary\Serializer; -use PetrKnap\Binary\Serializer; +use PetrKnap\Binary\Binary; /** * If your {@see self::__construct()} argument is an instance of {@see SelfSerializerInterface} then @@ -19,7 +19,7 @@ trait SelfSerializerTrait public function toBinary(): string { - return (new Serializer())->serialize(array_map( + return Binary::serialize(array_map( static fn (mixed $constructorArg): mixed => match ($constructorArg instanceof SelfSerializerInterface) { true => $constructorArg->toBinary(), false => $constructorArg, @@ -30,6 +30,6 @@ public function toBinary(): string public static function fromBinary(string $data): self { - return new self(...(new Serializer())->unserialize($data)); + return new self(...Binary::unserialize($data)); } } diff --git a/tests/BinariableTest.php b/tests/BinariableTest.php index 4f3ed54..1df65b7 100644 --- a/tests/BinariableTest.php +++ b/tests/BinariableTest.php @@ -4,6 +4,7 @@ namespace PetrKnap\Binary; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; final class BinariableTest extends TestCase @@ -23,16 +24,24 @@ public function testNativeComparisonWorks(): void self::assertTrue(self::BINARY == self::getInstance()); } - public function testUnionTypingWorks(): void + #[DataProvider('unionTypeDataProvider')] + public function testConversionHelperWorks(BinariableInterface|string $data): void { - $function = static fn (BinariableInterface|string $parameter): string => (string) $parameter; - self::assertSame( self::BINARY, - $function(self::getInstance()), + Binary::asBinary($data), ); } + public static function unionTypeDataProvider(): array + { + $instance = self::getInstance(); + return [ + BinariableInterface::class => [$instance], + 'binary' => [$instance->toBinary()], + ]; + } + private static function getInstance(): BinariableInterface { return new class () implements BinariableInterface { diff --git a/tests/ReadmeTest.php b/tests/ReadmeTest.php index 630c23c..3bbe55f 100644 --- a/tests/ReadmeTest.php +++ b/tests/ReadmeTest.php @@ -22,6 +22,7 @@ public static function getExpectedOutputsOfPhpExamples(): iterable return [ 'coder' => 'Data was coded into `a8vMFCssyD2Rs5BB0Evt6tJv10J_b2Aoui0tcXT69aaPP9oIyB-fLeAHAA` successfully.', 'serializer' => 'Data was serialized into `S7QysqoutjKxUiqpLEhVsi62srRSysxNTE/VL8hLB/GBUimJJYkgpoWxlVJngJ87L5cUFwMDA6+nh0sQkGYEYQ42ICkveqQTxCkOcndiWHdO5iVYlYtjiER48o/9Ux7aM7C9Z1qixnnFBCjB4Onq57LOKaFJyboWAA==` successfully.', + 'self-serializer' => 'Data object was serialized into `DckxCsMwDAXQq4jMJbTd6qwdewnjfMoHSw6W1KX07s324NVyK1+W6+blcS/La0yo8PBU2UcfU5whVREXacMcLRA5pe486I32FnTGKs+kywcGq3Eqe0w2ws+GwiJ1XbbfHw==` successfully.', 'byter' => 'Hashes and data was unbitten into `IoPwxcGHZQM0gfF966vHI3kleehoRKHtC32Xh30RDlg5E026hmlpFnFwbchsoQARSibVpfbWVfuwAHLbGxjFl9eC8fiGaWkWcXBtyGyhABFKJtWl9tZV+7AActsbGMWX14Lx+A==` successfully.', ]; }