ByteBuf (@NotNull ByteBuf input, int requiredLength, @NotNull ChannelHandlerContext context) { if (!input.isReadable()) { return null; } if (cumulation == null) { if (input.readableBytes() < requiredLength) { cumulation = input; input.retain(); input.touch(); return null; } else { return input; } } else { int currentAccumulatedByteCount = cumulation.readableBytes(); if ((currentAccumulatedByteCount + input.readableBytes()) < requiredLength) { CompositeByteBuf compositeByteBuf; if ((cumulation instanceof CompositeByteBuf)) { compositeByteBuf = (CompositeByteBuf)cumulation; } else { compositeByteBuf = context.alloc().compositeBuffer(DEFAULT_MAX_COMPOSITE_BUFFER_COMPONENTS); compositeByteBuf.addComponent(true, cumulation); cumulation = compositeByteBuf; } compositeByteBuf.addComponent(true, input); input.retain(); input.touch(); return null; } else { CompositeByteBuf buffer; if (cumulation instanceof CompositeByteBuf) { buffer = (CompositeByteBuf)cumulation; buffer.addComponent(input); } else { // may be it will be used by client to cumulate something - don't set artificial restriction (2) buffer = context.alloc().compositeBuffer(DEFAULT_MAX_COMPOSITE_BUFFER_COMPONENTS); buffer.addComponents(cumulation, input); } // we don't set writerIndex on addComponent, it is clear to set it to requiredLength here buffer.writerIndex(requiredLength); input.skipBytes(requiredLength - currentAccumulatedByteCount); input.retain(); input.touch(); cumulation = null; return buffer; } } }