@Override public void write(Buffer source, long byteCount) throws IOException { if (!channel.isOpen()) throw new IllegalStateException("closed"); if (byteCount == 0) return; long remaining = byteCount; while (remaining > 0) { timeout.throwIfReached(); try (Buffer.UnsafeCursor ignored = source.readUnsafe(cursor)) { cursor.seek(0); int length = (int) Math.min(cursor.end - cursor.start, remaining); int written = channel.write(ByteBuffer.wrap(cursor.data, cursor.start, length)); remaining -= written; source.skip(written); } } }
@Test public void doubleAcquire() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { buffer.readUnsafe(cursor); fail(); } catch (IllegalStateException expected) { } }
@Override public void write(Buffer source, long byteCount) throws IOException { if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount); if (source.size() < byteCount) { throw new IllegalArgumentException("size=" + source.size() + " byteCount=" + byteCount); } if (byteCount == 0) return; source.readUnsafe(cursor); try { long remaining = byteCount; for (int length = cursor.seek(0); remaining > 0 && length > 0; length = cursor.next()) { int toIntercept = (int) Math.min(length, remaining); intercept(cursor.data, cursor.start, toIntercept); remaining -= toIntercept; } } finally { cursor.close(); } super.write(source, byteCount); }
@Override public long read(Buffer sink, long byteCount) throws IOException { if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount); if (byteCount == 0) return 0; long result = super.read(sink, byteCount); if (result == -1L) return result; sink.readUnsafe(cursor); try { long remaining = result; for (int length = cursor.seek(sink.size() - result); remaining > 0 && length > 0; length = cursor.next()) { int toIntercept = (int) Math.min(length, remaining); intercept(cursor.data, cursor.start, toIntercept); remaining -= toIntercept; } } finally { cursor.close(); } return result; }
@Test public void accessSegmentBySegment() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { Buffer actual = new Buffer(); while (cursor.next() != -1L) { actual.write(cursor.data, cursor.start, cursor.end - cursor.start); } assertEquals(buffer, actual); } }
@Test public void resizeAcquiredReadOnly() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { cursor.resizeBuffer(10); fail(); } catch (IllegalStateException expected) { } }
@Test public void expandAcquiredReadOnly() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { cursor.expandBuffer(10); fail(); } catch (IllegalStateException expected) { } }
@Test public void releaseAfterRelease() throws Exception { Buffer buffer = bufferFactory.newBuffer(); UnsafeCursor cursor = buffer.readUnsafe(); cursor.close(); try { cursor.close(); fail(); } catch (IllegalStateException expected) { } }
@Test public void accessByteByByte() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { byte[] actual = new byte[(int) buffer.size()]; for (int i = 0; i < buffer.size(); i++) { cursor.seek(i); actual[i] = cursor.data[cursor.start]; } assertEquals(ByteString.of(actual), buffer.snapshot()); } }
@Test public void accessByteByByteReverse() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { byte[] actual = new byte[(int) buffer.size()]; for (int i = (int) (buffer.size() - 1); i >= 0; i--) { cursor.seek(i); actual[i] = cursor.data[cursor.start]; } assertEquals(ByteString.of(actual), buffer.snapshot()); } }
@Test public void seekToNegativeOneSeeksBeforeFirstSegment() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { cursor.seek(-1L); assertEquals(-1, cursor.offset); assertEquals(null, cursor.data); assertEquals(-1, cursor.start); assertEquals(-1, cursor.end); cursor.next(); assertEquals(0, cursor.offset); } }
@Test public void accessByteByByteAlwaysResettingToZero() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { byte[] actual = new byte[(int) buffer.size()]; for (int i = 0; i < buffer.size(); i++) { cursor.seek(i); actual[i] = cursor.data[cursor.start]; cursor.seek(0L); } assertEquals(ByteString.of(actual), buffer.snapshot()); } }
@Test public void segmentBySegmentNavigation() throws Exception { Buffer buffer = bufferFactory.newBuffer(); UnsafeCursor cursor = buffer.readUnsafe(); assertEquals(-1, cursor.offset); try { long lastOffset = cursor.offset; while (cursor.next() != -1L) { assertTrue(cursor.offset > lastOffset); lastOffset = cursor.offset; } assertEquals(buffer.size(), cursor.offset); assertNull(cursor.data); assertEquals(-1, cursor.start); assertEquals(-1, cursor.end); } finally { cursor.close(); } }
@Test public void acquireAndRelease() throws Exception { Buffer buffer = bufferFactory.newBuffer(); UnsafeCursor cursor = new UnsafeCursor(); // Nothing initialized before acquire. assertEquals(-1, cursor.offset); assertNull(cursor.data); assertEquals(-1, cursor.start); assertEquals(-1, cursor.end); buffer.readUnsafe(cursor); cursor.close(); // Nothing initialized after close. assertEquals(-1, cursor.offset); assertNull(cursor.data); assertEquals(-1, cursor.start); assertEquals(-1, cursor.end); }
@Test public void seekWithinSegment() throws Exception { assumeTrue(bufferFactory == BufferFactory.SMALL_SEGMENTED_BUFFER); Buffer buffer = bufferFactory.newBuffer(); assertEquals("abcdefghijkl", buffer.clone().readUtf8()); // Seek to the 'f' in the "defg" segment. try (UnsafeCursor cursor = buffer.readUnsafe()) { assertEquals(2, cursor.seek(5)); // 2 for 2 bytes left in the segment: "fg". assertEquals(5, cursor.offset); assertEquals(2, cursor.end - cursor.start); assertEquals('d', (char) cursor.data[cursor.start - 2]); // Out of bounds! assertEquals('e', (char) cursor.data[cursor.start - 1]); // Out of bounds! assertEquals('f', (char) cursor.data[cursor.start]); assertEquals('g', (char) cursor.data[cursor.start + 1]); } }