Merge pull request #33 from netty/read-comp-byte-cursor

Make ReadableComponent expose ByteCursors
This commit is contained in:
Chris Vest 2021-03-01 09:51:49 +01:00 committed by GitHub
commit f14a77961c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 0 deletions

View File

@ -72,5 +72,18 @@ public interface ReadableComponent {
* @return A new {@link ByteBuffer}, with its own position and limit, for this memory component.
*/
ByteBuffer readableBuffer();
/**
* Open a cursor to iterate the readable bytes of this component.
* Any offsets internal to the component are not modified by the cursor.
* <p>
* Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
* the internal offsets of the component (such as {@link Buffer#readerOffset()} and {@link Buffer#writerOffset()})
* are not modified while the iteration takes place. Otherwise unpredictable behaviour might result.
*
* @return A {@link ByteCursor} for iterating the readable bytes of this buffer.
* @see Buffer#openCursor()
*/
ByteCursor openCursor();
// todo for Unsafe-based impl, DBB.attachment needs to keep underlying memory alive
}

View File

@ -300,6 +300,11 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
}
}
@Override
public ByteCursor openCursor() {
return openCursor(readerOffset(), readableBytes());
}
@Override
public ByteCursor openCursor(int fromOffset, int length) {
if (seg == CLOSED_SEGMENT) {
@ -364,6 +369,12 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
};
}
@Override
public ByteCursor openReverseCursor() {
int woff = writerOffset();
return openReverseCursor(woff == 0? 0 : woff - 1, readableBytes());
}
@Override
public ByteCursor openReverseCursor(int fromOffset, int length) {
if (seg == CLOSED_SEGMENT) {

View File

@ -2890,6 +2890,39 @@ public class BufferTest {
}
}
@ParameterizedTest
@MethodSource("allocators")
public void forEachReadableMustExposeByteCursors(Fixture fixture) {
try (BufferAllocator allocator = fixture.createAllocator();
Buffer buf = allocator.allocate(32).order(BIG_ENDIAN)) {
buf.writeLong(0x0102030405060708L);
buf.writeLong(0x1112131415161718L);
assertEquals(0x01020304, buf.readInt());
try (Buffer actualData = allocator.allocate(buf.readableBytes()).order(BIG_ENDIAN);
Buffer expectedData = allocator.allocate(12).order(BIG_ENDIAN)) {
expectedData.writeInt(0x05060708);
expectedData.writeInt(0x11121314);
expectedData.writeInt(0x15161718);
buf.forEachReadable(0, (i, component) -> {
ByteCursor forward = component.openCursor();
while (forward.readLong()) {
actualData.writeLong(forward.getLong());
}
while (forward.readByte()) {
actualData.writeByte(forward.getByte());
}
return true;
});
assertEquals(expectedData.readableBytes(), actualData.readableBytes());
while (expectedData.readableBytes() > 0) {
assertEquals(expectedData.readByte(), actualData.readByte());
}
}
}
}
@ParameterizedTest
@MethodSource("nonCompositeAllocators")
public void forEachWritableMustVisitBuffer(Fixture fixture) {