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).
int b = in.read();
    if (b == -1) {
      return bytes;
    }
    
    Deque<byte[]> bufs = new ArrayDeque<byte[]>(TO_BYTE_ARRAY_DEQUE_SIZE + 2);
    bufs.add(bytes);
    bufs.add(new byte[] {(byte) b});
    return toByteArrayInternal(in, bufs, bytes.length + 1);
  }
  /**
   * Reads and discards data from the given {@code InputStream} until the end of the stream is
   * reached. Returns the total number of bytes read. Does not close the stream.
   *
   * @since 20.0
   */
  @CanIgnoreReturnValue
  @Beta
  public static long exhaust(InputStream in) throws IOException {
    long total = 0;
    long read;
    byte[] buf = createBuffer();
    while ((read = in.read(buf)) != -1) {
      total += read;
    }
    return total;
  }
  /**
   * Returns a new {@link ByteArrayDataInput} instance to read from the {@code bytes} array from the