async def read(self, size: Optional[int] = -1) -> T:
        """
        Read up to size bytes from the stream and return them. If size
        is unspecified or is -1, all bytes will be read.

        :param Optional[int] size:
            The number of bytes to download from the stream. Leave unspecified
            or set to -1 to download all bytes.
        :returns:
            The requested data as bytes or a string if encoding was specified. If
            the return value is empty, there is no more data to read.
        :rtype: T
        """
        if size == -1:
            return await self.readall()
        # Empty blob or already read to the end
        if size == 0 or self._offset >= self.size:
            return b'' if not self._encoding else ''

        stream = BytesIO()
        remaining_size = size

        # Start by reading from current_content if there is data left
        if self._offset < len(self._current_content):
            start = self._offset
            length = min(remaining_size, len(self._current_content) - self._offset)
            read = stream.write(self._current_content[start:start + length])

            remaining_size -= read
            self._offset += read
            if self._progress_hook:
                await self._progress_hook(self._offset, self.size)

        if remaining_size > 0:
            start_range = self._get_downloader_start_with_offset()

            # End is the min between the remaining size, the file size, and the end of the specified range
            end_range = min(start_range + remaining_size, self._file_size)
            if self._end_range is not None:
                end_range = min(end_range, self._end_range + 1)

            parallel = self._max_concurrency > 1
            downloader = _AsyncChunkDownloader(
                client=self._clients.blob,
                non_empty_ranges=self._non_empty_ranges,
                total_size=self.size,
                chunk_size=self._config.max_chunk_get_size,
                current_progress=self._offset,
                start_range=start_range,
                end_range=end_range,
                stream=stream,
                parallel=parallel,
                validate_content=self._validate_content,
                encryption_options=self._encryption_options,
                encryption_data=self._encryption_data,
                use_location=self._location_mode,
                progress_hook=self._progress_hook,
                **self._request_options
            )

            dl_tasks = downloader.get_chunk_offsets()
            running_futures = [
                asyncio.ensure_future(downloader.process_chunk(d))
                for d in islice(dl_tasks, 0, self._max_concurrency)
            ]
            while running_futures:
                # Wait for some download to finish before adding a new one
                done, running_futures = await asyncio.wait(
                    running_futures, return_when=asyncio.FIRST_COMPLETED)
                try:
                    for task in done:
                        task.result()
                except HttpResponseError as error:
                    process_storage_error(error)
                try:
                    next_chunk = next(dl_tasks)
                except StopIteration:
                    break
                else:
                    running_futures.add(asyncio.ensure_future(downloader.process_chunk(next_chunk)))

            if running_futures:
                # Wait for the remaining downloads to finish
                done, _running_futures = await asyncio.wait(running_futures)
                try:
                    for task in done:
                        task.result()
                except HttpResponseError as error:
                    process_storage_error(error)

            self._offset += remaining_size

        data = stream.getvalue()
        if self._encoding:
            return data.decode(self._encoding)
        return data

        Read up to size bytes from the stream and return them. If size
        is unspecified or is -1, all bytes will be read.

        :param Optional[int] size:
            The number of bytes to download from the stream. Leave unspecified
            or set to -1 to download all bytes.
        :returns:
            The requested data as bytes or a string if encoding was specified. If
            the return value is empty, there is no more data to read.
        :rtype: T
        
Solutions/CyberArkAudit/Data Connectors/.python_packages/lib/site-packages/azure/storage/blob/aio/_download_async.py