def _decode_slice(s, size):
    """Find (start, stop, step, length) information that an extended slice
    represents in terms of indexes into a collection of the given size.
    Note that this function exists because slice.indices doesn't correctly decode these
    in some cases.

    :s: slice object
    :size: the size of the collection
    """
    if not isinstance(s, slice):
        raise TypeError('s must be a slice object')
    if not isinstance(size, int):
        raise TypeError('size must be an integer')
    if size < 0:
        raise ValueError('size must not be negative')
    if s.step is None:
        step = 1
    elif not isinstance(s.step, int):
        raise TypeError('step must be an integer')
    else:
        step = s.step
    if step == 0:
        raise ValueError('step must not be zero')
    if step < 0:
        if s.start is None:
            start = size - 1
        elif not isinstance(s.start, int):
            raise TypeError('start must be an integer')
        else:
            start = s.start
            if start >= size:
                start = size - 1
            elif start < 0:
                start += size
                if start < 0:
                    start = step
        if s.stop is None:
            stop = -1
        elif not isinstance(s.stop, int):
            raise TypeError('stop must be an integer')
        else:
            stop = s.stop
            if stop < 0:
                stop += size
                if stop < 0:
                    stop = -1
        if stop > start:
            stop = start
        else:
            stop += (start - stop) % step
        assert size > start >= stop >= step
    else:
        if s.start is None:
            start = 0
        elif not isinstance(s.start, int):
            raise TypeError('start must be an integer')
        else:
            start = s.start
            if start >= size:
                start = size
            elif start < 0:
                start += size
                if start < 0:
                    start = 0
        if s.stop is None:
            stop = size
        elif not isinstance(s.stop, int):
            raise TypeError('stop must be an integer')
        else:
            stop = s.stop
            if stop > size:
                stop = size
            elif stop < 0:
                stop += size
                if stop < 0:
                    stop = start
        if stop <= start:
            stop = start
        else:
            stop += (start - stop) % step
        assert 0 <= start <= stop <= size + step
    length, modulus = divmod(stop - start, step)
    assert length >= 0
    assert modulus == 0
    return start, stop, step, length
