/** * Skip {@code src}'s position forward over one encoded value. * @param src the buffer containing the encoded value. * @return number of bytes skipped. * @throws IllegalArgumentException when the terminator sequence is not found. */ @Override public int skip(PositionedByteRange src) { if (wrapped.isSkippable()) { int ret = wrapped.skip(src); src.setPosition(src.getPosition() + term.length); return ret + term.length; } else { // find the terminator position final int start = src.getPosition(); int skipped = terminatorPosition(src); if (-1 == skipped) { throw new IllegalArgumentException("Terminator sequence not found."); } skipped += term.length; src.setPosition(skipped); return skipped - start; } }
@Test(expected = IllegalArgumentException.class) public void testEmptyDelimiter() { new TerminatedWrapper<>(new RawBytes(), ""); }
/** * Write instance {@code val} into buffer {@code dst}. * @throws IllegalArgumentException when the encoded representation of * {@code val} contains the {@code term} sequence. */ @Override public int encode(PositionedByteRange dst, T val) { final int start = dst.getPosition(); int written = wrapped.encode(dst, val); PositionedByteRange b = dst.shallowCopy(); b.setLength(dst.getPosition()); b.setPosition(start); if (-1 != terminatorPosition(b)) { dst.setPosition(start); throw new IllegalArgumentException("Encoded value contains terminator sequence."); } dst.put(term); return written + term.length; } }
@Test(expected = IllegalArgumentException.class) public void testEncodedValueContainsTerm() { DataType<byte[]> type = new TerminatedWrapper<>(new RawBytes(), "foo"); PositionedByteRange buff = new SimplePositionedMutableByteRange(16); type.encode(buff, Bytes.toBytes("hello foobar!")); }
@Override public T decode(PositionedByteRange src) { if (wrapped.isSkippable()) { T ret = wrapped.decode(src); src.setPosition(src.getPosition() + term.length); return ret; } else { // find the terminator position int term = terminatorPosition(src); if (-1 == term) { throw new IllegalArgumentException("Terminator sequence not found."); } byte[] b = new byte[term - src.getPosition()]; src.get(b); // TODO: should we assert that b.position == b.length? T ret = wrapped.decode(new SimplePositionedMutableByteRange(b)); src.get(this.term); return ret; } }
@Test(expected = IllegalArgumentException.class) public void testInvalidSkip() { PositionedByteRange buff = new SimplePositionedMutableByteRange(Bytes.toBytes("foo")); DataType<byte[]> type = new TerminatedWrapper<>(new RawBytes(), new byte[] { 0x00 }); type.skip(buff); } }
/** * Skip {@code src}'s position forward over one encoded value. * @param src the buffer containing the encoded value. * @return number of bytes skipped. * @throws IllegalArgumentException when the terminator sequence is not found. */ @Override public int skip(PositionedByteRange src) { if (wrapped.isSkippable()) { int ret = wrapped.skip(src); src.setPosition(src.getPosition() + term.length); return ret + term.length; } else { // find the terminator position final int start = src.getPosition(); int skipped = terminatorPosition(src); if (-1 == skipped) { throw new IllegalArgumentException("Terminator sequence not found."); } skipped += term.length; src.setPosition(skipped); return skipped - start; } }
@Test public void testReadWriteSkippable() { PositionedByteRange buff = new SimplePositionedMutableByteRange(14); for (OrderedString t : new OrderedString[] { OrderedString.ASCENDING, OrderedString.DESCENDING }) { for (byte[] term : TERMINATORS) { for (String val : VALUES_STRINGS) { buff.setPosition(0); DataType<String> type = new TerminatedWrapper<>(t, term); assertEquals(val.length() + 2 + term.length, type.encode(buff, val)); buff.setPosition(0); assertEquals(val, type.decode(buff)); assertEquals(val.length() + 2 + term.length, buff.getPosition()); } } } }
/** * Skip {@code src}'s position forward over one encoded value. * @param src the buffer containing the encoded value. * @return number of bytes skipped. * @throws IllegalArgumentException when the terminator sequence is not found. */ @Override public int skip(PositionedByteRange src) { if (wrapped.isSkippable()) { int ret = wrapped.skip(src); src.setPosition(src.getPosition() + term.length); return ret + term.length; } else { // find the terminator position final int start = src.getPosition(); int skipped = terminatorPosition(src); if (-1 == skipped) throw new IllegalArgumentException("Terminator sequence not found."); skipped += term.length; src.setPosition(skipped); return skipped - start; } }
@Test public void testSkipSkippable() { PositionedByteRange buff = new SimplePositionedMutableByteRange(14); for (OrderedString t : new OrderedString[] { OrderedString.ASCENDING, OrderedString.DESCENDING }) { for (byte[] term : TERMINATORS) { for (String val : VALUES_STRINGS) { buff.setPosition(0); DataType<String> type = new TerminatedWrapper<>(t, term); int expected = val.length() + 2 + term.length; assertEquals(expected, type.encode(buff, val)); buff.setPosition(0); assertEquals(expected, type.skip(buff)); assertEquals(expected, buff.getPosition()); } } } }
/** * Skip {@code src}'s position forward over one encoded value. * @param src the buffer containing the encoded value. * @return number of bytes skipped. * @throws IllegalArgumentException when the terminator sequence is not found. */ @Override public int skip(PositionedByteRange src) { if (wrapped.isSkippable()) { int ret = wrapped.skip(src); src.setPosition(src.getPosition() + term.length); return ret + term.length; } else { // find the terminator position final int start = src.getPosition(); int skipped = terminatorPosition(src); if (-1 == skipped) { throw new IllegalArgumentException("Terminator sequence not found."); } skipped += term.length; src.setPosition(skipped); return skipped - start; } }
@Test public void testSkipNonSkippable() { PositionedByteRange buff = new SimplePositionedMutableByteRange(12); for (Order ord : new Order[] { Order.ASCENDING, Order.DESCENDING }) { for (byte[] term : TERMINATORS) { for (byte[] val : VALUES_BYTES) { buff.setPosition(0); DataType<byte[]> type = new TerminatedWrapper<>(new RawBytes(ord), term); int expected = type.encode(buff, val); buff.setPosition(0); assertEquals(expected, type.skip(buff)); assertEquals(expected, buff.getPosition()); } } } }
/** * Write instance {@code val} into buffer {@code dst}. * @throws IllegalArgumentException when the encoded representation of * {@code val} contains the {@code term} sequence. */ @Override public int encode(PositionedByteRange dst, T val) { final int start = dst.getPosition(); int written = wrapped.encode(dst, val); PositionedByteRange b = dst.shallowCopy(); b.setLength(dst.getPosition()); b.setPosition(start); if (-1 != terminatorPosition(b)) { dst.setPosition(start); throw new IllegalArgumentException("Encoded value contains terminator sequence."); } dst.put(term); return written + term.length; } }
@Test public void testReadWriteNonSkippable() { PositionedByteRange buff = new SimplePositionedMutableByteRange(12); for (Order ord : new Order[] { Order.ASCENDING, Order.DESCENDING }) { for (byte[] term : TERMINATORS) { for (byte[] val : VALUES_BYTES) { buff.setPosition(0); DataType<byte[]> type = new TerminatedWrapper<>(new RawBytes(ord), term); assertEquals(val.length + term.length, type.encode(buff, val)); buff.setPosition(0); assertArrayEquals(val, type.decode(buff)); assertEquals(val.length + term.length, buff.getPosition()); } } } }
/** * Write instance {@code val} into buffer {@code dst}. * @throws IllegalArgumentException when the encoded representation of * {@code val} contains the {@code term} sequence. */ @Override public int encode(PositionedByteRange dst, T val) { final int start = dst.getPosition(); int written = wrapped.encode(dst, val); PositionedByteRange b = dst.shallowCopy(); b.setLength(dst.getPosition()); b.setPosition(start); if (-1 != terminatorPosition(b)) { dst.setPosition(start); throw new IllegalArgumentException("Encoded value contains terminator sequence."); } dst.put(term); return written + term.length; } }
Struct longer = builder .add(new TerminatedWrapper<>(OrderedString.ASCENDING, "/")) .add(OrderedNumeric.ASCENDING) .toStruct();
/** * Write instance {@code val} into buffer {@code dst}. * @throws IllegalArgumentException when the encoded representation of * {@code val} contains the {@code term} sequence. */ @Override public int encode(PositionedByteRange dst, T val) { final int start = dst.getPosition(); int written = wrapped.encode(dst, val); PositionedByteRange b = dst.shallowCopy(); b.setLength(dst.getPosition()); b.setPosition(start); if (-1 != terminatorPosition(b)) { dst.setPosition(start); throw new IllegalArgumentException("Encoded value contains terminator sequence."); } dst.put(term); return written + term.length; } }
@Test(expected = IllegalArgumentException.class) public void testEmptyDelimiter() { new TerminatedWrapper<>(new RawBytes(), ""); }
@Override public T decode(PositionedByteRange src) { if (wrapped.isSkippable()) { T ret = wrapped.decode(src); src.setPosition(src.getPosition() + term.length); return ret; } else { // find the terminator position int term = terminatorPosition(src); if (-1 == term) { throw new IllegalArgumentException("Terminator sequence not found."); } byte[] b = new byte[term - src.getPosition()]; src.get(b); // TODO: should we assert that b.position == b.length? T ret = wrapped.decode(new SimplePositionedMutableByteRange(b)); src.get(this.term); return ret; } }
@Test(expected = IllegalArgumentException.class) public void testEmptyDelimiter() { new TerminatedWrapper<>(new RawBytes(), ""); }