2017-05-05 22:39:39 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Amp\ByteStream;
|
|
|
|
|
|
|
|
use Amp\Promise;
|
|
|
|
use function Amp\call;
|
|
|
|
|
2017-05-22 14:35:13 +02:00
|
|
|
final class ZlibInputStream implements InputStream {
|
2017-05-05 22:39:39 +02:00
|
|
|
private $source;
|
2017-05-14 14:40:20 +02:00
|
|
|
private $encoding;
|
2017-05-22 14:35:13 +02:00
|
|
|
private $options;
|
2017-05-05 22:39:39 +02:00
|
|
|
private $resource;
|
|
|
|
|
2017-05-22 14:35:13 +02:00
|
|
|
/**
|
|
|
|
* ZlibInputStream constructor.
|
|
|
|
*
|
|
|
|
* @param InputStream $source
|
|
|
|
* @param int $encoding
|
|
|
|
* @param array $options
|
|
|
|
*
|
|
|
|
* @throws StreamException
|
|
|
|
* @throws \Error
|
|
|
|
*
|
|
|
|
* @see http://php.net/manual/en/function.inflate-init.php
|
|
|
|
*/
|
|
|
|
public function __construct(InputStream $source, int $encoding, array $options = []) {
|
2017-05-05 22:39:39 +02:00
|
|
|
$this->source = $source;
|
2017-05-14 14:40:20 +02:00
|
|
|
$this->encoding = $encoding;
|
2017-05-22 14:35:13 +02:00
|
|
|
$this->options = $options;
|
2017-05-22 14:44:36 +02:00
|
|
|
$this->resource = @\inflate_init($encoding, $options);
|
2017-05-05 22:39:39 +02:00
|
|
|
|
|
|
|
if ($this->resource === false) {
|
|
|
|
throw new StreamException("Failed initializing deflate context");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function read(): Promise {
|
|
|
|
return call(function () {
|
2017-05-08 09:30:11 +02:00
|
|
|
if ($this->resource === null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2017-05-05 22:39:39 +02:00
|
|
|
$data = yield $this->source->read();
|
|
|
|
|
2017-05-08 09:44:54 +02:00
|
|
|
// Needs a double guard, as stream might have been closed while reading
|
|
|
|
if ($this->resource === null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2017-05-05 22:39:39 +02:00
|
|
|
if ($data === null) {
|
2017-05-07 11:14:41 +02:00
|
|
|
$decompressed = \inflate_add($this->resource, "", \ZLIB_FINISH);
|
2017-05-05 22:39:39 +02:00
|
|
|
|
|
|
|
if ($decompressed === false) {
|
|
|
|
throw new StreamException("Failed adding data to deflate context");
|
|
|
|
}
|
|
|
|
|
2017-05-08 09:30:11 +02:00
|
|
|
$this->close();
|
2017-05-07 11:14:41 +02:00
|
|
|
|
2017-05-05 22:39:39 +02:00
|
|
|
return $decompressed;
|
|
|
|
}
|
|
|
|
|
|
|
|
$decompressed = \inflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH);
|
|
|
|
|
|
|
|
if ($decompressed === false) {
|
|
|
|
throw new StreamException("Failed adding data to deflate context");
|
|
|
|
}
|
|
|
|
|
|
|
|
return $decompressed;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-05-12 01:08:45 +02:00
|
|
|
protected function close() {
|
2017-05-07 11:14:41 +02:00
|
|
|
$this->resource = null;
|
2017-05-08 09:30:11 +02:00
|
|
|
$this->source = null;
|
2017-05-05 22:39:39 +02:00
|
|
|
}
|
2017-05-14 14:40:20 +02:00
|
|
|
|
|
|
|
public function getEncoding(): int {
|
|
|
|
return $this->encoding;
|
|
|
|
}
|
2017-05-22 14:35:13 +02:00
|
|
|
|
|
|
|
public function getOptions(): array {
|
|
|
|
return $this->options;
|
|
|
|
}
|
2017-05-07 22:14:45 +02:00
|
|
|
}
|