diff --git a/src/main/java/ch/dissem/msgpack/types/MPBinary.java b/src/main/java/ch/dissem/msgpack/types/MPBinary.java index 2414c1e..3999741 100644 --- a/src/main/java/ch/dissem/msgpack/types/MPBinary.java +++ b/src/main/java/ch/dissem/msgpack/types/MPBinary.java @@ -60,7 +60,7 @@ public class MPBinary implements MPType { public MPBinary unpack(int firstByte, InputStream in) throws IOException { int size; if (firstByte == 0xC4) { - size = in.read() << 8 | in.read(); + size = in.read(); } else if (firstByte == 0xC5) { size = in.read() << 8 | in.read(); } else if (firstByte == 0xC6) { diff --git a/src/main/java/ch/dissem/msgpack/types/MPString.java b/src/main/java/ch/dissem/msgpack/types/MPString.java index bbee5cc..741a137 100644 --- a/src/main/java/ch/dissem/msgpack/types/MPString.java +++ b/src/main/java/ch/dissem/msgpack/types/MPString.java @@ -21,11 +21,11 @@ public class MPString implements MPType { public void pack(OutputStream out) throws IOException { int size = value.length(); - if (size < 16) { + if (size < 32) { out.write(0b10100000 + size); } else if (size < 256) { out.write(0xD9); - out.write((byte) size); + out.write(size); } else if (size < 65536) { out.write(0xDA); out.write(ByteBuffer.allocate(2).putShort((short) size).array()); @@ -64,7 +64,7 @@ public class MPString implements MPType { if ((firstByte & 0b11100000) == 0b10100000) { size = firstByte & 0b00011111; } else if (firstByte == 0xD9) { - size = in.read() << 8 | in.read(); + size = in.read(); } else if (firstByte == 0xDA) { size = in.read() << 8 | in.read(); } else if (firstByte == 0xDB) { diff --git a/src/test/java/ch/dissem/msgpack/ReaderTest.java b/src/test/java/ch/dissem/msgpack/ReaderTest.java index cb7975d..64bbd4d 100644 --- a/src/test/java/ch/dissem/msgpack/ReaderTest.java +++ b/src/test/java/ch/dissem/msgpack/ReaderTest.java @@ -7,14 +7,17 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Random; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; public class ReaderTest { + private static final Random RANDOM = new Random(); private Reader reader = new Reader(); @Test @@ -38,7 +41,7 @@ public class ReaderTest { @SuppressWarnings("unchecked") public void ensureMPArrayIsEncodedAndDecodedCorrectly() throws Exception { MPArray> array = new MPArray<>( -// new MPBinary(new byte[]{1, 3, 3, 7}), + new MPBinary(new byte[]{1, 3, 3, 7}), new MPBoolean(false), new MPDouble(Math.PI), new MPFloat(1.5f), @@ -54,6 +57,101 @@ public class ReaderTest { assertThat((MPArray>) read, is(array)); } + @Test + public void ensureStringsAreEncodedAndDecodedCorrectly() throws Exception { + ensureStringIsEncodedAndDecodedCorrectly(0); + ensureStringIsEncodedAndDecodedCorrectly(31); + ensureStringIsEncodedAndDecodedCorrectly(32); + ensureStringIsEncodedAndDecodedCorrectly(255); + ensureStringIsEncodedAndDecodedCorrectly(256); + ensureStringIsEncodedAndDecodedCorrectly(65535); + ensureStringIsEncodedAndDecodedCorrectly(65536); + } + + private void ensureStringIsEncodedAndDecodedCorrectly(int length) throws Exception { + MPString value = new MPString(stringWithLength(length)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + value.pack(out); + MPType read = reader.read(new ByteArrayInputStream(out.toByteArray())); + assertThat(read, instanceOf(MPString.class)); + assertThat((MPString) read, is(value)); + } + + @Test + public void ensureBinariesAreEncodedAndDecodedCorrectly() throws Exception { + ensureBinaryIsEncodedAndDecodedCorrectly(0); + ensureBinaryIsEncodedAndDecodedCorrectly(255); + ensureBinaryIsEncodedAndDecodedCorrectly(256); + ensureBinaryIsEncodedAndDecodedCorrectly(65535); + ensureBinaryIsEncodedAndDecodedCorrectly(65536); + } + + private void ensureBinaryIsEncodedAndDecodedCorrectly(int length) throws Exception { + MPBinary value = new MPBinary(new byte[length]); + RANDOM.nextBytes(value.getValue()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + value.pack(out); + MPType read = reader.read(new ByteArrayInputStream(out.toByteArray())); + assertThat(read, instanceOf(MPBinary.class)); + assertThat((MPBinary) read, is(value)); + } + + @Test + public void ensureArraysAreEncodedAndDecodedCorrectly() throws Exception { + ensureArrayIsEncodedAndDecodedCorrectly(0); + ensureArrayIsEncodedAndDecodedCorrectly(15); + ensureArrayIsEncodedAndDecodedCorrectly(16); + ensureArrayIsEncodedAndDecodedCorrectly(65535); + ensureArrayIsEncodedAndDecodedCorrectly(65536); + } + + @SuppressWarnings("unchecked") + private void ensureArrayIsEncodedAndDecodedCorrectly(int length) throws Exception { + MPNil nil = new MPNil(); + ArrayList list = new ArrayList<>(length); + for (int i = 0; i < length; i++) { + list.add(nil); + } + MPArray value = new MPArray<>(list); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + value.pack(out); + MPType read = reader.read(new ByteArrayInputStream(out.toByteArray())); + assertThat(read, instanceOf(MPArray.class)); + assertThat((MPArray) read, is(value)); + } + + @Test + public void ensureMapsAreEncodedAndDecodedCorrectly() throws Exception { + ensureMapIsEncodedAndDecodedCorrectly(0); + ensureMapIsEncodedAndDecodedCorrectly(15); + ensureMapIsEncodedAndDecodedCorrectly(16); + ensureMapIsEncodedAndDecodedCorrectly(65535); + ensureMapIsEncodedAndDecodedCorrectly(65536); + } + + @SuppressWarnings("unchecked") + private void ensureMapIsEncodedAndDecodedCorrectly(int length) throws Exception { + MPNil nil = new MPNil(); + HashMap map = new HashMap<>(length); + for (int i = 0; i < length; i++) { + map.put(nil, nil); + } + MPMap value = new MPMap<>(map); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + value.pack(out); + MPType read = reader.read(new ByteArrayInputStream(out.toByteArray())); + assertThat(read, instanceOf(MPMap.class)); + assertThat((MPMap) read, is(value)); + } + + private String stringWithLength(int length) { + StringBuilder result = new StringBuilder(length); + for (int i = 0; i < length; i++) { + result.append('a'); + } + return result.toString(); + } + private InputStream stream(String resource) { return getClass().getClassLoader().getResourceAsStream(resource); }