code: public void consume(int size, @NotNull ByteBufConsumer consumer) {
  		assert hasRemainingBytes(size);
  		ByteBuf buf = bufs[first];
  		if (buf.readRemaining() >= size) {
  			int newPos = buf.head() + size;
  			consumer.accept(buf);
  			buf.head(newPos);
  			if (!buf.canRead()) {
  				first = next(first);
  				buf.recycle();
  			}
  		} else {
  			buf = ByteBufPool.allocate(size);
  			drainTo(buf, size);
  			consumer.accept(buf);
  			buf.recycle();
  		}
  	}
docs: Consumes the first ByteBuf of the queue to the provided consumer
  if the ByteBuf has at least {@code size} bytes available for reading.
  If after consuming ByteBuf has no readable bytes left, it is recycled
  and {@code first} index is increased by 1 or set to the value 0 if it
  has run a full circle of the queue.
  <p>
  If the first ByteBuf of the queue doesn't have enough bytes available
  for reading, a new ByteBuf with {@code size} bytes is created, it contains
  all data from the queue's first ByteBuf. This new ByteBuf is consumed and
  then recycled.
  
  @param size the size of the ByteBuf to be consumed
  @param consumer a consumer for the ByteBuf