readBytes method

Future<List<int>?> readBytes(
  1. int nrBytesToRead
)

Reads a list of bytes of nrBytesToRead bytes from the stream, if possible, or null otherwise (e.g. the stream doesn't contain nrBytesToRead bytes).

Implementation

Future<List<int>?> readBytes(int nrBytesToRead) async {
  // If we don't want to read anything, stop immediately.
  if (nrBytesToRead == 0) {
    return null;
  }

  // Try to get enough data in the cache.
  var cachedBytes = await _ensureEnoughBytesInCache(nrBytesToRead);

  // If we still don't have enough bytes, stop.
  if (cachedBytes < nrBytesToRead) {
    return null;
  }

  // Have enough bytes -> return them.
  final result = List<int>.filled(nrBytesToRead, 0);
  _bytesRead += nrBytesToRead;
  do {
    final firstList = _cachedLists.first;
    // Determine how many items we can take from the first list.
    final nrBytesFromFirstList =
        min(nrBytesToRead, firstList.length - _positionInFrontList);

    // Get those items to the result.
    final srcRange = firstList.getRange(
        _positionInFrontList, _positionInFrontList + nrBytesFromFirstList);
    // We need to start setting bytes to result after the ones we've already
    // set in previous loops.
    final targetPos = result.length - nrBytesToRead;
    result.setRange(targetPos, targetPos + nrBytesFromFirstList, srcRange);

    // Remove the first list if it's fully consumed.
    _positionInFrontList += nrBytesFromFirstList;
    if (_positionInFrontList == firstList.length) {
      _cachedLists.removeFirst();
      _positionInFrontList = 0;
    }

    // Calculate how many bytes we still need to read.
    nrBytesToRead -= nrBytesFromFirstList;

    // Continue until we've read all we needed to.
  } while (nrBytesToRead != 0);

  return result;
}