diff --git a/src/main/java/io/netty/buffer/api/Buf.java b/src/main/java/io/netty/buffer/api/Buf.java index f95d0d7..946f473 100644 --- a/src/main/java/io/netty/buffer/api/Buf.java +++ b/src/main/java/io/netty/buffer/api/Buf.java @@ -295,69 +295,70 @@ public interface Buf extends Rc, BufAccessors { } /** - * Iterate the readable bytes of this buffer. The {@linkplain #readerOffset() reader offset} and - * {@linkplain #writerOffset() witer offset} are not modified by the iterator. + * Open a cursor to iterate the readable bytes of this buffer. The {@linkplain #readerOffset() reader offset} and + * {@linkplain #writerOffset() witer offset} are not modified by the cursor. *

- * Care should be taken to ensure that the buffers lifetime extends beyond the iteration, and the - * {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified while - * the iteration takes place. Otherwise unpredictable behaviour might result. + * Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that + * the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified + * while the iteration takes place. Otherwise unpredictable behaviour might result. * - * @return A {@link ByteIterator} for the readable bytes of this buffer. + * @return A {@link ByteCursor} for iterating the readable bytes of this buffer. */ - default ByteIterator iterate() { - return iterate(readerOffset(), readableBytes()); + default ByteCursor openCursor() { + return openCursor(readerOffset(), readableBytes()); } /** - * Iterate the given number bytes of this buffer, starting at the given offset. + * Open a cursor to iterate the given number bytes of this buffer, starting at the given offset. * The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() witer offset} are not modified by - * the iterator. + * the cursor. *

- * Care should be taken to ensure that the buffers lifetime extends beyond the iteration, and the - * {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified while - * the iteration takes place. Otherwise unpredictable behaviour might result. + * Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that + * the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified + * while the iteration takes place. Otherwise unpredictable behaviour might result. * * @param fromOffset The offset into the buffer where iteration should start. * The first byte read from the iterator will be the byte at this offset. * @param length The number of bytes to iterate. - * @return A {@link ByteIterator} for the given stretch of bytes of this buffer. + * @return A {@link ByteCursor} for the given stretch of bytes of this buffer. * @throws IllegalArgumentException if the length is negative, or if the region given by the {@code fromOffset} and * the {@code length} reaches outside of the bounds of this buffer. */ - ByteIterator iterate(int fromOffset, int length); + ByteCursor openCursor(int fromOffset, int length); /** - * Iterate the readable bytes of this buffer, in reverse. The {@linkplain #readerOffset() reader offset} and - * {@linkplain #writerOffset() witer offset} are not modified by the iterator. + * Open a cursor to iterate the readable bytes of this buffer, in reverse. + * The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() witer offset} are not modified by + * the cursor. *

- * Care should be taken to ensure that the buffers lifetime extends beyond the iteration, and the - * {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified while - * the iteration takes place. Otherwise unpredictable behaviour might result. + * Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that + * the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified + * while the iteration takes place. Otherwise unpredictable behaviour might result. * - * @return A {@link ByteIterator} for the readable bytes of this buffer. + * @return A {@link ByteCursor} for the readable bytes of this buffer. */ - default ByteIterator iterateReverse() { + default ByteCursor openReverseCursor() { int woff = writerOffset(); - return iterateReverse(woff == 0? 0 : woff - 1, readableBytes()); + return openReverseCursor(woff == 0? 0 : woff - 1, readableBytes()); } /** - * Iterate the given number bytes of this buffer, in reverse, starting at the given offset. + * Open a cursor to iterate the given number bytes of this buffer, in reverse, starting at the given offset. * The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() witer offset} are not modified by - * the iterator. + * the cursor. *

- * Care should be taken to ensure that the buffers lifetime extends beyond the iteration, and the - * {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified while - * the iteration takes place. Otherwise unpredictable behaviour might result. + * Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that + * the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified + * while the iteration takes place. Otherwise unpredictable behaviour might result. * * @param fromOffset The offset into the buffer where iteration should start. * The first byte read from the iterator will be the byte at this offset. * @param length The number of bytes to iterate. - * @return A {@link ByteIterator} for the given stretch of bytes of this buffer. + * @return A {@link ByteCursor} for the given stretch of bytes of this buffer. * @throws IllegalArgumentException if the length is negative, or if the region given by the {@code fromOffset} and * the {@code length} reaches outside of the bounds of this buffer. */ - ByteIterator iterateReverse(int fromOffset, int length); + ByteCursor openReverseCursor(int fromOffset, int length); /** * Ensure that this buffer has {@linkplain #writableBytes() available space for writing} the given number of diff --git a/src/main/java/io/netty/buffer/api/ByteIterator.java b/src/main/java/io/netty/buffer/api/ByteCursor.java similarity index 55% rename from src/main/java/io/netty/buffer/api/ByteIterator.java rename to src/main/java/io/netty/buffer/api/ByteCursor.java index dbf40c0..f94bdeb 100644 --- a/src/main/java/io/netty/buffer/api/ByteIterator.java +++ b/src/main/java/io/netty/buffer/api/ByteCursor.java @@ -17,48 +17,57 @@ package io.netty.buffer.api; import io.netty.util.ByteProcessor; /** - * The ByteIterator scans through a sequence of bytes. + * The ByteCursor scans through a sequence of bytes. * This is similar to {@link ByteProcessor}, but for external iteration rather than internal iteration. * The external iteration allows the callers to control the pace of the iteration. * The API includes methods for reading {@code long}s as a batch of 8 bytes. * The long values are always in big-endian format, so that the highest-order byte in the long value, contain the byte - * that would otherwise have been returned by the next call to {@link #nextByte()}. + * that would otherwise have been returned by the next call to {@link #getByte()}. */ -public interface ByteIterator { +public interface ByteCursor { /** - * Check if the iterator has at least 8 bytes left. - * Note that when this method returns {@code false}, the {@link #hasNextByte()} can still return {@code true}. + * Check if the iterator has at least 8 bytes left, and if so, read those 8 bytes and move the cursor forward. + * The bytes are packed as a {@code long} value in big-endian format, such that the highest-order byte + * in the long, is the byte that would otherwise have been returned by the next call to {@link #getByte()}, + * after a call to {@link #readByte()}. + * The bytes (as a {@code long}) will then be available through the {@link #getLong()} method. + *

+ * Note that when this method returns {@code false}, the {@link #readByte()} can still return {@code true}. * It is recommended to have any long-processing loop be followed by a byte-processing loop for the 7 or fewer - * bytes that might form a tail in the iterator. + * bytes that might form a tail in the cursor. + *

+ * Also note that this method will not influence what is returned the {@link #getByte()} method. * - * @return {@code true} if a call to {@link #nextLong()} would succeed, otherwise {@code false}. + * @return {@code true} if the cursor read 8 bytes and moved forward, otherwise {@code false}. */ - boolean hasNextLong(); + boolean readLong(); /** - * Read and return the next 8 bytes, and move the iterator position forward by 8 bytes. - * The bytes are packed and return as a {@code long} value in big-endian format, such that the highest-order byte - * in the long, is the byte that would otherwise have been returned by the next call to {@link #nextByte()}. + * Return the last 8 bytes read by {@link #readLong()}. + * If {@link #readLong()} has not been called on this cursor before, then {@code -1} is returned. * - * @return The next 8 bytes in big-endian format. - * @throws java.util.NoSuchElementException If the iterator has fewer than 8 bytes left. + * @return The 8 bytes, in big-endian format, that was read by the most recent successful call to + * {@link #readLong()}. */ - long nextLong(); + long getLong(); /** - * Check if the iterator has at least one byte left. + * Check if the iterator has at least one byte left, and if so, read that byte and move the cursor forward. + * The byte will then be available through the {@link #getByte()}. + *

+ * Note that this method will not influence what is returned from the {@link #getLong()} method. * - * @return {@code true} if the next call to {@link #nextByte()} would succeed, otherwise {@code false}. + * @return {@code true} if the cursor read a byte and moved forward, otherwise {@code false}. */ - boolean hasNextByte(); + boolean readByte(); /** - * Read and return the next byte, and move the iterator position] forward by one byte. + * Return the last byte that was read by {@link #readByte()}. + * If {@link #readByte()} has not been called on this cursor before, then {@code -1} is returned. * - * @return The next byte. - * @throws java.util.NoSuchElementException If the iterator has no more bytes left. + * @return The next byte that was read by the most recent successful call to {@link #readByte()}. */ - byte nextByte(); + byte getByte(); /** * The current position of this iterator into the underlying sequence of bytes. @@ -85,14 +94,10 @@ public interface ByteIterator { */ default int process(ByteProcessor processor) { boolean requestMore = true; - int index = currentOffset(); - if (hasNextByte()) { - byte val = nextByte(); - while ((requestMore = processor.process(val)) && hasNextByte()) { - val = nextByte(); - index++; - } + int count = 0; + while (readByte() && (requestMore = processor.process(getByte()))) { + count++; } - return requestMore? -1 : index; + return requestMore? -1 : count; } } diff --git a/src/main/java/io/netty/buffer/api/CompositeBuf.java b/src/main/java/io/netty/buffer/api/CompositeBuf.java index 3492b0e..0f1346e 100644 --- a/src/main/java/io/netty/buffer/api/CompositeBuf.java +++ b/src/main/java/io/netty/buffer/api/CompositeBuf.java @@ -18,7 +18,6 @@ package io.netty.buffer.api; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; -import java.util.NoSuchElementException; import java.util.Objects; final class CompositeBuf extends RcSupport implements Buf { @@ -293,18 +292,17 @@ final class CompositeBuf extends RcSupport implements Buf { // Iterate in reverse to account for src and dest buffer overlap. // todo optimise by delegating to constituent buffers. - var itr = iterateReverse(srcPos + length - 1, length); + var cursor = openReverseCursor(srcPos + length - 1, length); ByteOrder prevOrder = dest.order(); // We read longs in BE, in reverse, so they need to be flipped for writing. dest.order(ByteOrder.LITTLE_ENDIAN); try { - while (itr.hasNextLong()) { - long val = itr.nextLong(); + while (cursor.readLong()) { length -= Long.BYTES; - dest.setLong(destPos + length, val); + dest.setLong(destPos + length, cursor.getLong()); } - while (itr.hasNextByte()) { - dest.setByte(destPos + --length, itr.nextByte()); + while (cursor.readByte()) { + dest.setByte(destPos + --length, cursor.getByte()); } } finally { dest.order(prevOrder); @@ -312,7 +310,7 @@ final class CompositeBuf extends RcSupport implements Buf { } @Override - public ByteIterator iterate(int fromOffset, int length) { + public ByteCursor openCursor(int fromOffset, int length) { if (fromOffset < 0) { throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.'); } @@ -326,77 +324,94 @@ final class CompositeBuf extends RcSupport implements Buf { int startBufferIndex = searchOffsets(fromOffset); int off = fromOffset - offsets[startBufferIndex]; Buf startBuf = bufs[startBufferIndex]; - ByteIterator startIterator = startBuf.iterate(off, Math.min(startBuf.capacity() - off, length)); - return new ByteIterator() { + ByteCursor startCursor = startBuf.openCursor(off, Math.min(startBuf.capacity() - off, length)); + return new ByteCursor() { int index = fromOffset; final int end = fromOffset + length; int bufferIndex = startBufferIndex; - ByteIterator itr = startIterator; + int initOffset = startCursor.currentOffset(); + ByteCursor cursor = startCursor; + long longValue = -1; + byte byteValue = -1; @Override - public boolean hasNextLong() { - return bytesLeft() >= Long.BYTES; - } - - @Override - public long nextLong() { - if (itr.hasNextLong()) { - long val = itr.nextLong(); - index += Long.BYTES; - return val; + public boolean readLong() { + if (cursor.readLong()) { + longValue = cursor.getLong(); + return true; } - if (!hasNextLong()) { - throw new NoSuchElementException(); + if (bytesLeft() >= Long.BYTES) { + longValue = nextLongFromBytes(); + return true; } - return nextLongFromBytes(); // Leave index increments to 'nextByte' + return false; } private long nextLongFromBytes() { + if (cursor.bytesLeft() == 0) { + nextCursor(); + if (cursor.readLong()) { + return cursor.getLong(); + } + } long val = 0; for (int i = 0; i < 8; i++) { + readByte(); val <<= 8; - val |= nextByte(); + val |= getByte(); } return val; } @Override - public boolean hasNextByte() { - return index < end; + public long getLong() { + return longValue; } @Override - public byte nextByte() { - if (itr.hasNextByte()) { - byte val = itr.nextByte(); - index++; - return val; + public boolean readByte() { + if (cursor.readByte()) { + byteValue = cursor.getByte(); + return true; } - if (!hasNextByte()) { - throw new NoSuchElementException(); + if (bytesLeft() > 0) { + nextCursor(); + cursor.readByte(); + byteValue = cursor.getByte(); + return true; } + return false; + } + + private void nextCursor() { bufferIndex++; Buf nextBuf = bufs[bufferIndex]; - itr = nextBuf.iterate(0, Math.min(nextBuf.capacity(), bytesLeft())); - byte val = itr.nextByte(); - index++; - return val; + cursor = nextBuf.openCursor(0, Math.min(nextBuf.capacity(), bytesLeft())); + initOffset = 0; + } + + @Override + public byte getByte() { + return byteValue; } @Override public int currentOffset() { + int currOff = cursor.currentOffset(); + index += currOff - initOffset; + initOffset = currOff; return index; } @Override public int bytesLeft() { - return end - index; + return end - currentOffset(); } }; } @Override - public ByteIterator iterateReverse(int fromOffset, int length) { + public ByteCursor openReverseCursor(int fromOffset, int length) { if (fromOffset < 0) { throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.'); } @@ -410,70 +425,90 @@ final class CompositeBuf extends RcSupport implements Buf { int startBufferIndex = searchOffsets(fromOffset); int off = fromOffset - offsets[startBufferIndex]; Buf startBuf = bufs[startBufferIndex]; - ByteIterator startIterator = startBuf.iterateReverse(off, Math.min(off + 1, length)); - return new ByteIterator() { + ByteCursor startCursor = startBuf.openReverseCursor(off, Math.min(off + 1, length)); + return new ByteCursor() { int index = fromOffset; final int end = fromOffset - length; int bufferIndex = startBufferIndex; - ByteIterator itr = startIterator; + int initOffset = startCursor.currentOffset(); + ByteCursor cursor = startCursor; + long longValue = -1; + byte byteValue = -1; @Override - public boolean hasNextLong() { - return bytesLeft() >= Long.BYTES; - } - - @Override - public long nextLong() { - if (itr.hasNextLong()) { - index -= Long.BYTES; - return itr.nextLong(); + public boolean readLong() { + if (cursor.readLong()) { + longValue = cursor.getLong(); + return true; } - if (!hasNextLong()) { - throw new NoSuchElementException(); + if (bytesLeft() >= Long.BYTES) { + longValue = nextLongFromBytes(); + return true; } - return nextLongFromBytes(); // Leave index increments to 'nextByte' + return false; } private long nextLongFromBytes() { + if (cursor.bytesLeft() == 0) { + nextCursor(); + if (cursor.readLong()) { + return cursor.getLong(); + } + } long val = 0; for (int i = 0; i < 8; i++) { + readByte(); val <<= 8; - val |= nextByte(); + val |= getByte(); } return val; } @Override - public boolean hasNextByte() { - return index > end; + public long getLong() { + return longValue; } @Override - public byte nextByte() { - if (itr.hasNextByte()) { - byte val = itr.nextByte(); - index--; - return val; + public boolean readByte() { + if (cursor.readByte()) { + byteValue = cursor.getByte(); + return true; } - if (!hasNextByte()) { - throw new NoSuchElementException(); + if (bytesLeft() > 0) { + nextCursor(); + cursor.readByte(); + byteValue = cursor.getByte(); + return true; } + return false; + } + + private void nextCursor() { bufferIndex--; Buf nextBuf = bufs[bufferIndex]; - itr = nextBuf.iterateReverse(nextBuf.capacity() - 1, Math.min(nextBuf.capacity(), bytesLeft())); - byte val = itr.nextByte(); - index--; - return val; + int length = Math.min(nextBuf.capacity(), bytesLeft()); + int offset = nextBuf.capacity() - 1; + cursor = nextBuf.openReverseCursor(offset, length); + initOffset = offset; + } + + @Override + public byte getByte() { + return byteValue; } @Override public int currentOffset() { + int currOff = cursor.currentOffset(); + index -= initOffset - currOff; + initOffset = currOff; return index; } @Override public int bytesLeft() { - return index - end; + return currentOffset() - end; } }; } diff --git a/src/main/java/io/netty/buffer/api/memseg/MemSegBuf.java b/src/main/java/io/netty/buffer/api/memseg/MemSegBuf.java index 3367c57..cc5f2fb 100644 --- a/src/main/java/io/netty/buffer/api/memseg/MemSegBuf.java +++ b/src/main/java/io/netty/buffer/api/memseg/MemSegBuf.java @@ -18,7 +18,7 @@ package io.netty.buffer.api.memseg; import io.netty.buffer.api.Allocator; import io.netty.buffer.api.AllocatorControl; import io.netty.buffer.api.Buf; -import io.netty.buffer.api.ByteIterator; +import io.netty.buffer.api.ByteCursor; import io.netty.buffer.api.Drop; import io.netty.buffer.api.Owned; import io.netty.buffer.api.RcSupport; @@ -26,7 +26,6 @@ import jdk.incubator.foreign.MemorySegment; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.NoSuchElementException; import static jdk.incubator.foreign.MemoryAccess.getByteAtOffset; import static jdk.incubator.foreign.MemoryAccess.getCharAtOffset; @@ -158,18 +157,18 @@ class MemSegBuf extends RcSupport implements Buf { public void copyInto(int srcPos, Buf dest, int destPos, int length) { // todo optimise: specialise for MemSegBuf. // Iterate in reverse to account for src and dest buffer overlap. - var itr = iterateReverse(srcPos + length - 1, length); + var itr = openReverseCursor(srcPos + length - 1, length); ByteOrder prevOrder = dest.order(); // We read longs in BE, in reverse, so they need to be flipped for writing. dest.order(ByteOrder.LITTLE_ENDIAN); try { - while (itr.hasNextLong()) { - long val = itr.nextLong(); + while (itr.readLong()) { + long val = itr.getLong(); length -= Long.BYTES; dest.setLong(destPos + length, val); } - while (itr.hasNextByte()) { - dest.setByte(destPos + --length, itr.nextByte()); + while (itr.readByte()) { + dest.setByte(destPos + --length, itr.getByte()); } } finally { dest.order(prevOrder); @@ -177,7 +176,7 @@ class MemSegBuf extends RcSupport implements Buf { } @Override - public ByteIterator iterate(int fromOffset, int length) { + public ByteCursor openCursor(int fromOffset, int length) { if (fromOffset < 0) { throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.'); } @@ -188,39 +187,41 @@ class MemSegBuf extends RcSupport implements Buf { throw new IllegalArgumentException("The fromOffset+length is beyond the end of the buffer: " + "fromOffset=" + fromOffset + ", length=" + length + '.'); } - return new ByteIterator() { + return new ByteCursor() { final MemorySegment segment = seg; int index = fromOffset; final int end = index + length; + long longValue = -1; + byte byteValue = -1; @Override - public boolean hasNextLong() { - return index + Long.BYTES <= end; - } - - @Override - public long nextLong() { - if (!hasNextLong()) { - throw new NoSuchElementException("No 'long' value at offet " + currentOffset() + '.'); + public boolean readLong() { + if (index + Long.BYTES <= end) { + longValue = getLongAtOffset(segment, index, ByteOrder.BIG_ENDIAN); + index += Long.BYTES; + return true; } - long val = getLongAtOffset(segment, index, ByteOrder.BIG_ENDIAN); - index += Long.BYTES; - return val; + return false; } @Override - public boolean hasNextByte() { - return index < end; + public long getLong() { + return longValue; } @Override - public byte nextByte() { - if (!hasNextByte()) { - throw new NoSuchElementException("No 'byte' value at offet " + currentOffset() + '.'); + public boolean readByte() { + if (index < end) { + byteValue = getByteAtOffset(segment, index); + index++; + return true; } - byte val = getByteAtOffset(segment, index); - index++; - return val; + return false; + } + + @Override + public byte getByte() { + return byteValue; } @Override @@ -236,7 +237,7 @@ class MemSegBuf extends RcSupport implements Buf { } @Override - public ByteIterator iterateReverse(int fromOffset, int length) { + public ByteCursor openReverseCursor(int fromOffset, int length) { if (fromOffset < 0) { throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.'); } @@ -250,40 +251,42 @@ class MemSegBuf extends RcSupport implements Buf { throw new IllegalArgumentException("The fromOffset-length would underflow the buffer: " + "fromOffset=" + fromOffset + ", length=" + length + '.'); } - return new ByteIterator() { + return new ByteCursor() { final MemorySegment segment = seg; int index = fromOffset; final int end = index - length; + long longValue = -1; + byte byteValue = -1; @Override - public boolean hasNextLong() { - return index - Long.BYTES >= end; - } - - @Override - public long nextLong() { - if (!hasNextLong()) { - throw new NoSuchElementException("No 'long' value at offet " + currentOffset() + '.'); + public boolean readLong() { + if (index - Long.BYTES >= end) { + index -= 7; + longValue = getLongAtOffset(segment, index, ByteOrder.LITTLE_ENDIAN); + index--; + return true; } - index -= 7; - long val = getLongAtOffset(segment, index, ByteOrder.LITTLE_ENDIAN); - index--; - return val; + return false; } @Override - public boolean hasNextByte() { - return index > end; + public long getLong() { + return longValue; } @Override - public byte nextByte() { - if (!hasNextByte()) { - throw new NoSuchElementException("No 'byte' value at offet " + currentOffset() + '.'); + public boolean readByte() { + if (index > end) { + byteValue = getByteAtOffset(segment, index); + index--; + return true; } - byte val = getByteAtOffset(segment, index); - index--; - return val; + return false; + } + + @Override + public byte getByte() { + return byteValue; } @Override diff --git a/src/test/java/io/netty/buffer/api/BufTest.java b/src/test/java/io/netty/buffer/api/BufTest.java index 70d027f..0e4dbba 100644 --- a/src/test/java/io/netty/buffer/api/BufTest.java +++ b/src/test/java/io/netty/buffer/api/BufTest.java @@ -32,7 +32,6 @@ import java.nio.ByteOrder; import java.text.ParseException; import java.util.Arrays; import java.util.List; -import java.util.NoSuchElementException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -1051,130 +1050,134 @@ public class BufTest { } private static void checkByteIteration(Buf buf) { - var itr = buf.iterate(); - assertFalse(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); - assertEquals(0, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertThrows(NoSuchElementException.class, itr::nextByte); + var cursor = buf.openCursor(); + assertFalse(cursor.readByte()); + assertFalse(cursor.readLong()); + assertEquals(0, cursor.bytesLeft()); + assertEquals((byte) -1, cursor.getByte()); + assertEquals(-1L, cursor.getLong()); for (int i = 0; i < 0x27; i++) { buf.writeByte((byte) (i + 1)); } int roff = buf.readerOffset(); int woff = buf.writerOffset(); - itr = buf.iterate(); - assertEquals(0x27, itr.bytesLeft()); - assertTrue(itr.hasNextByte()); - assertTrue(itr.hasNextLong()); - assertEquals(0x0102030405060708L, itr.nextLong()); - assertEquals(0x1F, itr.bytesLeft()); - assertTrue(itr.hasNextLong()); - assertEquals(0x090A0B0C0D0E0F10L, itr.nextLong()); - assertTrue(itr.hasNextLong()); - assertEquals(0x17, itr.bytesLeft()); - assertEquals(0x1112131415161718L, itr.nextLong()); - assertTrue(itr.hasNextLong()); - assertEquals(0x0F, itr.bytesLeft()); - assertEquals(0x191A1B1C1D1E1F20L, itr.nextLong()); - assertFalse(itr.hasNextLong()); - assertEquals(7, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertTrue(itr.hasNextByte()); - assertEquals((byte) 0x21, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(6, itr.bytesLeft()); - assertEquals((byte) 0x22, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(5, itr.bytesLeft()); - assertEquals((byte) 0x23, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(4, itr.bytesLeft()); - assertEquals((byte) 0x24, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(3, itr.bytesLeft()); - assertEquals((byte) 0x25, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(2, itr.bytesLeft()); - assertEquals((byte) 0x26, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(1, itr.bytesLeft()); - assertEquals((byte) 0x27, itr.nextByte()); - assertFalse(itr.hasNextByte()); - assertEquals(0, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertThrows(NoSuchElementException.class, itr::nextByte); + cursor = buf.openCursor(); + assertEquals(0x27, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x01, cursor.getByte()); + assertEquals((byte) 0x01, cursor.getByte()); + assertTrue(cursor.readLong()); + assertEquals(0x0203040506070809L, cursor.getLong()); + assertEquals(0x0203040506070809L, cursor.getLong()); + assertEquals(0x1E, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x0A0B0C0D0E0F1011L, cursor.getLong()); + assertEquals(0x16, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x1213141516171819L, cursor.getLong()); + assertEquals(0x0E, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x1A1B1C1D1E1F2021L, cursor.getLong()); + assertEquals(6, cursor.bytesLeft()); + assertFalse(cursor.readLong()); + assertEquals(6, cursor.bytesLeft()); + assertEquals(0x1A1B1C1D1E1F2021L, cursor.getLong()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x22, cursor.getByte()); + assertEquals((byte) 0x22, cursor.getByte()); + assertEquals(5, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x23, cursor.getByte()); + assertEquals(4, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x24, cursor.getByte()); + assertEquals(3, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x25, cursor.getByte()); + assertEquals(2, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x26, cursor.getByte()); + assertEquals(1, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x27, cursor.getByte()); + assertEquals(0, cursor.bytesLeft()); + assertFalse(cursor.readByte()); + assertEquals((byte) 0x27, cursor.getByte()); + assertEquals((byte) 0x27, cursor.getByte()); + assertFalse(cursor.readLong()); assertEquals(roff, buf.readerOffset()); assertEquals(woff, buf.writerOffset()); } private static void checkByteIterationOfRegion(Buf buf) { - assertThrows(IllegalArgumentException.class, () -> buf.iterate(-1, 1)); - assertThrows(IllegalArgumentException.class, () -> buf.iterate(1, -1)); - assertThrows(IllegalArgumentException.class, () -> buf.iterate(buf.capacity(), 1)); - assertThrows(IllegalArgumentException.class, () -> buf.iterate(buf.capacity() - 1, 2)); - assertThrows(IllegalArgumentException.class, () -> buf.iterate(buf.capacity() - 2, 3)); + assertThrows(IllegalArgumentException.class, () -> buf.openCursor(-1, 1)); + assertThrows(IllegalArgumentException.class, () -> buf.openCursor(1, -1)); + assertThrows(IllegalArgumentException.class, () -> buf.openCursor(buf.capacity(), 1)); + assertThrows(IllegalArgumentException.class, () -> buf.openCursor(buf.capacity() - 1, 2)); + assertThrows(IllegalArgumentException.class, () -> buf.openCursor(buf.capacity() - 2, 3)); - var itr = buf.iterate(1, 0); - assertFalse(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); - assertEquals(0, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertThrows(NoSuchElementException.class, itr::nextByte); + var cursor = buf.openCursor(1, 0); + assertFalse(cursor.readByte()); + assertFalse(cursor.readLong()); + assertEquals(0, cursor.bytesLeft()); + assertEquals((byte) -1, cursor.getByte()); + assertEquals(-1L, cursor.getLong()); for (int i = 0; i < 0x27; i++) { buf.writeByte((byte) (i + 1)); } int roff = buf.readerOffset(); int woff = buf.writerOffset(); - itr = buf.iterate(buf.readerOffset() + 1, buf.readableBytes() - 2); - assertEquals(0x25, itr.bytesLeft()); - assertTrue(itr.hasNextByte()); - assertTrue(itr.hasNextLong()); - assertEquals(0x0203040506070809L, itr.nextLong()); - assertEquals(0x1D, itr.bytesLeft()); - assertTrue(itr.hasNextLong()); - assertEquals(0x0A0B0C0D0E0F1011L, itr.nextLong()); - assertTrue(itr.hasNextLong()); - assertEquals(0x15, itr.bytesLeft()); - assertEquals(0x1213141516171819L, itr.nextLong()); - assertTrue(itr.hasNextLong()); - assertEquals(0x0D, itr.bytesLeft()); - assertEquals(0x1A1B1C1D1E1F2021L, itr.nextLong()); - assertFalse(itr.hasNextLong()); - assertEquals(5, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertTrue(itr.hasNextByte()); - assertEquals((byte) 0x22, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(4, itr.bytesLeft()); - assertEquals((byte) 0x23, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(3, itr.bytesLeft()); - assertEquals((byte) 0x24, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(2, itr.bytesLeft()); - assertEquals((byte) 0x25, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(1, itr.bytesLeft()); - assertEquals((byte) 0x26, itr.nextByte()); - assertFalse(itr.hasNextByte()); - assertEquals(0, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertThrows(NoSuchElementException.class, itr::nextByte); + cursor = buf.openCursor(buf.readerOffset() + 1, buf.readableBytes() - 2); + assertEquals(0x25, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x02, cursor.getByte()); + assertEquals((byte) 0x02, cursor.getByte()); + assertTrue(cursor.readLong()); + assertEquals(0x030405060708090AL, cursor.getLong()); + assertEquals(0x1C, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x0B0C0D0E0F101112L, cursor.getLong()); + assertEquals(0x14, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x131415161718191AL, cursor.getLong()); + assertEquals(0x0C, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x1B1C1D1E1F202122L, cursor.getLong()); + assertEquals(4, cursor.bytesLeft()); + assertFalse(cursor.readLong()); + assertEquals(4, cursor.bytesLeft()); + assertEquals(0x1B1C1D1E1F202122L, cursor.getLong()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x23, cursor.getByte()); + assertEquals(3, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x24, cursor.getByte()); + assertEquals(2, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x25, cursor.getByte()); + assertEquals(1, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x26, cursor.getByte()); + assertEquals(0, cursor.bytesLeft()); + assertFalse(cursor.readByte()); + assertEquals(0, cursor.bytesLeft()); + assertEquals(0x1B1C1D1E1F202122L, cursor.getLong()); + assertEquals((byte) 0x26, cursor.getByte()); - itr = buf.iterate(buf.readerOffset() + 1, 2); - assertEquals(2, itr.bytesLeft()); - assertTrue(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); - assertEquals((byte) 0x02, itr.nextByte()); - assertEquals(1, itr.bytesLeft()); - assertTrue(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); - assertEquals((byte) 0x03, itr.nextByte()); - assertEquals(0, itr.bytesLeft()); - assertFalse(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); + cursor = buf.openCursor(buf.readerOffset() + 1, 2); + assertEquals(2, cursor.bytesLeft()); + assertFalse(cursor.readLong()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x02, cursor.getByte()); + assertEquals(1, cursor.bytesLeft()); + assertFalse(cursor.readLong()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x03, cursor.getByte()); + assertEquals(0, cursor.bytesLeft()); + assertFalse(cursor.readByte()); + assertFalse(cursor.readLong()); assertEquals(roff, buf.readerOffset()); assertEquals(woff, buf.writerOffset()); } @@ -1204,130 +1207,134 @@ public class BufTest { } private static void checkReverseByteIteration(Buf buf) { - var itr = buf.iterateReverse(); - assertFalse(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); - assertEquals(0, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertThrows(NoSuchElementException.class, itr::nextByte); + var cursor = buf.openReverseCursor(); + assertFalse(cursor.readByte()); + assertFalse(cursor.readLong()); + assertEquals(0, cursor.bytesLeft()); + assertEquals((byte) -1, cursor.getByte()); + assertEquals(-1L, cursor.getLong()); for (int i = 0; i < 0x27; i++) { buf.writeByte((byte) (i + 1)); } int roff = buf.readerOffset(); int woff = buf.writerOffset(); - itr = buf.iterateReverse(); - assertEquals(0x27, itr.bytesLeft()); - assertTrue(itr.hasNextByte()); - assertTrue(itr.hasNextLong()); - assertEquals(0x2726252423222120L, itr.nextLong()); - assertEquals(0x1F, itr.bytesLeft()); - assertTrue(itr.hasNextLong()); - assertEquals(0x1F1E1D1C1B1A1918L, itr.nextLong()); - assertTrue(itr.hasNextLong()); - assertEquals(0x17, itr.bytesLeft()); - assertEquals(0x1716151413121110L, itr.nextLong()); - assertTrue(itr.hasNextLong()); - assertEquals(0x0F, itr.bytesLeft()); - assertEquals(0x0F0E0D0C0B0A0908L, itr.nextLong()); - assertFalse(itr.hasNextLong()); - assertEquals(7, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertTrue(itr.hasNextByte()); - assertEquals((byte) 0x07, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(6, itr.bytesLeft()); - assertEquals((byte) 0x06, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(5, itr.bytesLeft()); - assertEquals((byte) 0x05, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(4, itr.bytesLeft()); - assertEquals((byte) 0x04, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(3, itr.bytesLeft()); - assertEquals((byte) 0x03, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(2, itr.bytesLeft()); - assertEquals((byte) 0x02, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(1, itr.bytesLeft()); - assertEquals((byte) 0x01, itr.nextByte()); - assertFalse(itr.hasNextByte()); - assertEquals(0, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertThrows(NoSuchElementException.class, itr::nextByte); + cursor = buf.openReverseCursor(); + assertEquals(0x27, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x27, cursor.getByte()); + assertEquals((byte) 0x27, cursor.getByte()); + assertTrue(cursor.readLong()); + assertEquals(0x262524232221201FL, cursor.getLong()); + assertEquals(0x1E, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x1E1D1C1B1A191817L, cursor.getLong()); + assertEquals(0x16, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x161514131211100FL, cursor.getLong()); + assertEquals(0x0E, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x0E0D0C0B0A090807L, cursor.getLong()); + assertEquals(6, cursor.bytesLeft()); + assertFalse(cursor.readLong()); + assertEquals(6, cursor.bytesLeft()); + assertEquals(0x0E0D0C0B0A090807L, cursor.getLong()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x06, cursor.getByte()); + assertEquals(5, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x05, cursor.getByte()); + assertEquals(4, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x04, cursor.getByte()); + assertEquals(3, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x03, cursor.getByte()); + assertEquals(2, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x02, cursor.getByte()); + assertEquals(1, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x01, cursor.getByte()); + assertEquals(0, cursor.bytesLeft()); + assertFalse(cursor.readByte()); + assertEquals((byte) 0x01, cursor.getByte()); + assertFalse(cursor.readByte()); + assertEquals(0, cursor.bytesLeft()); + assertEquals(0x0E0D0C0B0A090807L, cursor.getLong()); assertEquals(roff, buf.readerOffset()); assertEquals(woff, buf.writerOffset()); } private static void checkReverseByteIterationOfRegion(Buf buf) { - assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(-1, 0)); - assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(0, -1)); - assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(0, 2)); - assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(1, 3)); - assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(buf.capacity(), 0)); + assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(-1, 0)); + assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(0, -1)); + assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(0, 2)); + assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(1, 3)); + assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(buf.capacity(), 0)); - var itr = buf.iterateReverse(1, 0); - assertFalse(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); - assertEquals(0, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertThrows(NoSuchElementException.class, itr::nextByte); + var cursor = buf.openReverseCursor(1, 0); + assertFalse(cursor.readByte()); + assertFalse(cursor.readLong()); + assertEquals(0, cursor.bytesLeft()); + assertEquals((byte) -1, cursor.getByte()); + assertEquals(-1L, cursor.getLong()); for (int i = 0; i < 0x27; i++) { buf.writeByte((byte) (i + 1)); } int roff = buf.readerOffset(); int woff = buf.writerOffset(); - itr = buf.iterateReverse(buf.writerOffset() - 2, buf.readableBytes() - 2); - assertEquals(0x25, itr.bytesLeft()); - assertTrue(itr.hasNextByte()); - assertTrue(itr.hasNextLong()); - assertEquals(0x262524232221201FL, itr.nextLong()); - assertEquals(0x1D, itr.bytesLeft()); - assertTrue(itr.hasNextLong()); - assertEquals(0x1E1D1C1B1A191817L, itr.nextLong()); - assertTrue(itr.hasNextLong()); - assertEquals(0x15, itr.bytesLeft()); - assertEquals(0x161514131211100FL, itr.nextLong()); - assertTrue(itr.hasNextLong()); - assertEquals(0x0D, itr.bytesLeft()); - assertEquals(0x0E0D0C0B0A090807L, itr.nextLong()); - assertFalse(itr.hasNextLong()); - assertEquals(5, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertTrue(itr.hasNextByte()); - assertEquals((byte) 0x06, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(4, itr.bytesLeft()); - assertEquals((byte) 0x05, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(3, itr.bytesLeft()); - assertEquals((byte) 0x04, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(2, itr.bytesLeft()); - assertEquals((byte) 0x03, itr.nextByte()); - assertTrue(itr.hasNextByte()); - assertEquals(1, itr.bytesLeft()); - assertEquals((byte) 0x02, itr.nextByte()); - assertFalse(itr.hasNextByte()); - assertEquals(0, itr.bytesLeft()); - assertThrows(NoSuchElementException.class, itr::nextLong); - assertThrows(NoSuchElementException.class, itr::nextByte); + cursor = buf.openReverseCursor(buf.writerOffset() - 2, buf.readableBytes() - 2); + assertEquals(0x25, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x26, cursor.getByte()); + assertEquals((byte) 0x26, cursor.getByte()); + assertTrue(cursor.readLong()); + assertEquals(0x2524232221201F1EL, cursor.getLong()); + assertEquals(0x1C, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x1D1C1B1A19181716L, cursor.getLong()); + assertEquals(0x14, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x1514131211100F0EL, cursor.getLong()); + assertEquals(0x0C, cursor.bytesLeft()); + assertTrue(cursor.readLong()); + assertEquals(0x0D0C0B0A09080706L, cursor.getLong()); + assertEquals(4, cursor.bytesLeft()); + assertFalse(cursor.readLong()); + assertEquals(4, cursor.bytesLeft()); + assertEquals(0x0D0C0B0A09080706L, cursor.getLong()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x05, cursor.getByte()); + assertEquals(3, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x04, cursor.getByte()); + assertEquals(2, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x03, cursor.getByte()); + assertEquals(1, cursor.bytesLeft()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x02, cursor.getByte()); + assertEquals(0, cursor.bytesLeft()); + assertFalse(cursor.readByte()); + assertEquals((byte) 0x02, cursor.getByte()); + assertFalse(cursor.readByte()); + assertEquals(0, cursor.bytesLeft()); + assertEquals(0x0D0C0B0A09080706L, cursor.getLong()); - itr = buf.iterateReverse(buf.readerOffset() + 2, 2); - assertEquals(2, itr.bytesLeft()); - assertTrue(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); - assertEquals((byte) 0x03, itr.nextByte()); - assertEquals(1, itr.bytesLeft()); - assertTrue(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); - assertEquals((byte) 0x02, itr.nextByte()); - assertEquals(0, itr.bytesLeft()); - assertFalse(itr.hasNextByte()); - assertFalse(itr.hasNextLong()); + cursor = buf.openReverseCursor(buf.readerOffset() + 2, 2); + assertEquals(2, cursor.bytesLeft()); + assertFalse(cursor.readLong()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x03, cursor.getByte()); + assertEquals(1, cursor.bytesLeft()); + assertFalse(cursor.readLong()); + assertTrue(cursor.readByte()); + assertEquals((byte) 0x02, cursor.getByte()); + assertEquals(0, cursor.bytesLeft()); + assertFalse(cursor.readByte()); + assertFalse(cursor.readLong()); assertEquals(roff, buf.readerOffset()); assertEquals(woff, buf.writerOffset()); } diff --git a/src/test/java/io/netty/buffer/api/benchmarks/ByteIterationBenchmark.java b/src/test/java/io/netty/buffer/api/benchmarks/ByteIterationBenchmark.java index a0bfe37..ba3a38f 100644 --- a/src/test/java/io/netty/buffer/api/benchmarks/ByteIterationBenchmark.java +++ b/src/test/java/io/netty/buffer/api/benchmarks/ByteIterationBenchmark.java @@ -92,26 +92,26 @@ public class ByteIterationBenchmark { @Benchmark public long sum() { - var itr = buf.iterate(); + var itr = buf.openCursor(); long sum = 0; - while (itr.hasNextLong()) { - sum += itr.nextLong(); + while (itr.readLong()) { + sum += itr.getLong(); } - while (itr.hasNextByte()) { - sum += itr.nextByte(); + while (itr.readByte()) { + sum += itr.getByte(); } return sum; } @Benchmark public long sumReverse() { - var itr = buf.iterateReverse(); + var itr = buf.openReverseCursor(); long sum = 0; - while (itr.hasNextLong()) { - sum += itr.nextLong(); + while (itr.readLong()) { + sum += itr.getLong(); } - while (itr.hasNextByte()) { - sum += itr.nextByte(); + while (itr.readByte()) { + sum += itr.getByte(); } return sum; }