def _get_next_chunk(stream, chunk_size):
    """Get a chunk from an I/O stream.

    The ``stream`` may have fewer bytes remaining than ``chunk_size``
    so it may not always be the case that
    ``end_byte == start_byte + chunk_size - 1``.

    Args:
       stream (IO[bytes]): The stream (i.e. file-like object).

    Returns:
        Tuple[int, int, bytes]: Triple of the start byte index, the end byte
        index and the content in between those bytes.

    Raises:
        ValueError: If there is no data left to consume. This corresponds
            exactly to the case ``end_byte < start_byte``, which can only
            occur if ``end_byte == start_byte - 1``.
    """
    start_byte = stream.tell()
    payload = stream.read(chunk_size)
    end_byte = stream.tell() - 1
    if end_byte < start_byte:
        raise ValueError(
            u'Stream is already exhausted. There is no content remaining.')
    return start_byte, end_byte, payload