def clean_slice(
    dim: int,
    sl: slice,
) -> slice:
    """return a cleaned slice for a given length, converting start, stop and step
    to non negative integer values. Only unit step are supported.

    Args:
        dim (int): the length of the axis
        sl (slice): the slice regarding the axis

    Raises:
        ValueError: if any parameter of the slice is not an int or NoneType
        IndexError: if any parameter of the slice is out of bounds

    Returns:
        slice: a slice with only non negative integer values
    """

    # make sure steps are all 1 or None
    if sl.step not in [1, None]:
        raise ValueError(f"slice should have step of 1: {sl} ({sl.step=})")

    start = sl.start
    if start is None:
        start = 0
    if not isinstance(start, int):
        raise ValueError(f"invalid start for slice {sl} ({start=})")

    stop = sl.stop
    if stop is None:
        stop = dim
    if not isinstance(stop, int):
        raise ValueError(f"invalid stop for slice {sl} ({stop=})")

    # update slices to have >= 0 start
    if start < 0:
        start += dim
        if start < 0:
            raise IndexError(f"bad start for slice {sl} ({start=} < 0)")
    if start >= dim:
        raise IndexError(f"bad start for slice {sl} ({start=} >= {dim=}")

    # update slices to have <= len max
    if stop < 0:
        stop += dim
        if stop < 0:
            raise IndexError(f"bad stop for slice {sl} ({stop=} < 0)")
    if stop > dim:
        raise IndexError(f"bad stop for slice {sl} ({stop=} > {dim=})")

    # must not be empty
    if stop <= start:
        raise ValueError(f"empty slice {sl} ({stop=} <= {start=})")

    return slice(start, stop, 1)