@Override
    protected List<SearchResult<SequenceMatcher>> doSearchForwards(final WindowReader reader, 
            final long fromPosition, final long toPosition) throws IOException {
        // Get info needed to search with:
        final SearchInfo info = forwardInfo.get();
        final int[] safeShifts = info.shifts;
        final MultiSequenceMatcher backMatcher = info.matcher;
        final int hashBitMask = safeShifts.length - 1; // safe shifts is a power of two size.            

        // Initialise window search:
        final long finalPosition = toPosition + sequences.getMaximumLength() - 1;
        long searchPosition = fromPosition + sequences.getMinimumLength() - 1;       

        // While there is a window to search in:
        Window window;             
        while (searchPosition <= finalPosition &&
               (window = reader.getWindow(searchPosition)) != null) {

            // Initialise array search:
            final byte[] array = window.getArray();
            final int arrayStartPosition = reader.getWindowOffset(searchPosition);
            final int arrayEndPosition = window.length() - 1;
            final long distanceToEnd = finalPosition - window.getWindowPosition();     
            final int lastSearchPosition = distanceToEnd < arrayEndPosition?
                                     (int) distanceToEnd : arrayEndPosition;
            int arraySearchPosition = arrayStartPosition;            

            if (arraySearchPosition == 0) {
                //TODO: why is this here?
            }

            // Search forwards in this array:
            // Use the readByte method on the reader to get the first byte of 
            // the block to hash, as it could be in a prior window.
            int firstBlockByte = reader.readByte(searchPosition - 1); 
            while (arraySearchPosition <= lastSearchPosition) {

                // Calculate the hash of the current block:
                final int lastBlockByte = array[arraySearchPosition] & 0xFF;
                if (firstBlockByte < 0) {
                    firstBlockByte = array[arraySearchPosition - 1] & 0xFF;
                }
                final int blockHash = (firstBlockByte << 5) - firstBlockByte + lastBlockByte;

                // Get the safe shift for this block:
                final int safeShift = safeShifts[blockHash & hashBitMask];

                if (safeShift == 0) {
                    // see if we have a match:
                    final long matchEndPosition = searchPosition + arraySearchPosition - arrayStartPosition;
                    final Collection<SequenceMatcher> matches =
                            backMatcher.allMatchesBackwards(reader, matchEndPosition);
                    if (!matches.isEmpty()) {
                        // See if any of the matches are within the bounds of the search:
                        final List<SearchResult<SequenceMatcher>> results = 
                            SearchUtils.resultsBackFromPosition(matchEndPosition, matches,
                                                                fromPosition, toPosition);
                        if (!results.isEmpty()) {
                            return results;
                        }
                    }
                    arraySearchPosition++;
                    firstBlockByte = lastBlockByte;
                } else {
                    arraySearchPosition += safeShift;
                    firstBlockByte = -1;
                } 
            } 

            // No match was found in this array - calculate the current search position:
            searchPosition += arraySearchPosition - arrayStartPosition;
        }

        return SearchUtils.noResults();                    
    }