protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        try {
            while (in.isReadable()) {
                int outSize = out.size();

                if (outSize > 0) {
                    fireChannelRead(ctx, out, outSize);
                    out.clear();

                    // Check if this handler was removed before continuing with decoding.
                    // If it was removed, it is not safe to continue to operate on the buffer.
                    //
                    // See:
                    // - https://github.com/netty/netty/issues/4635
                    if (ctx.isRemoved()) {
                        break;
                    }
                    outSize = 0;
                }

                int oldInputLength = in.readableBytes();
                decodeRemovalReentryProtection(ctx, in, out);

                // Check if this handler was removed before continuing the loop.
                // If it was removed, it is not safe to continue to operate on the buffer.
                //
                // See https://github.com/netty/netty/issues/1664
                if (ctx.isRemoved()) {
                    break;
                }

                if (outSize == out.size()) {
                    if (oldInputLength == in.readableBytes()) {
                        break;
                    } else {
                        continue;
                    }
                }

                if (oldInputLength == in.readableBytes()) {
                    throw new DecoderException(
                            StringUtil.simpleClassName(getClass()) +
                                    ".decode() did not read anything but decoded a message.");
                }

                if (isSingleDecode()) {
                    break;
                }
            }
        } catch (DecoderException e) {
            throw e;
        } catch (Exception cause) {
            throw new DecoderException(cause);
        }
    }
protected void callDecode ( ChannelHandlerContext ctx , ByteBuf in , List < Object > out ) { try { while ( in . isReadable ( ) ) { int outSize = out . size ( ) ; if ( outSize > 0 ) { fireChannelRead ( ctx , out , outSize ) ; out . clear ( ) ; if ( ctx . isRemoved ( ) ) { break ; } outSize = 0 ; } int oldInputLength = in . readableBytes ( ) ; decodeRemovalReentryProtection ( ctx , in , out ) ; if ( ctx . isRemoved ( ) ) { break ; } if ( outSize == out . size ( ) ) { if ( oldInputLength == in . readableBytes ( ) ) { break ; } else { continue ; } } if ( oldInputLength == in . readableBytes ( ) ) { throw new DecoderException ( StringUtil . simpleClassName ( getClass ( ) ) + ".decode() did not read anything but decoded a message." ) ; } if ( isSingleDecode ( ) ) { break ; } } } catch ( DecoderException e ) { throw e ; } catch ( Exception cause ) { throw new DecoderException ( cause ) ; } }
Called once data should be decoded from the given {@link ByteBuf}. This method will call
{@link #decode(ChannelHandlerContext, ByteBuf, List)} as long as decoding should take place.

@param ctx           the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to
@param in            the {@link ByteBuf} from which to read data
@param out           the {@link List} to which decoded messages should be added