From bd772d127e3fb2da4a1de40b55b42382819f85d2 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Sat, 10 Mar 2018 00:46:45 -0800 Subject: [PATCH] FixedCompositeByteBuf should allow to access memoryAddress / array when wrap a single buffer. Motivation: We should allow to access the memoryAddress / array of the FixedCompositeByteBuf when it only wraps a single ByteBuf. We do the same for CompositeByteBuf. Modifications: - Check how many buffers FixedCompositeByteBuf wraps and depending on it delegate the access to the memoryAddress / array - Add unit tests. Result: Fixes [#7752]. --- .../netty/buffer/FixedCompositeByteBuf.java | 45 ++++++++++-- .../buffer/FixedCompositeByteBufTest.java | 73 +++++++++++++++++++ 2 files changed, 113 insertions(+), 5 deletions(-) diff --git a/buffer/src/main/java/io/netty/buffer/FixedCompositeByteBuf.java b/buffer/src/main/java/io/netty/buffer/FixedCompositeByteBuf.java index bb933ce7b1..b8d650663f 100644 --- a/buffer/src/main/java/io/netty/buffer/FixedCompositeByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/FixedCompositeByteBuf.java @@ -612,27 +612,62 @@ final class FixedCompositeByteBuf extends AbstractReferenceCountedByteBuf { @Override public boolean hasArray() { - return false; + switch (buffers.length) { + case 0: + return true; + case 1: + return buffer(0).hasArray(); + default: + return false; + } } @Override public byte[] array() { - throw new UnsupportedOperationException(); + switch (buffers.length) { + case 0: + return EmptyArrays.EMPTY_BYTES; + case 1: + return buffer(0).array(); + default: + throw new UnsupportedOperationException(); + } } @Override public int arrayOffset() { - throw new UnsupportedOperationException(); + switch (buffers.length) { + case 0: + return 0; + case 1: + return buffer(0).arrayOffset(); + default: + throw new UnsupportedOperationException(); + } } @Override public boolean hasMemoryAddress() { - return false; + switch (buffers.length) { + case 0: + return Unpooled.EMPTY_BUFFER.hasMemoryAddress(); + case 1: + return buffer(0).hasMemoryAddress(); + default: + return false; + } } @Override public long memoryAddress() { - throw new UnsupportedOperationException(); + switch (buffers.length) { + case 0: + return Unpooled.EMPTY_BUFFER.memoryAddress(); + case 1: + return buffer(0).memoryAddress(); + default: + throw new UnsupportedOperationException(); + } } @Override diff --git a/buffer/src/test/java/io/netty/buffer/FixedCompositeByteBufTest.java b/buffer/src/test/java/io/netty/buffer/FixedCompositeByteBufTest.java index 3d3edc854d..481c70fc84 100644 --- a/buffer/src/test/java/io/netty/buffer/FixedCompositeByteBufTest.java +++ b/buffer/src/test/java/io/netty/buffer/FixedCompositeByteBufTest.java @@ -16,6 +16,7 @@ package io.netty.buffer; +import org.junit.Assume; import org.junit.Test; import java.io.ByteArrayInputStream; @@ -377,4 +378,76 @@ public class FixedCompositeByteBufTest { ByteBuf buf = newBuffer(new ByteBuf[0]); buf.release(); } + + @Test + public void testHasMemoryAddressWithSingleBuffer() { + ByteBuf buf1 = directBuffer(10); + if (!buf1.hasMemoryAddress()) { + buf1.release(); + return; + } + ByteBuf buf = newBuffer(buf1); + assertTrue(buf.hasMemoryAddress()); + assertEquals(buf1.memoryAddress(), buf.memoryAddress()); + buf.release(); + } + + @Test + public void testHasMemoryAddressWhenEmpty() { + Assume.assumeTrue(EMPTY_BUFFER.hasMemoryAddress()); + ByteBuf buf = newBuffer(new ByteBuf[0]); + assertTrue(buf.hasMemoryAddress()); + assertEquals(EMPTY_BUFFER.memoryAddress(), buf.memoryAddress()); + buf.release(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testHasNoMemoryAddressWhenMultipleBuffers() { + ByteBuf buf1 = directBuffer(10); + if (!buf1.hasMemoryAddress()) { + buf1.release(); + return; + } + + ByteBuf buf2 = directBuffer(10); + ByteBuf buf = newBuffer(buf1, buf2); + assertFalse(buf.hasMemoryAddress()); + try { + buf.memoryAddress(); + fail(); + } finally { + buf.release(); + } + } + + @Test + public void testHasArrayWithSingleBuffer() { + ByteBuf buf1 = buffer(10); + ByteBuf buf = newBuffer(buf1); + assertTrue(buf.hasArray()); + assertArrayEquals(buf1.array(), buf.array()); + buf.release(); + } + + @Test + public void testHasArrayWhenEmpty() { + ByteBuf buf = newBuffer(new ByteBuf[0]); + assertTrue(buf.hasArray()); + assertArrayEquals(EMPTY_BUFFER.array(), buf.array()); + buf.release(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testHasNoArrayWhenMultipleBuffers() { + ByteBuf buf1 = buffer(10); + ByteBuf buf2 = buffer(10); + ByteBuf buf = newBuffer(buf1, buf2); + assertFalse(buf.hasArray()); + try { + buf.array(); + fail(); + } finally { + buf.release(); + } + } }