/** * @param ReadableStreamInterface $readable * @param WritableStreamInterface $writable */ public function __construct(ReadableStreamInterface $readable, WritableStreamInterface $writable) { $this->readable = $readable; $this->writable = $writable; $this->forwardEvents($this->readable, $this, ['data', 'end', 'error', 'close']); $this->forwardEvents($this->writable, $this, ['drain', 'error', 'close', 'pipe']); $this->readable->on('close', [$this, 'close']); $this->writable->on('close', [$this, 'close']); $this->on('pipe', [$this, 'handlePipeEvent']); }
/** * @param ReadableStreamInterface $source * @param WritableStreamInterface $destination * @param array $options * * @return WritableStreamInterface */ public function pipeAll(ReadableStreamInterface $source, WritableStreamInterface $destination, array $options = []) { // TODO: use stream_copy_to_stream // it is 4x faster than this // but can lose data under load with no way to recover it $destination->emit('pipe', array($source)); $source->on('data', function ($data) use($source, $destination) { $feedMore = $destination->write($data); if (false === $feedMore) { $source->pause(); } }); $destination->on('drain', function () use($source) { $source->resume(); }); $end = isset($options['end']) ? $options['end'] : true; if ($end && $source !== $destination) { $source->on('end', function () use($destination) { $destination->end(); }); } return $destination; }