@Test public void testDecodeLastNonEmptyBuffer() { EmbeddedChannel channel = new EmbeddedChannel(new ByteToMessageDecoder() { private boolean decodeLast; @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { int readable = in.readableBytes(); assertTrue(readable > 0); if (!decodeLast && readable == 1) { return; } out.add(in.readBytes(decodeLast ? readable : readable - 1)); } @Override protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { assertFalse(decodeLast); decodeLast = true; super.decodeLast(ctx, in, out); } }); byte[] bytes = new byte[1024]; PlatformDependent.threadLocalRandom().nextBytes(bytes); assertTrue(channel.writeInbound(Unpooled.wrappedBuffer(bytes))); assertBuffer(Unpooled.wrappedBuffer(bytes, 0, bytes.length - 1), (ByteBuf) channel.readInbound()); assertNull(channel.readInbound()); assertTrue(channel.finish()); assertBuffer(Unpooled.wrappedBuffer(bytes, bytes.length - 1, 1), (ByteBuf) channel.readInbound()); assertNull(channel.readInbound()); }
protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.isReadable()) { decodeRemovalReentryProtection(ctx, in, out); } }
ByteToMessageDecoder extends ChannelInboundHandlerAdapter { protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.isReadable()) { decodeRemovalReentryProtection(ctx, in, out); } } }
ByteToMessageDecoder extends ChannelInboundHandlerAdapter { protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.isReadable()) { decodeRemovalReentryProtection(ctx, in, out); } } protected  ByteToMessageDecoder(); }
ByteToMessageDecoder extends ChannelInboundHandlerAdapter { protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.isReadable()) { decodeRemovalReentryProtection(ctx, in, out); } } protected  ByteToMessageDecoder(); void setSingleDecode(boolean singleDecode); boolean isSingleDecode(); void setCumulator(Cumulator cumulator); void setDiscardAfterReads(int discardAfterReads); @Override final void handlerRemoved(ChannelHandlerContext ctx); @Override void channelRead(ChannelHandlerContext ctx, Object msg); @Override void channelReadComplete(ChannelHandlerContext ctx); @Override void channelInactive(ChannelHandlerContext ctx); @Override void userEventTriggered(ChannelHandlerContext ctx, Object evt); }
ByteToMessageDecoder extends ChannelInboundHandlerAdapter { protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.isReadable()) { decodeRemovalReentryProtection(ctx, in, out); } } protected  ByteToMessageDecoder(); void setSingleDecode(boolean singleDecode); boolean isSingleDecode(); void setCumulator(Cumulator cumulator); void setDiscardAfterReads(int discardAfterReads); @Override final void handlerRemoved(ChannelHandlerContext ctx); @Override void channelRead(ChannelHandlerContext ctx, Object msg); @Override void channelReadComplete(ChannelHandlerContext ctx); @Override void channelInactive(ChannelHandlerContext ctx); @Override void userEventTriggered(ChannelHandlerContext ctx, Object evt); static final Cumulator MERGE_CUMULATOR; static final Cumulator COMPOSITE_CUMULATOR; }