def chunked_slicing(slice_start, slice_stop, chunk_size):
    """
    Iterator that yields, every time, a data structure like this:
      - Current chunk index
      - Start index in chunk
      - Stop index in chunk
      - Start index in source/destination
      - Stop index in source/destination

    It is guaranteed: 0 <= slice_start <= slice_stop <= logical length <= chunk_size * chunk_count.

    The algorithm goes like this:
      - Before: we know the starter bin, and the end bin.
    :param slice_start: The overall start.
    :param slice_stop: The overall stop.
    :param chunk_size: The chunk size.
    :return: A generator.
    """
    start_chunk = slice_start // chunk_size
    stop_chunk = slice_stop // chunk_size
    if start_chunk == stop_chunk:
        data_indices = 0, slice_stop - slice_start
        chunk_indices = slice_start % chunk_size, slice_stop % chunk_size
        yield data_indices, start_chunk, chunk_indices
    else:
        chunk_start_index = slice_start % chunk_size
        chunk_stop_index = slice_stop % chunk_size
        first_iteration = True
        data_index = 0
        current_chunk = start_chunk
        while True:
            if current_chunk == stop_chunk:
                if chunk_stop_index == 0:
                    return
                current_chunk_ubound = chunk_stop_index
            else:
                current_chunk_ubound = chunk_size
            if first_iteration:
                current_chunk_lbound = chunk_start_index
            else:
                current_chunk_lbound = 0
            length = current_chunk_ubound - current_chunk_lbound
            data_indices = data_index, data_index + length
            chunk_indices = current_chunk_lbound, current_chunk_ubound
            yield data_indices, current_chunk, chunk_indices
            if current_chunk == stop_chunk:
                return
            current_chunk += 1
            data_index += length
            first_iteration = False
