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].
This commit is contained in:
Norman Maurer 2018-03-10 00:46:45 -08:00 committed by Norman Maurer
parent 6eb9674bf5
commit bd772d127e
2 changed files with 113 additions and 5 deletions

View File

@ -612,28 +612,63 @@ final class FixedCompositeByteBuf extends AbstractReferenceCountedByteBuf {
@Override @Override
public boolean hasArray() { public boolean hasArray() {
switch (buffers.length) {
case 0:
return true;
case 1:
return buffer(0).hasArray();
default:
return false; return false;
} }
}
@Override @Override
public byte[] array() { public byte[] array() {
switch (buffers.length) {
case 0:
return EmptyArrays.EMPTY_BYTES;
case 1:
return buffer(0).array();
default:
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
}
@Override @Override
public int arrayOffset() { public int arrayOffset() {
switch (buffers.length) {
case 0:
return 0;
case 1:
return buffer(0).arrayOffset();
default:
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
}
@Override @Override
public boolean hasMemoryAddress() { public boolean hasMemoryAddress() {
switch (buffers.length) {
case 0:
return Unpooled.EMPTY_BUFFER.hasMemoryAddress();
case 1:
return buffer(0).hasMemoryAddress();
default:
return false; return false;
} }
}
@Override @Override
public long memoryAddress() { public long memoryAddress() {
switch (buffers.length) {
case 0:
return Unpooled.EMPTY_BUFFER.memoryAddress();
case 1:
return buffer(0).memoryAddress();
default:
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
}
@Override @Override
protected void deallocate() { protected void deallocate() {

View File

@ -16,6 +16,7 @@
package io.netty.buffer; package io.netty.buffer;
import org.junit.Assume;
import org.junit.Test; import org.junit.Test;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -377,4 +378,76 @@ public class FixedCompositeByteBufTest {
ByteBuf buf = newBuffer(new ByteBuf[0]); ByteBuf buf = newBuffer(new ByteBuf[0]);
buf.release(); 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();
}
}
} }