/** * @param ReadableStreamInterface $stream */ public function __construct(ReadableStreamInterface $stream) { $this->stream = $stream; $this->stream->on('data', array($this, 'handleData')); $this->stream->on('end', array($this, 'handleEnd')); Util::forwardEvents($this->stream, $this, ['error']); }
/** * Creates a `Promise` which resolves with the stream data buffer * * @param ReadableStreamInterface $stream * @return CancellablePromiseInterface Promise<string, Exception> */ function buffer(ReadableStreamInterface $stream) { // stream already ended => resolve with empty buffer if (!$stream->isReadable()) { return Promise\resolve(''); } $buffer = ''; $bufferer = function ($data) use(&$buffer) { $buffer .= $data; }; $stream->on('data', $bufferer); $promise = new Promise\Promise(function ($resolve, $reject) use($stream, &$buffer) { $stream->on('error', function ($error) use($reject) { $reject(new \RuntimeException('An error occured on the underlying stream while buffering', 0, $error)); }); $stream->on('close', function () use($resolve, &$buffer) { $resolve($buffer); }); }, function ($_, $reject) { $reject(new \RuntimeException('Cancelled buffering')); }); return $promise->then(null, function ($error) use(&$buffer, $bufferer, $stream) { // promise rejected => clear buffer and buffering $buffer = ''; $stream->removeListener('data', $bufferer); throw $error; }); }
public function __construct(ReadableStreamInterface $input) { $this->input = $input; $that = $this; $input->on('data', function ($data) use($that) { $that->emit('data', array($data, $that)); }); $input->on('error', function ($error) use($that) { $that->emit('error', array($error, $that)); }); $input->on('end', function () use($that) { $that->emit('end', array($that)); $that->emit('close', array($that)); }); $input->on('close', function () use($that) { $that->emit('close', array($that)); }); }
public function __construct(ReadableStreamInterface $multiplexed, $stderrEvent = null) { $this->multiplexed = $multiplexed; if ($stderrEvent === null) { $stderrEvent = 'data'; } $this->stderrEvent = $stderrEvent; $out = $this; $buffer =& $this->buffer; $closed =& $this->closed; // pass all input data chunks through the parser $multiplexed->on('data', array($out, 'push')); // forward end event to output (unless parsing is still in progress) $multiplexed->on('end', function () use(&$buffer, $out, &$closed) { // ignore duplicate end events if ($closed) { return; } // buffer must be empty on end, otherwise this is an error situation if ($buffer === '') { $out->emit('end', array()); } else { $out->emit('error', array(new \RuntimeException('Stream ended within incomplete multiplexed chunk'))); } $out->close(); }); // forward error event to output $multiplexed->on('error', function ($error) use($out) { $out->emit('error', array($error)); $out->close(); }); // forward close event to output $multiplexed->on('close', function ($error) use($out) { $out->close(); }); }
public function deferredStream(ReadableStreamInterface $stream, $progressEventName) { // cancelling the deferred will (try to) close the stream $deferred = new Deferred(function () use($stream) { $stream->close(); throw new RuntimeException('Cancelled'); }); if ($stream->isReadable()) { // buffer all data events for deferred resolving $buffered = array(); $stream->on($progressEventName, function ($data) use(&$buffered) { $buffered[] = $data; }); // error event rejects $stream->on('error', function ($error) use($deferred) { $deferred->reject($error); }); // close event resolves with buffered events (unless already error'ed) $stream->on('close', function () use($deferred, &$buffered) { $deferred->resolve($buffered); }); } else { $deferred->reject(new RuntimeException('Stream already ended, looks like it could not be opened')); } return $deferred->promise(); }