mirror of
https://github.com/danog/byte-stream.git
synced 2024-11-30 04:19:23 +01:00
Add GzipInputStream
This commit is contained in:
parent
bcefe903c9
commit
bc24326ec0
19
examples/gzip-decompress.php
Normal file
19
examples/gzip-decompress.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
use Amp\ByteStream\GzipInputStream;
|
||||
use Amp\ByteStream\ResourceInputStream;
|
||||
use Amp\ByteStream\ResourceOutputStream;
|
||||
use Amp\Loop;
|
||||
|
||||
require __DIR__ . "/../vendor/autoload.php";
|
||||
|
||||
Loop::run(function () {
|
||||
$stdin = new ResourceInputStream(STDIN);
|
||||
$stdout = new ResourceOutputStream(STDOUT);
|
||||
|
||||
$gzin = new GzipInputStream($stdin);
|
||||
|
||||
while (($chunk = yield $gzin->read()) !== null) {
|
||||
yield $stdout->write($chunk);
|
||||
}
|
||||
});
|
72
lib/GzipInputStream.php
Normal file
72
lib/GzipInputStream.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\ByteStream;
|
||||
|
||||
use Amp\Promise;
|
||||
use function Amp\call;
|
||||
|
||||
class GzipInputStream implements InputStream {
|
||||
const STATE_FAILED = -1;
|
||||
const STATE_NORMAL = 0;
|
||||
const STATE_ENDING = 1;
|
||||
const STATE_ENDED = 2;
|
||||
|
||||
private $source;
|
||||
private $resource;
|
||||
private $state = 0;
|
||||
|
||||
public function __construct(InputStream $source) {
|
||||
$this->source = $source;
|
||||
$this->resource = \inflate_init(\ZLIB_ENCODING_GZIP);
|
||||
|
||||
if ($this->resource === false) {
|
||||
throw new StreamException("Failed initializing deflate context");
|
||||
}
|
||||
}
|
||||
|
||||
public function read(): Promise {
|
||||
return call(function () {
|
||||
if ($this->state === self::STATE_ENDED) {
|
||||
throw new ClosedException("The stream has already been closed");
|
||||
}
|
||||
|
||||
if ($this->state === self::STATE_ENDING) {
|
||||
$this->state = self::STATE_ENDED;
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->state === self::STATE_FAILED) {
|
||||
throw new StreamException("The stream has previously failed");
|
||||
}
|
||||
|
||||
$data = yield $this->source->read();
|
||||
|
||||
if ($data === null) {
|
||||
$decompressed = \inflate_add($this->resource, "", \ZLIB_FINISH);
|
||||
|
||||
$this->state = self::STATE_ENDING;
|
||||
|
||||
if ($decompressed === false) {
|
||||
$this->state = self::STATE_FAILED;
|
||||
throw new StreamException("Failed adding data to deflate context");
|
||||
}
|
||||
|
||||
return $decompressed;
|
||||
}
|
||||
|
||||
$decompressed = \inflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH);
|
||||
|
||||
if ($decompressed === false) {
|
||||
$this->state = self::STATE_FAILED;
|
||||
throw new StreamException("Failed adding data to deflate context");
|
||||
}
|
||||
|
||||
return $decompressed;
|
||||
});
|
||||
}
|
||||
|
||||
public function close() {
|
||||
$this->state = self::STATE_ENDED;
|
||||
$this->source->close();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user