@NotNull
	public ByteBuf takeAtLeast(int size) {
		assert hasRemainingBytes(size);
		if (size == 0) return ByteBuf.empty();
		ByteBuf buf = bufs[first];
		if (buf.readRemaining() >= size) {
			first = next(first);
			return buf;
		}
		ByteBuf result = ByteBufPool.allocate(size);
		drainTo(result.array(), 0, size);
		result.moveTail(size);
		return result;
	}
@ NotNull public ByteBuf takeAtLeast ( int size ) { assert hasRemainingBytes ( size ) ; if ( size == 0 ) return ByteBuf . empty ( ) ; ByteBuf buf = bufs [ first ] ; if ( buf . readRemaining ( ) >= size ) { first = next ( first ) ; return buf ; } ByteBuf result = ByteBufPool . allocate ( size ) ; drainTo ( result . array ( ) , 0 , size ) ; result . moveTail ( size ) ; return result ; }
Creates and returns a ByteBuf which contains at least {@code size}
bytes from queue's first ByteBuf if the latter contains enough bytes.
Then {@code first} index is increased by 1 or set to the value 0 if it
has run a full circle of the queue.
<p>
Otherwise a new ByteBuf is allocated from the {@link ByteBufPool} with
{@code size} bytes which contains all data from the queue's first ByteBuf.

@param size the minimum size of returned ByteBuf
@return a ByteBuf which contains at least {@code size} bytes