@@ -72,7 +72,7 @@ public BytesRefIterator iterator() {
72
72
return new BytesRefIterator () {
73
73
BytesRef ref = length () == 0 ? null : toBytesRef ();
74
74
@ Override
75
- public BytesRef next () throws IOException {
75
+ public BytesRef next () {
76
76
BytesRef r = ref ;
77
77
ref = null ; // only return it once...
78
78
return r ;
@@ -189,7 +189,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
189
189
/**
190
190
* A StreamInput that reads off a {@link BytesRefIterator}. This is used to provide
191
191
* generic stream access to {@link BytesReference} instances without materializing the
192
- * underlying bytes reference .
192
+ * underlying bytes.
193
193
*/
194
194
private final class BytesReferenceStreamInput extends StreamInput {
195
195
@@ -239,7 +239,8 @@ public void readBytes(byte[] b, int bOffset, int len) throws IOException {
239
239
throw new IndexOutOfBoundsException (
240
240
"Cannot read " + len + " bytes from stream with length " + length + " at offset " + offset );
241
241
}
242
- read (b , bOffset , len );
242
+ final int bytesRead = read (b , bOffset , len );
243
+ assert bytesRead == len : bytesRead + " vs " + len ;
243
244
}
244
245
245
246
@ Override
@@ -257,7 +258,7 @@ public int read(final byte[] b, final int bOffset, final int len) throws IOExcep
257
258
if (offset >= length ) {
258
259
return -1 ;
259
260
}
260
- final int numBytesToCopy = Math .min (len , length - offset );
261
+ final int numBytesToCopy = Math .min (len , length - offset );
261
262
int remaining = numBytesToCopy ; // copy the full length or the remaining part
262
263
int destOffset = bOffset ;
263
264
while (remaining > 0 ) {
@@ -293,8 +294,11 @@ protected void ensureCanReadBytes(int bytesToRead) throws EOFException {
293
294
294
295
@ Override
295
296
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
298
302
int remaining = numBytesSkipped ;
299
303
while (remaining > 0 ) {
300
304
maybeNextSlice ();
@@ -308,11 +312,16 @@ public long skip(long n) throws IOException {
308
312
309
313
@ Override
310
314
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
+ }
316
325
}
317
326
318
327
@ Override
@@ -322,8 +331,7 @@ public boolean markSupported() {
322
331
323
332
@ Override
324
333
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.
327
335
this .mark = offset ();
328
336
}
329
337
}
0 commit comments