code: public void decode(ByteBuf in, List<Object> out, ByteBufAllocator allocator) {
          while (in.isReadable()) {
              final int startIndex = in.readerIndex();
  
              int lastReadIndex = in.forEachByte(LINE_END_FINDER);
  
              if (-1 == lastReadIndex) {
                  // Buffer end without line termination
                  if (null == incompleteBuffer) {
                      incompleteBuffer = allocator.buffer(DEFAULT_INITIAL_CAPACITY, maxLineLength);
                  }
  
                  /*Add to the incomplete buffer*/
                  incompleteBuffer.ensureWritable(in.readableBytes());
                  incompleteBuffer.writeBytes(in);
              } else {
                  ByteBuf lineBuf = in.readSlice(lastReadIndex - startIndex);
                  String line;
                  if (null != incompleteBuffer) {
                      line = incompleteBuffer.toString(encoding) + lineBuf.toString(encoding);
                      incompleteBuffer.release();
                      incompleteBuffer = null;
                  } else {
                      line = lineBuf.toString(encoding);
                  }
                  out.add(line);
                  in.skipBytes(1); // Skip new line character.
              }
          }
      }
docs: Reads the {@code in} buffer as much as it can and adds all the read lines into the {@code out} list. <p>
  If there is any outstanding data that is not read, it is stored into a temporary buffer and the next decode will
  prepend this data to the newly read data. <p>
  
  {@link #dispose()} must be called when the associated {@link ChannelHandler} is removed from the pipeline.
  
  @param in Buffer to decode.
  @param out List to add the read lines to.
  @param allocator Allocator to allocate new buffers, if required.