@Override
    public int encodeStrings(int valCount, long inputAddr, long outputAddr, int outputLimit, Wrapper extraInfo) {
        if (valCount == 0) return 0;

        Object2IntLinkedOpenHashMap<OffheapBytes> dict = new Object2IntLinkedOpenHashMap<>();
        dict.defaultReturnValue(-1);

        ByteSlice dataEntryIds = ByteSlice.allocateDirect(valCount << 2);

        StringsStruct stringDatas = new StringsStruct(valCount, inputAddr);
        int maxDictEntryCount = (int) Math.ceil(valCount * dictEntryRatioThreshold);
        int totalDictStringLen = 0;
        for (int i = 0; i < valCount; i++) {
            OffheapBytes v = stringDatas.getString(i);
            int vid = dict.getInt(v);
            if (vid == -1) {
                if (dict.size() >= maxDictEntryCount) {
                    dict.clear();
                    return ErrorCode.DATA_IMPROPER;
                }
                vid = dict.size();
                dict.put(v, vid);
            }
            dataEntryIds.putInt(i << 2, vid);
        }

        ObjectIterator<OffheapBytes> it = dict.keySet().iterator();
        OffheapBytes[] entries = new OffheapBytes[dict.size()];
        int id = 0;
        while (it.hasNext()) {
            entries[id] = it.next();
            id++;
        }
        assert id == dict.size();
        dict.clear();

        // | dict entry count |   dict   |  dataSize |  data(encoded ids) |
        //         4            dictSize       4           dataSize

        // Write dictionary entries.
        int dictEntriesCount = entries.length;
        UnsafeUtil.setInt(outputAddr, dictEntriesCount);
        StringsStruct dictEntriesData = StringsStruct.from(entries, outputAddr + 4);
        int dictSize = dictEntriesData.totalLen();

        // Write data entry ids.
        RLEPackingHybridCodec dataCodec = new RLEPackingHybridCodec(VarInteger.bitWidth(dictEntriesCount - 1));
        int dataSize = dataCodec.encodeInts(
                valCount,
                dataEntryIds.address(),
                outputAddr + 4 + dictSize + 4,
                outputLimit - (4 + dictSize + 4));
        if (dataSize < 0) {
            dataEntryIds.free();
            return dataSize;
        }
        UnsafeUtil.setInt(outputAddr + 4 + dictSize, dataSize);

        int encodedSize = 4 + dictSize + 4 + dataSize;
        if (encodedSize > outputLimit) {
            return ErrorCode.BUFFER_OVERFLOW;
        }
        return encodedSize;
    }
<pre>
| dictSize |   dict   |  dataSize |  data(encoded ids) |
     4       dictSize       4           dataSize
</pre>
indexr-vlt-segment/src/main/java/io/indexr/vlt/codec/dict/SimpleDictCodec.java