class ReversedCharSequence extends ReverseIndexMapperBase implements ReverseCharSequence {

    @Override
    public ReversedCharSequence subSequence(int start, int end) {
        if (start < 0 || end > length())
            throw new IndexOutOfBoundsException("[" + start + ", " + end + ") not in [0," + length() + "]");
        final int startIndex = mapBoundary(end);
        final int endIndex = startIndex + end - start;
        return startIndex == myStartIndex && endIndex == myEndIndex ? this : new ReversedCharSequence(myChars, startIndex, endIndex);
    }

}

class ReversedCharSequenceTest {

    @Test
    public void subSequence() throws Exception {

        CharSequence orig = "abcdef";
        CharSequence reved = "fedcba";
        ReversedCharSequence test = (ReversedCharSequence) ReversedCharSequence.of(orig);

        int iMax = orig.length();
        for (int i = 0; i < iMax; i++) {
            for (int j = iMax - i - 1; j >= 0 && j >= i; j--) {
                assertEquals("subSequence(" + i + "," + j + ")", reved.subSequence(i, j), test.subSequence(i, j).toString());
                assertEquals("reverse.of(subSequence(" + i + "," + j + "))", orig.subSequence(test.mapIndex(j) + 1, test.mapIndex(j) + 1 + j - i), ReversedCharSequence.of(test.subSequence(i, j)).toString());
                assertEquals("subSequence(" + i + "," + j + ").hashCode()", reved.subSequence(i, j).hashCode(), test.subSequence(i, j).hashCode());
                assertEquals("subSequence(" + i + "," + j + ").equals()", true, test.subSequence(i, j).equals(reved.subSequence(i, j)));
            }
        }
    }

}