docs: protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
          if (lineBasedDecoder != null) {
              return lineBasedDecoder.decode(ctx, buffer);
          }
          // Try all delimiters and choose the delimiter which yields the shortest frame.
          int minFrameLength = Integer.MAX_VALUE;
          ByteBuf minDelim = null;
          for (ByteBuf delim : delimiters) {
              int frameLength = indexOf(buffer, delim);
              if (frameLength >= 0 && frameLength < minFrameLength) {
                  minFrameLength = frameLength;
                  minDelim = delim;
              }
          }
  
          if (minDelim != null) {
              int minDelimLength = minDelim.capacity();
              ByteBuf frame;
  
              if (discardingTooLongFrame) {
                  // We've just finished discarding a very large frame.
                  // Go back to the initial state.
                  discardingTooLongFrame = false;
                  buffer.skipBytes(minFrameLength + minDelimLength);
  
                  int tooLongFrameLength = this.tooLongFrameLength;
                  this.tooLongFrameLength = 0;
                  if (!failFast) {
                      fail(tooLongFrameLength);
                  }
                  return null;
              }
  
              if (minFrameLength > maxFrameLength) {
                  // Discard read frame.
                  buffer.skipBytes(minFrameLength + minDelimLength);
                  fail(minFrameLength);
                  return null;
              }
  
              if (stripDelimiter) {
                  frame = buffer.readRetainedSlice(minFrameLength);
                  buffer.skipBytes(minDelimLength);
              } else {
                  frame = buffer.readRetainedSlice(minFrameLength + minDelimLength);
              }
  
              return frame;
          } else if (emitLastLineWithoutDelimiter && !ctx.channel().isActive()) {
              minFrameLength = buffer.readableBytes();
              ByteBuf frame;
  
              if (discardingTooLongFrame) {
                  // We've just finished discarding a very large frame.
                  // Go back to the initial state.
                  discardingTooLongFrame = false;
                  buffer.skipBytes(minFrameLength);
  
                  int tooLongFrameLength = this.tooLongFrameLength;
                  this.tooLongFrameLength = 0;
                  if (!failFast) {
                      fail(tooLongFrameLength);
                  }
                  return null;
              }
  
              if (minFrameLength > maxFrameLength) {
                  // Discard read frame.
                  buffer.skipBytes(minFrameLength);
                  fail(minFrameLength);
                  return null;
              }
  
              frame = buffer.readRetainedSlice(minFrameLength);
  
              return frame;
          } else {
              if (!discardingTooLongFrame) {
                  if (buffer.readableBytes() > maxFrameLength) {
                      // Discard the content of the buffer until a delimiter is found.
                      tooLongFrameLength = buffer.readableBytes();
                      buffer.skipBytes(buffer.readableBytes());
                      discardingTooLongFrame = true;
                      if (failFast) {
                          fail(tooLongFrameLength);
                      }
                  }
              } else {
                  // Still discarding the buffer since a delimiter is not found.
                  tooLongFrameLength += buffer.readableBytes();
                  buffer.skipBytes(buffer.readableBytes());
              }
              return null;
          }
      }