skipUpTo helpfully falls back from skip invocations which return zero to invoke a read into a buffer.

The current implementation has two inefficiencies which cause unexpected performance degradation in tight loops, especially when a small number of bytes are requested:

1. In many cases skipSafely is able to skip all the requested bytes, there's no need to allocate a read buffer
2. The caller only requests a few bytes are skipped. Calling `ByteStreams.skipFully(stream, 32)` always allocates a 8192 byte buffer.

Proposed solution:
Defer buffer allocation until it is needed, using the minimum of the requested size and BUFFER_SIZE. This reduces allocation pressure in all cases of small skip values, as well as streams that report nonzero bytes available (assuming skip returns a positive value).
while (buf.hasRemaining()) {
        total += to.write(buf);
      }
      buf.clear();
    }
    return total;
  }
  
  private static final int MAX_ARRAY_LEN = Integer.MAX_VALUE - 8;
  
  private static final int TO_BYTE_ARRAY_DEQUE_SIZE = 20;
  /**
   * Returns a byte array containing the bytes from the buffers already in {@code bufs} (which have
   * a total combined length of {@code totalLen} bytes) followed by all bytes remaining in the given
   * input stream.
   */
  private static byte[] toByteArrayInternal(InputStream in, Deque<byte[]> bufs, int totalLen)
      throws IOException {
    
    
    
    for (int bufSize = BUFFER_SIZE;
        totalLen < MAX_ARRAY_LEN;
        bufSize = IntMath.saturatedMultiply(bufSize, 2)) {
      byte[] buf = new byte[Math.min(bufSize, MAX_ARRAY_LEN - totalLen)];
      bufs.add(buf);
      int off = 0;
      while (off < buf.length) {
        
        int r = in.read(buf, off, buf.length - off);