Skip to content

Commit 6a33f8d

Browse files
committed
Merge remote-tracking branch 'origin/main' into v4.x
2 parents 66cc01f + 0eefe06 commit 6a33f8d

Some content is hidden

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

52 files changed

+479
-385
lines changed

Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ RUN apt-get update \
1212
COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer
1313
# endregion
1414

15+
# region included igbinary
16+
# hadolint ignore=DL3008
17+
RUN pecl install -o -f \
18+
igbinary \
19+
&& docker-php-ext-enable \
20+
igbinary \
21+
;
22+
# endregion
23+
1524
# region included composer-library
1625
WORKDIR /app
1726
COPY . .

composer.json

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
"allow-plugins": false,
1414
"sort-packages": true
1515
},
16+
"conflict": {
17+
"petrknap/xz-utils": "<1|>=2"
18+
},
1619
"description": "Library for work with binary data and objects",
1720
"funding": [
1821
{
@@ -22,6 +25,7 @@
2225
],
2326
"homepage": "https://github.com/petrknap/php-binary",
2427
"keywords": [
28+
"ascii",
2529
"base64",
2630
"binary",
2731
"checksum",
@@ -33,24 +37,28 @@
3337
"hexadecimal",
3438
"igbinary",
3539
"serializer",
36-
"zlib"
40+
"zlib",
41+
"xz"
3742
],
3843
"license": "LGPL-3.0-or-later",
3944
"name": "petrknap/binary",
4045
"require": {
4146
"php": ">=8.1",
42-
"petrknap/shorts": "^2.0|^3.0"
47+
"petrknap/optional": "^3.1",
48+
"petrknap/shorts": "^3.0"
4349
},
4450
"require-dev": {
51+
"ext-igbinary": "*",
4552
"ext-mbstring": "*",
4653
"ext-zlib": "*",
4754
"nunomaduro/phpinsights": "^2.11",
55+
"petrknap/xz-utils": "*",
4856
"phpstan/phpstan": "^1.12",
4957
"phpunit/phpunit": "^10.5",
5058
"squizlabs/php_codesniffer": "^3.7"
5159
},
5260
"scripts": {
53-
"test": "phpunit --colors=always --testdox tests",
61+
"test": "@test-implementation",
5462
"ci-script": [
5563
"@check-implementation",
5664
"@check-requirements",
@@ -67,12 +75,13 @@
6775
"composer outdated \"petrknap/*\" --major-only --strict --ansi --no-interaction"
6876
],
6977
"test-implementation": [
70-
"@test"
78+
"phpunit --colors=always --testdox tests"
7179
]
7280
},
7381
"suggest": {
7482
"ext-igbinary": "Required to serialize data via igbinary",
7583
"ext-mbstring": "Required to bite bytes",
76-
"ext-zlib": "Required to compress data"
84+
"ext-zlib": "Required to compress data",
85+
"petrknap/xz-utils": "Required to compress data"
7786
}
7887
}

src/Binary.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66

77
final class Binary
88
{
9-
public static function encode(string $data): EncoderInterface
9+
public static function encode(string $data): Encoder
1010
{
1111
return new Encoder($data);
1212
}
1313

14-
public static function decode(string $data): DecoderInterface
14+
public static function decode(string $data): Decoder
1515
{
1616
return new Decoder($data);
1717
}

src/Byter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use PetrKnap\Shorts\HasRequirements;
88
use RuntimeException;
99

10-
class Byter
10+
final class Byter
1111
{
1212
use HasRequirements;
1313

@@ -28,15 +28,15 @@ functions: [
2828
*
2929
* @return array<string> bites of specified sizes; and remains, if any
3030
*
31-
* @throws Exception\CouldNotBiteData
31+
* @throws Exception\ByterCouldNotBiteData
3232
*/
3333
public function bite(string $data, int $size1, int ...$sizeN): array
3434
{
3535
$remains = $data;
3636
$bites = [];
3737
foreach ([$size1, ...$sizeN] as $size) {
3838
if (abs($size) > $this->size($remains)) {
39-
throw new Exception\CouldNotBiteData(__METHOD__, $data, new RuntimeException(
39+
throw new Exception\ByterCouldNotBiteData(__METHOD__, $data, new RuntimeException(
4040
'Remains are smaller than bite',
4141
));
4242
}

src/Coder.php

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,60 @@
44

55
namespace PetrKnap\Binary;
66

7-
use PetrKnap\Shorts\Exception;
87
use Stringable;
98

109
/**
11-
* @internal please use subclass
12-
*
13-
* @phpstan-consistent-constructor override {@see self::create()} if not
14-
*
15-
* @implements CoderInterface<Exception\CouldNotProcessData>
10+
* @internal shared logic
1611
*/
17-
abstract class Coder implements CoderInterface, Stringable
12+
abstract class Coder implements Stringable
1813
{
1914
/**
2015
* @param string $data may contain binary data
2116
*/
22-
public function __construct(
17+
final public function __construct(
2318
public readonly string $data = '',
2419
) {
2520
}
2621

27-
public function withData(string $data): static
22+
final public function withData(string $data): static
2823
{
29-
return static::create($this, $data);
24+
return new static($data);
3025
}
3126

3227
/**
33-
* @deprecated use readonly property {@see self::$data}
28+
* @see Coder\Base64
29+
*
30+
* @throws Coder\Exception\CoderException
3431
*/
35-
final public function getData(): string
36-
{
37-
return $this->data;
38-
}
32+
abstract public function base64(): static;
33+
34+
/**
35+
* @see Coder\Checksum
36+
*
37+
* @throws Coder\Exception\CoderException
38+
*/
39+
abstract public function checksum(string|null $algorithm = null): static;
40+
41+
/**
42+
* @see Coder\Hex
43+
*
44+
* @throws Coder\Exception\CoderException
45+
*/
46+
abstract public function hex(): static;
47+
48+
/**
49+
* @see Coder\Xz
50+
*
51+
* @throws Coder\Exception\CoderException
52+
*/
53+
abstract public function xz(): static;
54+
55+
/**
56+
* @see Coder\zlib
57+
*
58+
* @throws Coder\Exception\CoderException
59+
*/
60+
abstract public function zlib(): static;
3961

4062
/**
4163
* @note this is just a helper, this class is not supposed to implement {@see BinariableInterface}
@@ -44,9 +66,4 @@ public function __toString(): string
4466
{
4567
return $this->data;
4668
}
47-
48-
protected static function create(self $coder, string $data): static
49-
{
50-
return new static($data);
51-
}
5269
}

src/Coder/Base64.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,24 @@
44

55
namespace PetrKnap\Binary\Coder;
66

7+
use PetrKnap\Optional\OptionalString;
8+
79
/**
810
* @see base64_encode()
911
* @see base64_decode()
1012
*/
1113
final class Base64 extends Coder
1214
{
13-
public const URL_SAFE = false;
1415
private const URL_REPLACE_TABLE = [
1516
['+', '/', '='],
1617
['-', '_', ''],
1718
];
1819

1920
private bool $urlSafe;
2021

21-
public function encode(string $decoded, ?bool $urlSafe = null): string
22+
public function encode(string $decoded, bool|null $urlSafe = null): string
2223
{
23-
$this->urlSafe = $urlSafe ?? self::URL_SAFE;
24+
$this->urlSafe = $urlSafe ?? false;
2425
return parent::encode($decoded);
2526
}
2627

@@ -35,13 +36,11 @@ protected function doEncode(string $decoded): string
3536

3637
protected function doDecode(string $encoded): string
3738
{
38-
$decoded = base64_decode(
39+
return OptionalString::ofFalsable(base64_decode(
3940
str_replace(self::URL_REPLACE_TABLE[1], self::URL_REPLACE_TABLE[0], $encoded),
4041
strict: true,
42+
))->orElseThrow(
43+
static fn () => new Exception\CoderCouldNotDecodeData(__METHOD__, $encoded),
4144
);
42-
if ($decoded === false) {
43-
throw new Exception\CouldNotDecodeData(__METHOD__, $encoded);
44-
}
45-
return $decoded;
4645
}
4746
}

src/Coder/Checksum.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
*/
1414
final class Checksum extends Coder
1515
{
16-
public const ALGORITHM = 'crc32';
16+
/**
17+
* @internal public for testing purposes only
18+
*/
19+
public const DEFAULT_ALGORITHM = 'crc32';
1720

1821
private string $algorithm;
1922
private readonly Byter $byter;
@@ -23,15 +26,15 @@ public function __construct()
2326
$this->byter = new Byter();
2427
}
2528

26-
public function encode(string $decoded, ?string $algorithm = null): string
29+
public function encode(string $decoded, string|null $algorithm = null): string
2730
{
28-
$this->algorithm = $algorithm ?? self::ALGORITHM;
31+
$this->algorithm = $algorithm ?? self::DEFAULT_ALGORITHM;
2932
return parent::encode($decoded);
3033
}
3134

32-
public function decode(string $encoded, ?string $algorithm = null): string
35+
public function decode(string $encoded, string|null $algorithm = null): string
3336
{
34-
$this->algorithm = $algorithm ?? self::ALGORITHM;
37+
$this->algorithm = $algorithm ?? self::DEFAULT_ALGORITHM;
3538
return parent::decode($encoded);
3639
}
3740

@@ -46,7 +49,7 @@ protected function doDecode(string $encoded): string
4649
$checksumLength = $this->byter->size(hash($this->algorithm, '', binary: true));
4750
[,$decoded] = $this->byter->bite($encoded, -$checksumLength);
4851
if ($this->doEncode($decoded) !== $encoded) {
49-
throw new Exception\CouldNotDecodeData(__METHOD__, $encoded);
52+
throw new Exception\CoderCouldNotDecodeData(__METHOD__, $encoded);
5053
}
5154
return $decoded;
5255
}

src/Coder/Coder.php

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,43 @@
66

77
use Throwable;
88

9+
/**
10+
* @internal shared logic
11+
*/
912
abstract class Coder implements CoderInterface
1013
{
1114
public function encode(string $decoded): string
1215
{
1316
try {
14-
return $this->doEncode($decoded);
17+
return @$this->doEncode($decoded);
18+
} catch (Exception\CoderCouldNotEncodeData $exception) {
19+
throw $exception;
1520
} catch (Throwable $reason) {
16-
if ($reason instanceof Exception\CouldNotEncodeData) {
17-
throw $reason;
18-
}
19-
throw new Exception\CouldNotEncodeData(__METHOD__, $decoded, $reason);
21+
throw new Exception\CoderCouldNotEncodeData(__METHOD__, $decoded, $reason);
2022
}
2123
}
2224

2325
public function decode(string $encoded): string
2426
{
2527
try {
26-
return $this->doDecode($encoded);
28+
return @$this->doDecode($encoded);
29+
} catch (Exception\CoderCouldNotDecodeData $exception) {
30+
throw $exception;
2731
} catch (Throwable $reason) {
28-
if ($reason instanceof Exception\CouldNotDecodeData) {
29-
throw $reason;
30-
}
31-
throw new Exception\CouldNotDecodeData(__METHOD__, $encoded, $reason);
32+
throw new Exception\CoderCouldNotDecodeData(__METHOD__, $encoded, $reason);
3233
}
3334
}
3435

3536
/**
37+
* @note errors will be silenced
38+
*
3639
* @throws Throwable
3740
*/
3841
abstract protected function doEncode(string $decoded): string;
3942

4043
/**
44+
* @note errors will be silenced
45+
*
4146
* @throws Throwable
4247
*/
4348
abstract protected function doDecode(string $encoded): string;

src/Coder/CoderInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
interface CoderInterface
88
{
99
/**
10-
* @throws Exception\CouldNotEncodeData
10+
* @throws Exception\CoderCouldNotEncodeData
1111
*/
1212
public function encode(string $decoded): string;
1313

1414
/**
15-
* @throws Exception\CouldNotDecodeData
15+
* @throws Exception\CoderCouldNotDecodeData
1616
*/
1717
public function decode(string $encoded): string;
1818
}

src/Coder/Exception/CouldNotDecodeData.php renamed to src/Coder/Exception/CoderCouldNotDecodeData.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
/**
1010
* @extends CouldNotProcessData<string>
1111
*/
12-
final class CouldNotDecodeData extends CouldNotProcessData implements CoderException
12+
final class CoderCouldNotDecodeData extends CouldNotProcessData implements CoderException
1313
{
1414
}

0 commit comments

Comments
 (0)