class KeySearch<K> {

    @StageRef
    public SegmentStages s;
    @StageRef
    public HashLookupSearch hashLookupSearch;
    @StageRef
    public HashEntryStages<K> entry;
    public Data<K> inputKey = null;
    @Stage("KeySearch")
    protected SearchState searchState = null;
    @StageRef
    VanillaChronicleMapHolder<?, ?, ?> mh;

    public abstract boolean inputKeyInit();

    public void initInputKey(Data<K> inputKey) {
        this.inputKey = inputKey;
    }

    public abstract boolean keySearchInit();

    @Stage("KeySearch")
    public void setSearchState(SearchState newSearchState) {
        this.searchState = newSearchState;
    }

    public void initKeySearch() {<FILL_FUNCTION_BODY>}

    boolean keyEquals(long keySize, long keyOffset) {
        return inputKey.size() == keySize && inputKey.equivalent(s.segmentBS, keyOffset);
    }

    public boolean searchStatePresent() {
        return searchState == PRESENT;
    }

    public boolean searchStateAbsent() {
        return searchState == ABSENT;
    }

    public enum SearchState {
        PRESENT,
        ABSENT
    }
}

        for (long pos; (pos = hashLookupSearch.nextPos()) >= 0L; ) {
            // otherwise we are inside iteration relocation.
            // During iteration, key search occurs when doReplaceValue() exhausts space in
            // the current segment, and insertion into the tiered segment requires to locate
            // an empty slot in the hashLookup.
            if (inputKeyInit()) {
                long keySizeOffset = s.entrySpaceOffset + pos * mh.m().chunkSize;
                Bytes segmentBytes = s.segmentBytesForRead();
                segmentBytes.readPosition(keySizeOffset);
                long keySize = mh.h().keySizeMarshaller.readSize(segmentBytes);
                long keyOffset = segmentBytes.readPosition();
                if (!keyEquals(keySize, keyOffset))
                    continue;
                hashLookupSearch.found();
                entry.readFoundEntry(pos, keySizeOffset, keySize, keyOffset);
                searchState = PRESENT;
                return;
            }
        }
        searchState = SearchState.ABSENT;
    
<no_super_class>