source = $source; $this->size = Integers::assertOptionalNonNegativeSize($options['size'] ?? null, 'Stream size'); $this->metadata = $options['metadata'] ?? []; $this->buffer = new BufferStream(); } public function __unserialize(array $data) : void { $this->source = null; $this->size = null; $this->tellPos = 0; $this->metadata = []; $this->buffer = new BufferStream(); throw new \LogicException(static::class . ' should never be unserialized'); } public function __toString() : string { return Utils::copyToString($this); } public function close() : void { $this->detach(); } public function detach() { $this->tellPos = 0; $this->source = null; $this->buffer->close(); return null; } public function getSize() : ?int { return $this->size; } public function tell() : int { return $this->tellPos; } public function eof() : bool { return $this->source === null; } public function isSeekable() : bool { return \false; } public function rewind() : void { $this->seek(0); } public function seek(int $offset, int $whence = \SEEK_SET) : void { throw new \RuntimeException('Cannot seek a PumpStream'); } public function isWritable() : bool { return \false; } public function write(string $string) : int { throw new \RuntimeException('Cannot write to a PumpStream'); } public function isReadable() : bool { return \true; } public function read(int $length) : string { if ($length < 0) { throw new \RuntimeException('Length parameter cannot be negative'); } $bufferLength = $this->buffer->getSize() ?? 0; if ($length > $bufferLength) { $this->pump($length - $bufferLength); } $data = $this->buffer->read($length); $this->tellPos = Integers::add($this->tellPos, \strlen($data)); return $data; } public function getContents() : string { return Utils::copyToString($this); } /** * @return mixed */ public function getMetadata(?string $key = null) { if ($key === null) { return $this->metadata; } return $this->metadata[$key] ?? null; } private function pump(int $length) : void { if ($this->source !== null) { do { /** @var string|false|null $data */ $data = ($this->source)($length); if ($data === \false || $data === null) { $this->source = null; return; } if ($data === '') { throw new \RuntimeException('PumpStream source returned an empty string'); } $this->buffer->write($data); $length -= \strlen($data); } while ($length > 0); } } }