DynamicCompositeByteBuf { public ByteBuf readRetainedSlice(int length) { if (length > readableBytes) { throw new IndexOutOfBoundsException("length > readableBytes"); } if (length <= 0) { return Unpooled.buffer(0); } ByteBuf first = buffers.peek(); int firstLen = first.readableBytes(); if (length == firstLen) { readableBytes -= length; return buffers.removeFirst(); } else if (length < firstLen) { ByteBuf newBuf = first.readRetainedSlice(length); readableBytes -= length; return newBuf; } else { int capacity = 2; ByteBuf[] byteBufs = new ByteBuf[capacity]; int i = 0; while (length > 0 && readableBytes > 0) { ByteBuf newBuf; if (firstLen > length) { newBuf = first.readRetainedSlice(length); readableBytes -= length; length = 0; } else { newBuf = first; readableBytes -= firstLen; length -= firstLen; buffers.pop(); } if (i == capacity) { int newCapacity = capacity * 2; ByteBuf[] newByteBufs = new ByteBuf[newCapacity]; System.arraycopy(byteBufs, 0, newByteBufs, 0, capacity); byteBufs = newByteBufs; capacity = newCapacity; } byteBufs[i++] = newBuf; first = buffers.peek(); if (first == null) { break; } firstLen = first.readableBytes(); } if (i == capacity) { int maxComponentNum = (i > 2) ? i : 2; return new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, true, maxComponentNum, byteBufs); } else { ByteBuf[] outBufs = new ByteBuf[i]; System.arraycopy(byteBufs, 0, outBufs, 0, i); int maxComponentNum = (i > 2) ? i : 2; return new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, true, maxComponentNum, outBufs); } } } DynamicCompositeByteBuf();  DynamicCompositeByteBuf(int capacity);  DynamicCompositeByteBuf(ByteBuf buf);  DynamicCompositeByteBuf(ByteBuf[] bufs, int offset, int len); int readableBytes(); boolean isEmpty(); boolean hasArray(); byte[] array(); int arrayOffset(); int readerIndex(); boolean isReadable(); ByteBuf nettyByteBuf(); void addBuffer(ByteBuf buffer); ByteBuf readRetainedSlice(int length); ByteBuf retainedSlice(int length); void skipBytes(int length); DynamicCompositeByteBuf readBytes(byte[] dst); DynamicCompositeByteBuf readBytes(byte[] dst, int dstIndex, int length); byte readByte(); short readUnsignedByte(); short readShort(); short readShortLE(); int readUnsignedShort(); int readUnsignedShortLE(); int readInt(); int readIntLE(); long readLong(); long readLongLE(); char readChar(); float readFloat(); float readFloatLE(); double readDouble(); double readDoubleLE(); ByteOrder order(); void release(); @Override String toString();  }
@Test public void testReadRetainedSlice() { DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(); ByteBuf buf = Unpooled.buffer(8); buf.writeInt(1); buf.writeInt(2); compositeByteBuf.addBuffer(buf); ByteBuf compositeByteBuf2 = compositeByteBuf.readRetainedSlice(4); Assert.assertTrue(compositeByteBuf.readableBytes() == 4); Assert.assertTrue(compositeByteBuf.readInt() == 2); Assert.assertTrue(compositeByteBuf2.readableBytes() == 4); Assert.assertTrue(compositeByteBuf2.readInt() == 1); compositeByteBuf2.release(); Assert.assertTrue(buf.refCnt() == 0); }