read($length); } catch (TimeoutException $e) { throw $e; } catch (\RuntimeException $e) { self::throwIfReadTimedOut($stream, $timeoutMessage, $e); throw $e; } if ($buffer === '') { self::throwIfReadTimedOut($stream, $timeoutMessage); } return $buffer; } public static function throwIfReadTimedOut( StreamInterface $stream, string $message, ?\Throwable $previous = null ): void { if (self::isReadTimedOut($stream)) { throw new TimeoutException($message, 0, $previous); } } public static function throwIfWriteTimedOut(StreamInterface $stream, ?\Throwable $previous = null): void { if (self::isWriteTimedOut($stream)) { throw new TimeoutException('Unable to write to stream: timed out', 0, $previous); } } public static function isReadTimedOut(StreamInterface $stream): bool { try { if ($stream->getMetadata('timed_out') !== true) { return false; } return !$stream->eof(); } catch (\Throwable $e) { return false; } } public static function isWriteTimedOut(StreamInterface $stream): bool { try { return $stream->getMetadata('timed_out') === true; } catch (\Throwable $e) { return false; } } /** * @param resource $resource */ public static function isResourceReadTimedOut($resource): bool { try { /** @var array $metadata */ $metadata = stream_get_meta_data($resource); return ($metadata['timed_out'] ?? false) === true && !feof($resource); } catch (\Throwable $e) { return false; } } /** * @param resource $resource */ public static function isResourceWriteTimedOut($resource): bool { try { /** @var array $metadata */ $metadata = stream_get_meta_data($resource); return ($metadata['timed_out'] ?? false) === true; } catch (\Throwable $e) { return false; } } }