public static int compress(DictStruct dictStruct, int valCount, long outputAddr, int outputLimit) {
        boolean isDictEntryCompressed = dictStruct.dictEntryCount() >= 64 && dictStruct.dictSize() >= 256;
        Codec dictEntryCodec = isDictEntryCompressed ? new DeltaCodec() : new PlainCodec();
        setInt(outputAddr, dictStruct.dictEntryCount());
        setByte(outputAddr + 4, (byte) (isDictEntryCompressed ? 1 : 0));
        int dictEntryEncodedSize;
        switch (dictStruct.dataType()) {
            case DataType.INT:
                dictEntryEncodedSize = dictEntryCodec.encodeInts(
                        dictStruct.dictEntryCount(),
                        dictStruct.dictEntriesAddr(),
                        outputAddr + (4 + 1),
                        outputLimit - (4 + 1));
                break;
            case DataType.LONG:
                dictEntryEncodedSize = dictEntryCodec.encodeLongs(
                        dictStruct.dictEntryCount(),
                        dictStruct.dictEntriesAddr(),
                        outputAddr + (4 + 1),
                        outputLimit - (4 + 1));
                break;
            case DataType.FLOAT:
                dictEntryEncodedSize = dictEntryCodec.encodeFloats(
                        dictStruct.dictEntryCount(),
                        dictStruct.dictEntriesAddr(),
                        outputAddr + (4 + 1),
                        outputLimit - (4 + 1));
                break;
            case DataType.DOUBLE:
                dictEntryEncodedSize = dictEntryCodec.encodeDoubles(
                        dictStruct.dictEntryCount(),
                        dictStruct.dictEntriesAddr(),
                        outputAddr + (4 + 1),
                        outputLimit - (4 + 1));
                break;
            case DataType.STRING:
                dictEntryEncodedSize = dictEntryCodec.encodeStrings(
                        dictStruct.dictEntryCount(),
                        dictStruct.dictEntriesAddr(),
                        outputAddr + (4 + 1),
                        outputLimit - (4 + 1));
                break;
            default:
                throw new RuntimeException("Illegal type: " + dictStruct.dataType());
        }
        if (dictEntryEncodedSize < 0) {
            return dictEntryEncodedSize;
        }

        Codec dataCodec = new RLEPackingHybridCodec(VarInteger.bitWidth(dictStruct.dictEntryCount() - 1));
        int dataEncodedSize = dataCodec.encodeInts(
                valCount,
                dictStruct.dataAddr(),
                outputAddr + 4 + 1 + dictEntryEncodedSize,
                outputLimit - (4 + 1 + dictEntryEncodedSize));
        return 4 + 1 + dictEntryEncodedSize + dataEncodedSize;
    }
<pre>
|  dictEntryCount | isDictEntryCompressed | dictEntryData | compressed value data(entry ids) |
         4                   1                  size?                size?
</pre>
indexr-vlt-segment/src/main/java/io/indexr/vlt/codec/dict/DictStructUtil.java