@@ -72,7 +72,7 @@ public BytesRefIterator iterator() {
7272 return new BytesRefIterator () {
7373 BytesRef ref = length () == 0 ? null : toBytesRef ();
7474 @ Override
75- public BytesRef next () throws IOException {
75+ public BytesRef next () {
7676 BytesRef r = ref ;
7777 ref = null ; // only return it once...
7878 return r ;
@@ -189,7 +189,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
189189 /**
190190 * A StreamInput that reads off a {@link BytesRefIterator}. This is used to provide
191191 * generic stream access to {@link BytesReference} instances without materializing the
192- * underlying bytes reference .
192+ * underlying bytes.
193193 */
194194 private final class BytesReferenceStreamInput extends StreamInput {
195195
@@ -239,7 +239,8 @@ public void readBytes(byte[] b, int bOffset, int len) throws IOException {
239239 throw new IndexOutOfBoundsException (
240240 "Cannot read " + len + " bytes from stream with length " + length + " at offset " + offset );
241241 }
242- read (b , bOffset , len );
242+ final int bytesRead = read (b , bOffset , len );
243+ assert bytesRead == len : bytesRead + " vs " + len ;
243244 }
244245
245246 @ Override
@@ -257,7 +258,7 @@ public int read(final byte[] b, final int bOffset, final int len) throws IOExcep
257258 if (offset >= length ) {
258259 return -1 ;
259260 }
260- final int numBytesToCopy = Math .min (len , length - offset );
261+ final int numBytesToCopy = Math .min (len , length - offset );
261262 int remaining = numBytesToCopy ; // copy the full length or the remaining part
262263 int destOffset = bOffset ;
263264 while (remaining > 0 ) {
@@ -293,8 +294,11 @@ protected void ensureCanReadBytes(int bytesToRead) throws EOFException {
293294
294295 @ Override
295296 public long skip (long n ) throws IOException {
296- final int skip = (int ) Math .min (Integer .MAX_VALUE , n );
297- final int numBytesSkipped = Math .min (skip , length () - offset ());
297+ if (n <= 0L ) {
298+ return 0L ;
299+ }
300+ assert offset () <= length () : offset () + " vs " + length ();
301+ final int numBytesSkipped = (int )Math .min (n , length () - offset ()); // definitely >= 0 and <= Integer.MAX_VALUE so casting is ok
298302 int remaining = numBytesSkipped ;
299303 while (remaining > 0 ) {
300304 maybeNextSlice ();
@@ -308,11 +312,16 @@ public long skip(long n) throws IOException {
308312
309313 @ Override
310314 public void reset () throws IOException {
311- iterator = iterator ();
312- slice = iterator .next ();
313- sliceStartOffset = 0 ;
314- sliceIndex = 0 ;
315- skip (mark );
315+ if (sliceStartOffset <= mark ) {
316+ sliceIndex = mark - sliceStartOffset ;
317+ } else {
318+ iterator = iterator ();
319+ slice = iterator .next ();
320+ sliceStartOffset = 0 ;
321+ sliceIndex = 0 ;
322+ final long skipped = skip (mark );
323+ assert skipped == mark : skipped + " vs " + mark ;
324+ }
316325 }
317326
318327 @ Override
@@ -322,8 +331,7 @@ public boolean markSupported() {
322331
323332 @ Override
324333 public void mark (int readLimit ) {
325- // readLimit is optional it only guarantees that the stream remembers data upto this limit but it can remember more
326- // which we do in our case
334+ // We ignore readLimit since the data is all in-memory and therefore we can reset the mark no matter how far we advance.
327335 this .mark = offset ();
328336 }
329337 }
0 commit comments