@SuppressWarnings("unchecked") @Override public int encode(PositionedByteRange dst, Object[] val) { if (val.length == 0) { return 0; } assert fields.length >= val.length; int end, written = 0; // find the last occurrence of a non-null or null and non-nullable value for (end = val.length - 1; end > -1; end--) { if (null != val[end] || (null == val[end] && !fields[end].isNullable())) { break; } } for (int i = 0; i <= end; i++) { written += fields[i].encode(dst, val[i]); } return written; } }
@Test public void testEncodedLength() { PositionedByteRange buff = new SimplePositionedMutableByteRange(20); for (DataType<String> type : new OrderedString[] { OrderedString.ASCENDING, OrderedString.DESCENDING }) { for (String val : VALUES) { buff.setPosition(0); type.encode(buff, val); assertEquals( "encodedLength does not match actual, " + val, buff.getPosition(), type.encodedLength(val)); } } } }
generic.encode(encodedGeneric[i], constructorArgs[i]); encodedGeneric[i].setPosition(0); specialized.encode(encodedSpecialized[i], vals[i]); encodedSpecialized[i].setPosition(0); assertArrayEquals(encodedGeneric[i].getBytes(), encodedSpecialized[i].getBytes());
@Override public int encode(PositionedByteRange dst, T val) { if (dst.getRemaining() < length) { throw new IllegalArgumentException("Not enough buffer remaining. dst.offset: " + dst.getOffset() + " dst.length: " + dst.getLength() + " dst.position: " + dst.getPosition() + " max length: " + length); } int written = base.encode(dst, val); if (written > length) { throw new IllegalArgumentException("Length of encoded value (" + written + ") exceeds max length (" + length + ")."); } // TODO: is the zero-padding appropriate? for (; written < length; written++) { dst.put((byte) 0x00); } return written; } }
@Test public void testEncodedLength() { PositionedByteRange buff = new SimplePositionedMutableByteRange(20); for (DataType<byte[]> type : new OrderedBlob[] { OrderedBlob.ASCENDING, OrderedBlob.DESCENDING }) { for (byte[] val : VALUES) { buff.setPosition(0); type.encode(buff, val); assertEquals( "encodedLength does not match actual, " + Bytes.toStringBinary(val), buff.getPosition(), type.encodedLength(val)); } } } }
@Override public int encode(PositionedByteRange dst, Object val) { Integer i = null; String s = null; try { i = (Integer) val; } catch (ClassCastException e) {} try { s = (String) val; } catch (ClassCastException e) {} if (null != i) { dst.put(IS_INTEGER); return 1 + typeA.encode(dst, i); } else if (null != s) { dst.put(IS_STRING); return 1 + typeB.encode(dst, s); } else throw new IllegalArgumentException("val is not of a supported type."); } }
@Test public void testEncodedLength() { PositionedByteRange buff = new SimplePositionedMutableByteRange(20); for (DataType<byte[]> type : new OrderedBlobVar[] { OrderedBlobVar.ASCENDING, OrderedBlobVar.DESCENDING }) { for (byte[] val : VALUES) { buff.setPosition(0); type.encode(buff, val); assertEquals( "encodedLength does not match actual, " + Bytes.toStringBinary(val), buff.getPosition(), type.encodedLength(val)); } } } }
/** * 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 testInsufficientRemainingWrite() { PositionedByteRange buff = new SimplePositionedMutableByteRange(0); DataType<byte[]> type = new FixedLengthWrapper<>(new RawBytes(), 3); type.encode(buff, Bytes.toBytes("")); }
@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!")); }
@Test(expected = IllegalArgumentException.class) public void testOverflowPassthrough() { PositionedByteRange buff = new SimplePositionedMutableByteRange(3); DataType<byte[]> type = new FixedLengthWrapper<>(new RawBytes(), 0); type.encode(buff, Bytes.toBytes("foo")); } }
@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()); } } } }
@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()); } } } }
@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()); } } } }
@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()); } } } }
@Test public void testReadWrite() { for (int limit : limits) { PositionedByteRange buff = new SimplePositionedMutableByteRange(limit); for (Order ord : new Order[] { Order.ASCENDING, Order.DESCENDING }) { for (byte[] val : VALUES) { buff.setPosition(0); DataType<byte[]> type = new FixedLengthWrapper<>(new RawBytes(ord), limit); assertEquals(limit, type.encode(buff, val)); buff.setPosition(0); byte[] actual = type.decode(buff); assertTrue("Decoding output differs from expected", Bytes.equals(val, 0, val.length, actual, 0, val.length)); buff.setPosition(0); assertEquals(limit, type.skip(buff)); } } } }
@Test(expected = IllegalArgumentException.class) public void testInsufficientRemainingWrite() { PositionedByteRange buff = new SimplePositionedMutableByteRange(0); DataType<byte[]> type = new FixedLengthWrapper<>(new RawBytes(), 3); type.encode(buff, Bytes.toBytes("")); }
@Test(expected = IllegalArgumentException.class) public void testOverflowPassthrough() { PositionedByteRange buff = new SimplePositionedMutableByteRange(3); DataType<byte[]> type = new FixedLengthWrapper<>(new RawBytes(), 0); type.encode(buff, Bytes.toBytes("foo")); } }
@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!")); }
@Test(expected = IllegalArgumentException.class) public void testOverflowPassthrough() { PositionedByteRange buff = new SimplePositionedMutableByteRange(3); DataType<byte[]> type = new FixedLengthWrapper<>(new RawBytes(), 0); type.encode(buff, Bytes.toBytes("foo")); } }