Skip to content

Commit 79a282b

Browse files
authored
Merge pull request #12 from xp-forge/feature/options
Abstract algorithm options into an `Options` class
2 parents 260228c + 67629f0 commit 79a282b

File tree

9 files changed

+178
-22
lines changed

9 files changed

+178
-22
lines changed

ChangeLog.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ Compression streams ChangeLog
33

44
## ?.?.? / ????-??-??
55

6+
## 2.0.0 / ????-??-??
7+
8+
* **Heads up:** Algorithm implementations must change their `compress`
9+
and `create` signatures from `$level= -1` to `$options= null`, and
10+
can use `Options::from($options)->level` to access the given level
11+
in a backwards-compatible fashion.
12+
(@thekid)
13+
* Merged PR #12: Abstract algorithm options into an `Options` class
14+
(@thekid)
15+
616
## 1.4.0 / 2025-07-31
717

818
* Merged PR #9: Add `Algorithm::compress()` and `Algorithm::decompress()`

src/main/php/io/streams/compress/Algorithm.class.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public abstract function extension(): string;
2121
public abstract function level(int $select): int;
2222

2323
/** Compresses data */
24-
public abstract function compress(string $data, int $level= Compression::DEFAULT): string;
24+
public abstract function compress(string $data, $options= null): string;
2525

2626
/** Decompresses bytes */
2727
public abstract function decompress(string $bytes): string;
@@ -30,7 +30,7 @@ public abstract function decompress(string $bytes): string;
3030
public abstract function open(InputStream $in): InputStream;
3131

3232
/** Opens an output stream for writing */
33-
public abstract function create(OutputStream $out, int $level= Compression::DEFAULT): OutputStream;
33+
public abstract function create(OutputStream $out, $options= null): OutputStream;
3434

3535
/** @return string */
3636
public function hashCode() { return crc32($this->name()); }

src/main/php/io/streams/compress/Brotli.class.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public function level(int $select): int {
2323
}
2424

2525
/** Compresses data */
26-
public function compress(string $data, int $level= Compression::DEFAULT): string {
27-
return brotli_compress($data, $this->level($level));
26+
public function compress(string $data, $options= null): string {
27+
return brotli_compress($data, $this->level(Options::from($options)->level));
2828
}
2929

3030
/** Decompresses bytes */
@@ -38,7 +38,7 @@ public function open(InputStream $in): InputStream {
3838
}
3939

4040
/** Opens an output stream for writing */
41-
public function create(OutputStream $out, int $level= Compression::DEFAULT): OutputStream {
42-
return new BrotliOutputStream($out, $this->level($level));
41+
public function create(OutputStream $out, $options= null): OutputStream {
42+
return new BrotliOutputStream($out, $this->level(Options::from($options)->level));
4343
}
4444
}

src/main/php/io/streams/compress/Bzip2.class.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ public function level(int $select): int {
2424
}
2525

2626
/** Compresses data */
27-
public function compress(string $data, int $level= Compression::DEFAULT): string {
28-
return bzcompress($data, $this->level($level));
27+
public function compress(string $data, $options= null): string {
28+
return bzcompress($data, $this->level(Options::from($options)->level));
2929
}
3030

3131
/** Decompresses bytes */
@@ -43,7 +43,7 @@ public function open(InputStream $in): InputStream {
4343
}
4444

4545
/** Opens an output stream for writing */
46-
public function create(OutputStream $out, int $level= Compression::DEFAULT): OutputStream {
47-
return new Bzip2OutputStream($out, $this->level($level));
46+
public function create(OutputStream $out, $options= null): OutputStream {
47+
return new Bzip2OutputStream($out, $this->level(Options::from($options)->level));
4848
}
4949
}

src/main/php/io/streams/compress/Gzip.class.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ public function level(int $select): int {
2424
}
2525

2626
/** Compresses data */
27-
public function compress(string $data, int $level= Compression::DEFAULT): string {
28-
return gzcompress($data, $this->level($level));
27+
public function compress(string $data, $options= null): string {
28+
return gzcompress($data, $this->level(Options::from($options)->level));
2929
}
3030

3131
/** Decompresses bytes */
@@ -44,7 +44,7 @@ public function open(InputStream $in): InputStream {
4444
}
4545

4646
/** Opens an output stream for writing */
47-
public function create(OutputStream $out, int $level= Compression::DEFAULT): OutputStream {
48-
return new GzipOutputStream($out, $this->level($level));
47+
public function create(OutputStream $out, $options= null): OutputStream {
48+
return new GzipOutputStream($out, $this->level(Options::from($options)->level));
4949
}
5050
}

src/main/php/io/streams/compress/None.class.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function extension(): string { return ''; }
2020
public function level(int $select): int { return 0; }
2121

2222
/** Compresses data */
23-
public function compress(string $data, int $level= Compression::DEFAULT): string { return $data; }
23+
public function compress(string $data, $options= null): string { return $data; }
2424

2525
/** Decompresses bytes */
2626
public function decompress(string $bytes): string { return $bytes; }
@@ -31,7 +31,7 @@ public function open(InputStream $in): InputStream {
3131
}
3232

3333
/** Opens an output stream for writing */
34-
public function create(OutputStream $out, int $level= Compression::DEFAULT): OutputStream {
34+
public function create(OutputStream $out, $options= null): OutputStream {
3535
return $out;
3636
}
3737
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php namespace io\streams\compress;
2+
3+
use io\streams\Compression;
4+
use lang\Value;
5+
use util\Comparison;
6+
7+
/** @test io.streams.compress.unittest.OptionsTest */
8+
class Options implements Value {
9+
use Comparison;
10+
11+
public $level, $length;
12+
13+
/**
14+
* Compression options
15+
*
16+
* @param ?int $level
17+
* @param ?int $length
18+
*/
19+
public function __construct(
20+
$level= null,
21+
$length= null
22+
) {
23+
$this->level= $level ?? Compression::DEFAULT;
24+
$this->length= $length;
25+
}
26+
27+
/** @param ?int|[:var]|self $arg */
28+
public static function from($arg): self {
29+
if (null === $arg) {
30+
return new self();
31+
} else if ($arg instanceof self) {
32+
return $arg;
33+
} else if (is_array($arg)) {
34+
return new self(
35+
$arg['level'] ?? null,
36+
$arg['length'] ?? null
37+
);
38+
} else {
39+
return new self($arg);
40+
}
41+
}
42+
43+
/** @return string */
44+
public function toString() {
45+
switch ($this->level) {
46+
case Compression::FASTEST: $level= 'FASTEST'; break;
47+
case Compression::DEFAULT: $level= 'DEFAULT'; break;
48+
case Compression::STRONGEST: $level= 'STRONGEST'; break;
49+
default: $level= $this->level;
50+
}
51+
52+
return sprintf(
53+
'%s(level: %s, length: %s)',
54+
nameof($this),
55+
$level,
56+
null === $this->length ? 'null' : $this->length
57+
);
58+
}
59+
}

src/test/php/io/streams/compress/unittest/AlgorithmsTest.class.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,32 @@ public function name(): string { return 'test'; }
1515
public function token(): string { return 'x-test'; }
1616
public function extension(): string { return '.test'; }
1717
public function level(int $select): int { return $select; }
18-
public function compress(string $data, int $level= Compression::DEFAULT): string { return $data; }
18+
public function compress(string $data, $options= null): string { return $data; }
1919
public function decompress(string $bytes): string { return $bytes; }
2020
public function open(InputStream $in): InputStream { return $in; }
21-
public function create(OutputStream $out, int $method= Compression::DEFAULT): OutputStream { return $out; }
21+
public function create(OutputStream $out, $options= null): OutputStream { return $out; }
2222
};
2323
$this->additional= new class() extends Algorithm {
2424
public function supported(): bool { return true; }
2525
public function name(): string { return 'add'; }
2626
public function token(): string { return 'x-add'; }
2727
public function extension(): string { return '.add'; }
2828
public function level(int $select): int { return $select; }
29-
public function compress(string $data, int $level= Compression::DEFAULT): string { return $data; }
29+
public function compress(string $data, $options= null): string { return $data; }
3030
public function decompress(string $bytes): string { return $bytes; }
3131
public function open(InputStream $in): InputStream { return $in; }
32-
public function create(OutputStream $out, int $method= Compression::DEFAULT): OutputStream { return $out; }
32+
public function create(OutputStream $out, $options= null): OutputStream { return $out; }
3333
};
3434
$this->unsupported= new class() extends Algorithm {
3535
public function supported(): bool { return false; }
3636
public function name(): string { return 'lzw'; }
3737
public function token(): string { return 'compress'; }
3838
public function extension(): string { return '.lz'; }
3939
public function level(int $select): int { return $select; }
40-
public function compress(string $data, int $level= Compression::DEFAULT): string { return $data; }
40+
public function compress(string $data, $options= null): string { return $data; }
4141
public function decompress(string $bytes): string { return $bytes; }
4242
public function open(InputStream $in): InputStream { return $in; }
43-
public function create(OutputStream $out, int $method= Compression::DEFAULT): OutputStream { return $out; }
43+
public function create(OutputStream $out, $options= null): OutputStream { return $out; }
4444
};
4545
}
4646

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php namespace io\streams\compress\unittest;
2+
3+
use io\streams\Compression;
4+
use io\streams\compress\Options;
5+
use test\{Assert, Test, Values};
6+
7+
class OptionsTest {
8+
const LENGTH= 6100;
9+
10+
/** @return iterable */
11+
private function maps() {
12+
yield [[], Compression::DEFAULT, null];
13+
yield [['unused' => -1], Compression::DEFAULT, null];
14+
yield [['level' => Compression::FASTEST], Compression::FASTEST, null];
15+
yield [['level' => Compression::FASTEST, 'length' => self::LENGTH], Compression::FASTEST, self::LENGTH];
16+
}
17+
18+
#[Test]
19+
public function can_create() {
20+
new Options();
21+
}
22+
23+
#[Test]
24+
public function default_level() {
25+
Assert::equals(Compression::DEFAULT, (new Options())->level);
26+
}
27+
28+
#[Test]
29+
public function default_length() {
30+
Assert::null((new Options())->length);
31+
}
32+
33+
#[Test, Values([Compression::FASTEST, Compression::DEFAULT, Compression::STRONGEST])]
34+
public function level($level) {
35+
Assert::equals($level, (new Options($level))->level);
36+
}
37+
38+
#[Test]
39+
public function length() {
40+
Assert::equals(self::LENGTH, (new Options(null, self::LENGTH))->length);
41+
}
42+
43+
#[Test]
44+
public function from_level() {
45+
Assert::equals(new Options(Compression::FASTEST, null), Options::from(Compression::FASTEST));
46+
}
47+
48+
#[Test]
49+
public function from_null() {
50+
Assert::equals(new Options(Compression::DEFAULT, null), Options::from(null));
51+
}
52+
53+
#[Test]
54+
public function from_options() {
55+
$options= new Options(Compression::FASTEST, self::LENGTH);
56+
Assert::equals($options, Options::from($options));
57+
}
58+
59+
#[Test, Values(from: 'maps')]
60+
public function from($map, $level, $length) {
61+
Assert::equals(new Options($level, $length), Options::from($map));
62+
}
63+
64+
#[Test]
65+
public function string_representation() {
66+
Assert::equals(
67+
'io.streams.compress.Options(level: DEFAULT, length: null)',
68+
(new Options())->toString()
69+
);
70+
}
71+
72+
#[Test]
73+
public function string_representation_with_length() {
74+
Assert::equals(
75+
'io.streams.compress.Options(level: DEFAULT, length: 6100)',
76+
(new Options(null, self::LENGTH))->toString()
77+
);
78+
}
79+
80+
#[Test]
81+
public function string_representation_with_level() {
82+
Assert::equals(
83+
'io.streams.compress.Options(level: 22, length: null)',
84+
(new Options(22))->toString()
85+
);
86+
}
87+
}

0 commit comments

Comments
 (0)