@Nullable
    public static ByteBuf accumulate(
            ByteBuf target, ByteBuf source, int targetAccumulationSize, int accumulatedSize) {
        if (accumulatedSize == 0 && source.readableBytes() >= targetAccumulationSize) {
            return source;
        }

        int copyLength = Math.min(source.readableBytes(), targetAccumulationSize - accumulatedSize);
        if (copyLength > 0) {
            target.writeBytes(source, copyLength);
        }

        if (accumulatedSize + copyLength == targetAccumulationSize) {
            return target;
        }

        return null;
    }
@Test
    void testAccumulateWithCopy() {
        int sourceLength = 128;
        int firstSourceReaderIndex = 32;
        int secondSourceReaderIndex = 0;
        int expectedAccumulationSize = 128;

        int firstAccumulationSize = sourceLength - firstSourceReaderIndex;
        int secondAccumulationSize = expectedAccumulationSize - firstAccumulationSize;

        ByteBuf firstSource =
                createSourceBuffer(sourceLength, firstSourceReaderIndex, firstAccumulationSize);
        ByteBuf secondSource =
                createSourceBuffer(sourceLength, secondSourceReaderIndex, secondAccumulationSize);

        ByteBuf target = Unpooled.buffer(expectedAccumulationSize);

        // If src does not have enough data, src will be copied into target and null will be
        // returned.
        ByteBuf accumulated =
                ByteBufUtils.accumulate(
                        target, firstSource, expectedAccumulationSize, target.readableBytes());
        assertThat(accumulated).isNull();
        assertThat(firstSource.readerIndex()).isEqualTo(sourceLength);
        assertThat(target.readableBytes()).isEqualTo(firstAccumulationSize);

        // The remaining data will be copied from the second buffer, and the target buffer will be
        // returned
        // after all data is accumulated.
        accumulated =
                ByteBufUtils.accumulate(
                        target, secondSource, expectedAccumulationSize, target.readableBytes());
        assertThat(accumulated).isSameAs(target);
        assertThat(secondSource.readerIndex())
                .isEqualTo(secondSourceReaderIndex + secondAccumulationSize);
        assertThat(target.readableBytes()).isEqualTo(expectedAccumulationSize);

        verifyBufferContent(accumulated, 0, expectedAccumulationSize);
    }