ChunkEncoder extends AbstractContentEncoder { @Override public int write(final ByteBuffer src) throws IOException { if (src == null) { return 0; } assertNotCompleted(); int total = 0; while (src.hasRemaining()) { int chunk = src.remaining(); int avail; avail = this.buffer.capacity(); avail -= 12; if (avail > 0) { if (avail < chunk) { chunk = avail; this.lineBuffer.clear(); this.lineBuffer.append(Integer.toHexString(chunk)); this.buffer.writeLine(this.lineBuffer); final int oldlimit = src.limit(); src.limit(src.position() + chunk); this.buffer.write(src); src.limit(oldlimit); } else { this.lineBuffer.clear(); this.lineBuffer.append(Integer.toHexString(chunk)); this.buffer.writeLine(this.lineBuffer); this.buffer.write(src); } this.lineBuffer.clear(); this.buffer.writeLine(this.lineBuffer); total += chunk; } if (this.buffer.length() >= this.chunkSizeHint || src.hasRemaining()) { final int bytesWritten = flushToChannel(); if (bytesWritten == 0) { break; } } } return total; } ChunkEncoder(
            final WritableByteChannel channel,
            final SessionOutputBuffer buffer,
            final BasicHttpTransportMetrics metrics,
            final int chunkSizeHint);  ChunkEncoder(
            final WritableByteChannel channel,
            final SessionOutputBuffer buffer,
            final BasicHttpTransportMetrics metrics); @Override int write(final ByteBuffer src); @Override void complete(final List<? extends Header> trailers); @Override String toString();  }
@Test public void testLimitedChannel() throws Exception { final WritableByteChannelMock channel = new WritableByteChannelMock(16, 16); final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(16, 16); final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics(); final ChunkEncoder encoder = new ChunkEncoder(channel, outbuf, metrics); channel.write(CodecTestUtils.wrap("0123456789ABCDEF")); outbuf.write(CodecTestUtils.wrap("0123456789ABCDEF")); final ByteBuffer src = CodecTestUtils.wrap("0123456789ABCDEF"); Assert.assertEquals(0, encoder.write(src)); Assert.assertEquals(0, encoder.write(src)); Assert.assertEquals(0, encoder.write(src)); channel.reset(); outbuf.flush(channel); channel.reset(); Assert.assertEquals(10, encoder.write(src)); channel.flush(); Assert.assertEquals(6, encoder.write(src)); channel.flush(); Assert.assertEquals(0, encoder.write(src)); outbuf.flush(channel); final String s = channel.dump(StandardCharsets.US_ASCII); Assert.assertEquals("4\r\n0123\r\n4\r\n4567\r\n2\r\n89\r\n4\r\nABCD\r\n2\r\nEF\r\n", s); }
@Test public void testBufferFragments() throws Exception { final WritableByteChannelMock channel = Mockito.spy(new WritableByteChannelMock(1024)); final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 1024); final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics(); final ChunkEncoder encoder = new ChunkEncoder(channel, outbuf, metrics, 1024); Assert.assertEquals(16, encoder.write(CodecTestUtils.wrap("0123456789ABCDEF"))); Assert.assertEquals(16, encoder.write(CodecTestUtils.wrap("0123456789ABCDEF"))); Assert.assertEquals(16, encoder.write(CodecTestUtils.wrap("0123456789ABCDEF"))); Mockito.verify(channel, Mockito.never()).write(ArgumentMatchers.<ByteBuffer>any()); outbuf.flush(channel); final String s = channel.dump(StandardCharsets.US_ASCII); Assert.assertEquals("10\r\n0123456789ABCDEF\r\n10\r\n0123456789ABCDEF\r\n" + "10\r\n0123456789ABCDEF\r\n", s); }
@Test public void testChunkExceed() throws Exception { final WritableByteChannelMock channel = new WritableByteChannelMock(64); final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(16, 16); final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics(); final ChunkEncoder encoder = new ChunkEncoder(channel, outbuf, metrics); final ByteBuffer src = CodecTestUtils.wrap("0123456789ABCDEF"); Assert.assertEquals(16, encoder.write(src)); Assert.assertEquals(0, src.remaining()); outbuf.flush(channel); final String s = channel.dump(StandardCharsets.US_ASCII); Assert.assertEquals("4\r\n0123\r\n4\r\n4567\r\n4\r\n89AB\r\n4\r\nCDEF\r\n", s); }