public function readBytes(int $num, bool $skipTests = false): string
    {
        // @codeCoverageIgnoreStart
        if ($num < 0) {
            throw new CannotPerformOperation('num < 0');
        } elseif ($num === 0) {
            return '';
        }
        if (($this->pos + $num) > $this->stat['size']) {
            throw new CannotPerformOperation('Out-of-bounds read');
        }
        // @codeCoverageIgnoreEnd
        $buf = '';
        $remaining = $num;
        do {
            if ($remaining <= 0) {
                // @codeCoverageIgnoreStart
                break;
                // @codeCoverageIgnoreEnd
            }
            /** @var int $bufSize */
            $bufSize = \min($remaining, self::CHUNK);
            /** @var string|bool $read */
            $read = \fread($this->fp, $bufSize);
            if (!\is_string($read)) {
                // @codeCoverageIgnoreStart
                throw new FileAccessDenied(
                    'Could not read from the file'
                );
                // @codeCoverageIgnoreEnd
            }
            $buf .= $read;
            $readSize = Binary::safeStrlen($read);
            $this->pos += $readSize;
            $remaining -= $readSize;
        } while ($remaining > 0);
        return $buf;
    }