private static Arbitrary<Encoder> varDataEncoder(
        final List<Token> tokens,
        final MutableInteger cursor,
        final int endIdxInclusive,
        final CharGenerationMode charGenerationMode)
    {
        final List<Arbitrary<Encoder>> encoders = new ArrayList<>();

        while (cursor.get() <= endIdxInclusive)
        {
            final Token token = tokens.get(cursor.get());
            if (BEGIN_VAR_DATA != token.signal())
            {
                break;
            }
            final int nextFieldIdx = cursor.get() + token.componentTokenCount();

            cursor.increment(); // BEGIN_COMPOSITE
            cursor.increment(); // ENCODED
            final Token lengthToken = tokens.get(cursor.get());
            cursor.increment(); // ENCODED
            final Token varDataToken = tokens.get(cursor.get());
            cursor.increment(); // END_COMPOSITE

            final String characterEncoding = varDataToken.encoding().characterEncoding();
            final Arbitrary<Byte> arbitraryByte = null == characterEncoding ?
                Arbitraries.bytes() :
                chars(charGenerationMode).map(c -> (byte)c.charValue());
            encoders.add(arbitraryByte.list()
                .ofMaxSize((int)Math.min(lengthToken.encoding().applicableMaxValue().longValue(), 260L))
                .map(bytes -> (builder, buffer, ignored, limit) ->
                {
                    final int offset = limit.get();
                    final int elementLength = varDataToken.encoding().primitiveType().size();
                    limit.set(offset + lengthToken.encodedLength() + bytes.size() * elementLength);
                    builder.beginScope(token.name());
                    builder.appendLine().append("limit: ").append(offset).append(" -> ").append(limit.get());
                    builder.beginScope("length");
                    integerValueEncoder(lengthToken.encoding(), bytes.size())
                        .encode(builder, buffer, offset, null);
                    builder.endScope();
                    for (int i = 0; i < bytes.size(); i++)
                    {
                        final int dataOffset = offset + lengthToken.encodedLength() + i * elementLength;
                        builder.beginScope("[" + i + "]");
                        integerValueEncoder(varDataToken.encoding(), bytes.get(i))
                            .encode(builder, buffer, dataOffset, null);
                        builder.endScope();
                    }
                    builder.endScope();
                }));

            cursor.set(nextFieldIdx);
        }

        return combineArbitraryEncoders(encoders);
    }
This combinator adds duplicates to an arbitrary list. We prefer this to JQwik's built-in functionality,
as that is inefficient and dominates test runs.
<p>
This method works by generating a list of integers, which represent, in an alternating manner,
the number of items to skip before <i>selecting</i> an item to duplicate
and the number of items to skip before <i>inserting</i> the duplicate.

@param maxDuplicates the maximum number of duplicates to add
@param arbitrary     the arbitrary list to duplicate items in
@param <T>           the type of the list
@return an arbitrary list with duplicates
sbe-tool/src/propertyTest/java/uk/co/real_logic/sbe/properties/arbitraries/SbeArbitraries.java