Skip to content

Commit 49f6811

Browse files
authored
Merge pull request #41 from clue-labs/flush-compressor
Add new `$flush` parameter to control flush mode for `Compressor`
2 parents 19a400f + a7765d8 commit 49f6811

File tree

3 files changed

+59
-8
lines changed

3 files changed

+59
-8
lines changed

src/Compressor.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,15 @@ final class Compressor extends TransformStream
3434
/** @var ?resource */
3535
private $context;
3636

37+
/** @var int */
38+
private $flush;
39+
3740
/**
3841
* @param int $encoding ZLIB_ENCODING_GZIP, ZLIB_ENCODING_RAW or ZLIB_ENCODING_DEFLATE
3942
* @param int $level optional compression level
43+
* @param int $flush optional flush mode (ZLIB_NO_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_FINISH)
4044
*/
41-
public function __construct($encoding, $level = -1)
45+
public function __construct($encoding, $level = -1, int $flush = ZLIB_NO_FLUSH)
4246
{
4347
$errstr = '';
4448
set_error_handler(function ($_, $error) use (&$errstr) {
@@ -61,12 +65,17 @@ public function __construct($encoding, $level = -1)
6165
throw new \InvalidArgumentException('Unable to initialize compressor' . $errstr); // @codeCoverageIgnore
6266
}
6367

68+
if (!in_array($flush, [ZLIB_NO_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_FINISH], true)) {
69+
throw new \InvalidArgumentException('Argument #3 ($flush) must be one of ZLIB_NO_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH or ZLIB_FINISH');
70+
}
71+
6472
$this->context = $context;
73+
$this->flush = $flush;
6574
}
6675

6776
protected function transformData($chunk)
6877
{
69-
$ret = deflate_add($this->context, $chunk, ZLIB_NO_FLUSH);
78+
$ret = deflate_add($this->context, $chunk, $this->flush);
7079

7180
if ($ret !== '') {
7281
$this->emit('data', [$ret]);

tests/CompressorTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,10 @@ public function testCtorThrowsForInvalidEncodingAndUnsetsUsedErrorHandler()
3030

3131
$this->assertEquals($handler, $checkHandler);
3232
}
33+
34+
public function testCtorThrowsForInvalidFlushMode()
35+
{
36+
$this->expectException(\InvalidArgumentException::class);
37+
new Compressor(ZLIB_ENCODING_GZIP, -1, -1);
38+
}
3339
}

tests/GzipCompressorTest.php

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,21 @@ class GzipCompressorTest extends TestCase
88
{
99
private $compressor;
1010

11+
/** @var string */
12+
private $os;
13+
1114
/**
1215
* @before
1316
*/
1417
public function setUpCompressor()
1518
{
1619
$this->compressor = new Compressor(ZLIB_ENCODING_GZIP);
20+
$this->os = DIRECTORY_SEPARATOR !== '\\' ? "\x03" : (PHP_VERSION_ID >= 70200 ? "\x0a" : "\x0b"); // UNIX (0x03) or incorrect TOPS-20(0x0a) or NTFS(0x0b)
1721
}
1822

1923
public function testCompressEmpty()
2024
{
21-
if (DIRECTORY_SEPARATOR === '\\') {
22-
$this->markTestSkipped('Not supported on Windows');
23-
}
24-
25-
$os = DIRECTORY_SEPARATOR === '\\' ? "\x0a" : "\x03"; // NTFS(0x0a) or UNIX (0x03)
26-
$this->compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $os . "\x03\x00" . "\x00\x00\x00\x00\x00\x00\x00\x00"));
25+
$this->compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $this->os . "\x03\x00" . "\x00\x00\x00\x00\x00\x00\x00\x00"));
2726
$this->compressor->on('end', $this->expectCallableOnce());
2827

2928
$this->compressor->end();
@@ -58,4 +57,41 @@ public function testCompressBig()
5857
// PHP < 5.4 does not support gzdecode(), so let's assert this the other way around…
5958
$this->assertEquals(gzencode($data), $buffered);
6059
}
60+
61+
public function testWriteWillOnlyFlushHeaderByDefaultToBufferDataBeforeFlushing()
62+
{
63+
$compressor = new Compressor(ZLIB_ENCODING_GZIP);
64+
65+
$compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $this->os));
66+
67+
$compressor->write('hello');
68+
}
69+
70+
public function testWriteWithSyncFlushWillFlushHeaderWithFirstChunkImmediately()
71+
{
72+
$compressor = new Compressor(ZLIB_ENCODING_GZIP, -1, ZLIB_SYNC_FLUSH);
73+
74+
$compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $this->os . "\xca\x48\xcd\xc9\xc9\x07\x00\x00\x00\xff\xff"));
75+
76+
$compressor->write('hello');
77+
}
78+
79+
public function testWriteWithFinishFlushWillFlushEntireGzipHeaderAndFooterWithFirstChunkImmediately()
80+
{
81+
$compressor = new Compressor(ZLIB_ENCODING_GZIP, -1, ZLIB_FINISH);
82+
83+
$compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $this->os . "\xcb\x48\xcd\xc9\xc9\x07\x00\x86\xa6\x10\x36" . "\x05\x00\x00\x00"));
84+
85+
$compressor->write('hello');
86+
}
87+
88+
public function testWriteAfterFinishFlushWillFlushEntireGzipWithSyncFlushWillFlushEntireGzipHeaderAndFooterAgainImmediately()
89+
{
90+
$compressor = new Compressor(ZLIB_ENCODING_GZIP, -1, ZLIB_FINISH);
91+
$compressor->write('hello');
92+
93+
$compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $this->os . "\xcb\x48\xcd\xc9\xc9\x07\x00\x86\xa6\x10\x36" . "\x05\x00\x00\x00"));
94+
95+
$compressor->write('hello');
96+
}
6197
}

0 commit comments

Comments
 (0)