Skip to content
This repository was archived by the owner on Dec 12, 2022. It is now read-only.

Commit 6175f8f

Browse files
committed
Make ReadableComponent expose ByteCursors
Motivation: Another way to process the readable data in a buffer. This might be faster for composite buffers, since their byte cursors are a bit slower than the MemSegBuffer due to the indirections and more complicated logic. Modification: ReadableComponent now have openCursor method. Note that we *don't* add an openReverseCursor method on ReadableComponent. The reason is that forEachReadable iterates the components in the forward direction, and it's really confusing to then iterate the bytes in a backwards direction. Working with both directions at the same time is very error prone. Result: It is now possible to process readable components with byte cursors.
1 parent 63df380 commit 6175f8f

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

src/main/java/io/netty/buffer/api/ReadableComponent.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,18 @@ public interface ReadableComponent {
7272
* @return A new {@link ByteBuffer}, with its own position and limit, for this memory component.
7373
*/
7474
ByteBuffer readableBuffer();
75+
76+
/**
77+
* Open a cursor to iterate the readable bytes of this component.
78+
* Any offsets internal to the component are not modified by the cursor.
79+
* <p>
80+
* Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
81+
* the internal offsets of the component (such as {@link Buffer#readerOffset()} and {@link Buffer#writerOffset()})
82+
* are not modified while the iteration takes place. Otherwise unpredictable behaviour might result.
83+
*
84+
* @return A {@link ByteCursor} for iterating the readable bytes of this buffer.
85+
* @see Buffer#openCursor()
86+
*/
87+
ByteCursor openCursor();
7588
// todo for Unsafe-based impl, DBB.attachment needs to keep underlying memory alive
7689
}

src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@ public void copyInto(int srcPos, Buffer dest, int destPos, int length) {
300300
}
301301
}
302302

303+
@Override
304+
public ByteCursor openCursor() {
305+
return openCursor(readerOffset(), readableBytes());
306+
}
307+
303308
@Override
304309
public ByteCursor openCursor(int fromOffset, int length) {
305310
if (seg == CLOSED_SEGMENT) {
@@ -364,6 +369,12 @@ public int bytesLeft() {
364369
};
365370
}
366371

372+
@Override
373+
public ByteCursor openReverseCursor() {
374+
int woff = writerOffset();
375+
return openReverseCursor(woff == 0? 0 : woff - 1, readableBytes());
376+
}
377+
367378
@Override
368379
public ByteCursor openReverseCursor(int fromOffset, int length) {
369380
if (seg == CLOSED_SEGMENT) {

src/test/java/io/netty/buffer/api/BufferTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2890,6 +2890,39 @@ public void forEachReadableMustAllowCollectingBuffersInArray(Fixture fixture) {
28902890
}
28912891
}
28922892

2893+
@ParameterizedTest
2894+
@MethodSource("allocators")
2895+
public void forEachReadableMustExposeByteCursors(Fixture fixture) {
2896+
try (BufferAllocator allocator = fixture.createAllocator();
2897+
Buffer buf = allocator.allocate(32).order(BIG_ENDIAN)) {
2898+
buf.writeLong(0x0102030405060708L);
2899+
buf.writeLong(0x1112131415161718L);
2900+
assertEquals(0x01020304, buf.readInt());
2901+
try (Buffer actualData = allocator.allocate(buf.readableBytes()).order(BIG_ENDIAN);
2902+
Buffer expectedData = allocator.allocate(12).order(BIG_ENDIAN)) {
2903+
expectedData.writeInt(0x05060708);
2904+
expectedData.writeInt(0x11121314);
2905+
expectedData.writeInt(0x15161718);
2906+
2907+
buf.forEachReadable(0, (i, component) -> {
2908+
ByteCursor forward = component.openCursor();
2909+
while (forward.readLong()) {
2910+
actualData.writeLong(forward.getLong());
2911+
}
2912+
while (forward.readByte()) {
2913+
actualData.writeByte(forward.getByte());
2914+
}
2915+
return true;
2916+
});
2917+
2918+
assertEquals(expectedData.readableBytes(), actualData.readableBytes());
2919+
while (expectedData.readableBytes() > 0) {
2920+
assertEquals(expectedData.readByte(), actualData.readByte());
2921+
}
2922+
}
2923+
}
2924+
}
2925+
28932926
@ParameterizedTest
28942927
@MethodSource("nonCompositeAllocators")
28952928
public void forEachWritableMustVisitBuffer(Fixture fixture) {

0 commit comments

Comments
 (0)