Skip to content

Commit 8a3e38d

Browse files
authored
Merge pull request #5 from petrknap/refactor
Refactoring
2 parents 39adf3d + f0f0472 commit 8a3e38d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+919
-716
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Library for work with binaries
1+
# Library for work with binary data and objects
22

3-
Library for basic work with binary data in PHP.
4-
See the examples below for more information, or check out [`CoderInterface`](./src/CoderInterface.php) and [`SerializerInterface`](./src/SerializerInterface.php).
3+
Simple library for work with binary data and objects in PHP.
4+
See the examples below for more information, or check out [`Encoder`](./src/Encoder.php), [`Decoder`](./src/Decoder.php) and [`Serializer`](./src/Serializer.php).
55

66
```php
77
use PetrKnap\Binary\Binary;

composer.json

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"allow-plugins": false,
1515
"sort-packages": true
1616
},
17-
"description": "Library for work with binaries",
17+
"description": "Library for work with binary data and objects",
1818
"funding": [
1919
{
2020
"type": "other",
@@ -23,21 +23,23 @@
2323
],
2424
"homepage": "https://github.com/petrknap/php-binary",
2525
"keywords": [
26-
"binary",
27-
"helper",
2826
"base64",
29-
"encoder",
30-
"decoder",
27+
"binary",
3128
"checksum",
32-
"zlib",
3329
"compression",
34-
"decompression"
30+
"decoder",
31+
"decompression",
32+
"encoder",
33+
"helper",
34+
"igbinary",
35+
"serializer",
36+
"zlib"
3537
],
3638
"license": "LGPL-3.0-or-later",
3739
"name": "petrknap/binary",
3840
"require": {
39-
"petrknap/shorts": "^1.4",
40-
"php": ">=8.1"
41+
"php": ">=8.1",
42+
"petrknap/shorts": "^1.5"
4143
},
4244
"require-dev": {
4345
"ext-mbstring": "*",

src/Binary.php

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,11 @@ public static function decode(string $data): Decoder
1818

1919
public static function serialize(mixed $data): string
2020
{
21-
return self::getSerializer()->serialize(serializable: $data);
21+
return (new Serializer())->serialize(serializable: $data);
2222
}
2323

2424
public static function unserialize(string $data): mixed
2525
{
26-
return self::getSerializer()->unserialize(serialized: $data);
27-
}
28-
29-
private static function getSerializer(): Serializer
30-
{
31-
static $serializer;
32-
return $serializer ??= new Serializer(
33-
new Encoder(),
34-
new Decoder(),
35-
);
26+
return (new Serializer())->unserialize(serialized: $data);
3627
}
3728
}

src/Coder.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@
44

55
namespace PetrKnap\Binary;
66

7+
use PetrKnap\Shorts\Exception;
8+
79
/**
10+
* @internal please use subclass
11+
*
812
* @phpstan-consistent-constructor override {@see self::create()} if not
913
*
10-
* @implements CoderInterface<Exception\CouldNotCodeData>
14+
* @implements CoderInterface<Exception\CouldNotProcessData>
1115
*/
1216
abstract class Coder implements CoderInterface
1317
{
14-
protected const BASE64_URL_SAFE_MAP = [
15-
['+', '/', '='],
16-
['-', '_', ''],
17-
];
18-
1918
public function __construct(
2019
protected readonly string $data = '',
2120
) {

src/Coder/Base64.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PetrKnap\Binary\Coder;
6+
7+
/**
8+
* @see base64_encode()
9+
* @see base64_decode()
10+
*/
11+
final class Base64 extends Coder
12+
{
13+
public const URL_SAFE = false;
14+
private const URL_REPLACE_TABLE = [
15+
['+', '/', '='],
16+
['-', '_', ''],
17+
];
18+
19+
private bool $urlSafe;
20+
21+
public function encode(string $decoded, ?bool $urlSafe = null): string
22+
{
23+
$this->urlSafe = $urlSafe ?? self::URL_SAFE;
24+
return parent::encode($decoded);
25+
}
26+
27+
protected function doEncode(string $decoded): string
28+
{
29+
$encoded = base64_encode($decoded);
30+
if ($this->urlSafe) {
31+
$encoded = str_replace(self::URL_REPLACE_TABLE[0], self::URL_REPLACE_TABLE[1], $encoded);
32+
}
33+
return $encoded;
34+
}
35+
36+
protected function doDecode(string $encoded): string
37+
{
38+
$decoded = base64_decode(
39+
str_replace(self::URL_REPLACE_TABLE[1], self::URL_REPLACE_TABLE[0], $encoded),
40+
strict: true,
41+
);
42+
if ($decoded === false) {
43+
throw new Exception\CouldNotDecodeData(__METHOD__, $encoded);
44+
}
45+
return $decoded;
46+
}
47+
}

src/Coder/Checksum.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PetrKnap\Binary\Coder;
6+
7+
use PetrKnap\Binary\HasRequirementsTrait;
8+
use PetrKnap\Shorts\HasRequirements;
9+
10+
/**
11+
* @see hash()
12+
*
13+
* @link https://en.wikipedia.org/wiki/Checksum
14+
*/
15+
final class Checksum extends Coder implements HasRequirements
16+
{
17+
use HasRequirementsTrait;
18+
19+
public const ALGORITHM = 'crc32';
20+
private const REQUIRED_FUNCTIONS = [
21+
'mb_strlen',
22+
'mb_strcut',
23+
];
24+
25+
private string $algorithm;
26+
27+
public function __construct()
28+
{
29+
self::checkRequirements();
30+
}
31+
32+
public function encode(string $decoded, ?string $algorithm = null): string
33+
{
34+
$this->algorithm = $algorithm ?? self::ALGORITHM;
35+
return parent::encode($decoded);
36+
}
37+
38+
public function decode(string $encoded, ?string $algorithm = null): string
39+
{
40+
$this->algorithm = $algorithm ?? self::ALGORITHM;
41+
return parent::decode($encoded);
42+
}
43+
44+
protected function doEncode(string $decoded): string
45+
{
46+
$checksum = hash($this->algorithm, $decoded, binary: true);
47+
return $decoded . $checksum;
48+
}
49+
50+
protected function doDecode(string $encoded): string
51+
{
52+
$checksumLength = mb_strlen(hash($this->algorithm, '', binary: true), encoding: '8bit');
53+
$dataLength = mb_strlen($encoded, encoding: '8bit') - $checksumLength;
54+
$decoded = mb_strcut($encoded, 0, $dataLength, encoding: '8bit');
55+
if ($this->doEncode($decoded) !== $encoded) {
56+
throw new Exception\CouldNotDecodeData(__METHOD__, $encoded);
57+
}
58+
return $decoded;
59+
}
60+
}

src/Coder/Coder.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PetrKnap\Binary\Coder;
6+
7+
use Throwable;
8+
9+
abstract class Coder implements CoderInterface
10+
{
11+
public function encode(string $decoded): string
12+
{
13+
try {
14+
return $this->doEncode($decoded);
15+
} catch (Throwable $reason) {
16+
if ($reason instanceof Exception\CouldNotEncodeData) {
17+
throw $reason;
18+
}
19+
throw new Exception\CouldNotEncodeData(__METHOD__, $decoded, $reason);
20+
}
21+
}
22+
23+
public function decode(string $encoded): string
24+
{
25+
try {
26+
return $this->doDecode($encoded);
27+
} catch (Throwable $reason) {
28+
if ($reason instanceof Exception\CouldNotDecodeData) {
29+
throw $reason;
30+
}
31+
throw new Exception\CouldNotDecodeData(__METHOD__, $encoded, $reason);
32+
}
33+
}
34+
35+
/**
36+
* @throws Throwable
37+
*/
38+
abstract protected function doEncode(string $decoded): string;
39+
40+
/**
41+
* @throws Throwable
42+
*/
43+
abstract protected function doDecode(string $encoded): string;
44+
}

src/Coder/CoderInterface.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PetrKnap\Binary\Coder;
6+
7+
interface CoderInterface
8+
{
9+
/**
10+
* @throws Exception\CouldNotEncodeData
11+
*/
12+
public function encode(string $decoded): string;
13+
14+
/**
15+
* @throws Exception\CouldNotDecodeData
16+
*/
17+
public function decode(string $encoded): string;
18+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PetrKnap\Binary\Coder\Exception;
6+
7+
use PetrKnap\Binary\Exception\BinaryException;
8+
9+
interface CoderException extends BinaryException
10+
{
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PetrKnap\Binary\Coder\Exception;
6+
7+
use PetrKnap\Shorts\Exception\CouldNotProcessData;
8+
9+
/**
10+
* @extends CouldNotProcessData<string>
11+
*/
12+
final class CouldNotDecodeData extends CouldNotProcessData implements CoderException
13+
{
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PetrKnap\Binary\Coder\Exception;
6+
7+
use PetrKnap\Shorts\Exception\CouldNotProcessData;
8+
9+
/**
10+
* @extends CouldNotProcessData<string>
11+
*/
12+
final class CouldNotEncodeData extends CouldNotProcessData implements CoderException
13+
{
14+
}

src/Coder/Zlib.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PetrKnap\Binary\Coder;
6+
7+
use PetrKnap\Binary\HasRequirementsTrait;
8+
use PetrKnap\Shorts\HasRequirements;
9+
10+
/**
11+
* @see zlib_encode()
12+
* @see zlib_decode()
13+
*/
14+
final class Zlib extends Coder implements HasRequirements
15+
{
16+
use HasRequirementsTrait;
17+
18+
public const ENCODING = ZLIB_ENCODING_RAW;
19+
public const LEVEL = -1;
20+
public const MAX_LENGTH = 0;
21+
private const REQUIRED_FUNCTIONS = [
22+
'zlib_encode',
23+
'zlib_decode',
24+
];
25+
26+
private int $encoding;
27+
private int $level;
28+
private int $maxLength;
29+
30+
public function encode(string $decoded, ?int $encoding = null, ?int $level = null): string
31+
{
32+
$this->encoding = $encoding ?? self::ENCODING;
33+
$this->level = $level ?? self::LEVEL;
34+
return parent::encode($decoded);
35+
}
36+
37+
public function decode(string $encoded, ?int $maxLength = null): string
38+
{
39+
$this->maxLength = $maxLength ?? self::MAX_LENGTH;
40+
return parent::decode($encoded);
41+
}
42+
43+
protected function doEncode(string $decoded): string
44+
{
45+
$encoded = zlib_encode($decoded, $this->encoding, $this->level);
46+
if ($encoded === false) {
47+
throw new Exception\CouldNotEncodeData(__METHOD__, $decoded);
48+
}
49+
return $encoded;
50+
}
51+
52+
protected function doDecode(string $encoded): string
53+
{
54+
$decoded = zlib_decode($encoded, $this->maxLength);
55+
if ($decoded === false) {
56+
throw new Exception\CouldNotDecodeData(__METHOD__, $encoded);
57+
}
58+
return $decoded;
59+
}
60+
}

0 commit comments

Comments
 (0)