docs: public int read(byte[] to, int off, int len) throws IOException {
      if ((off | len | (off + len) | (to.length - (off + len))) < 0) {
        throw new IndexOutOfBoundsException();
      } else if (len == 0) {
        return 0;
      }
  
      // if the read would go to wrapped stream, but would result
      // in a small read then try read to the buffer instead
      int avail = endIndex - index;
      if (len - avail < MINIMUM_READ) {
        ensureBytes(len);
        avail = endIndex - index;
      }
  
      // first copy from buffer
      if (avail > 0) {
        if (len <= avail) {
          System.arraycopy(buffer, index, to, off, len);
          index += len;
          return len;
        }
        System.arraycopy(buffer, index, to, off, avail);
        len -= avail;
        off += avail;
      }
      int read = avail;
  
      // good place to reset index because the buffer is fully drained
      index = 0;
      endIndex = 0;
  
      // then directly from wrapped stream
      do {
        int r = wrapped.read(to, off, len);
        if (r <= 0) {
          return (read == 0) ? r : read;
        }
        read += r;
        off += r;
        len -= r;
      } while (len > 0);
  
      return read;
    }