diff --git a/src/main/java/ch/dissem/msgpack/types/MPInteger.java b/src/main/java/ch/dissem/msgpack/types/MPInteger.java index 5125717..3a15a27 100644 --- a/src/main/java/ch/dissem/msgpack/types/MPInteger.java +++ b/src/main/java/ch/dissem/msgpack/types/MPInteger.java @@ -52,7 +52,7 @@ public class MPInteger implements MPType { } else if (value <= 0xFFFF) { out.write(0xCD); out.write(ByteBuffer.allocate(2).putShort((short) value).array()); - } else if (value < 0xFFFFFFFFL) { + } else if (value <= 0xFFFFFFFFL) { out.write(0xCE); out.write(ByteBuffer.allocate(4).putInt((int) value).array()); } else { @@ -60,7 +60,11 @@ public class MPInteger implements MPType { out.write(ByteBuffer.allocate(8).putLong(value).array()); } } else { - if (value >= Byte.MIN_VALUE) { + if (value >= -32) { + out.write(new byte[]{ + (byte) value + }); + } else if (value >= Byte.MIN_VALUE) { out.write(0xD0); out.write(ByteBuffer.allocate(1).put((byte) value).array()); } else if (value >= Short.MIN_VALUE) { @@ -125,8 +129,13 @@ public class MPInteger implements MPType { return new MPInteger(in.read()); case 0xCD: return new MPInteger(in.read() << 8 | in.read()); - case 0xCE: - return new MPInteger(in.read() << 24 | in.read() << 16 | in.read() << 8 | in.read()); + case 0xCE: { + long value = 0; + for (int i = 0; i < 4; i++) { + value = value << 8 | in.read(); + } + return new MPInteger(value); + } case 0xCF: { long value = 0; for (int i = 0; i < 8; i++) { diff --git a/src/main/java/ch/dissem/msgpack/types/Utils.java b/src/main/java/ch/dissem/msgpack/types/Utils.java index 62f68f7..7bc32a3 100644 --- a/src/main/java/ch/dissem/msgpack/types/Utils.java +++ b/src/main/java/ch/dissem/msgpack/types/Utils.java @@ -101,7 +101,7 @@ public class Utils { return new MPFloat(value); } - public static MPInteger mp(int value) { + public static MPInteger mp(long value) { return new MPInteger(value); } diff --git a/src/test/java/ch/dissem/msgpack/ReaderTest.java b/src/test/java/ch/dissem/msgpack/ReaderTest.java index 1504f88..6066bd0 100644 --- a/src/test/java/ch/dissem/msgpack/ReaderTest.java +++ b/src/test/java/ch/dissem/msgpack/ReaderTest.java @@ -100,6 +100,50 @@ public class ReaderTest { assertThat(actual.getPrecision(), is(MPFloat.Precision.FLOAT64)); } + @Test + public void ensureLongsAreEncodedAndDecodedCorrectly() throws Exception { + // positive fixnum + ensureLongIsEncodedAndDecodedCorrectly(0, 1); + ensureLongIsEncodedAndDecodedCorrectly(127, 1); + // negative fixnum + ensureLongIsEncodedAndDecodedCorrectly(-1, 1); + ensureLongIsEncodedAndDecodedCorrectly(-32, 1); + // uint 8 + ensureLongIsEncodedAndDecodedCorrectly(128, 2); + ensureLongIsEncodedAndDecodedCorrectly(255, 2); + // uint 16 + ensureLongIsEncodedAndDecodedCorrectly(256, 3); + ensureLongIsEncodedAndDecodedCorrectly(65535, 3); + // uint 32 + ensureLongIsEncodedAndDecodedCorrectly(65536, 5); + ensureLongIsEncodedAndDecodedCorrectly(4294967295L, 5); + // uint 64 + ensureLongIsEncodedAndDecodedCorrectly(4294967296L, 9); + ensureLongIsEncodedAndDecodedCorrectly(Long.MAX_VALUE, 9); + // int 8 + ensureLongIsEncodedAndDecodedCorrectly(-33, 2); + ensureLongIsEncodedAndDecodedCorrectly(-128, 2); + // int 16 + ensureLongIsEncodedAndDecodedCorrectly(-129, 3); + ensureLongIsEncodedAndDecodedCorrectly(-32768, 3); + // int 32 + ensureLongIsEncodedAndDecodedCorrectly(-32769, 5); + ensureLongIsEncodedAndDecodedCorrectly(Integer.MIN_VALUE, 5); + // int 64 + ensureLongIsEncodedAndDecodedCorrectly(-2147483649L, 9); + ensureLongIsEncodedAndDecodedCorrectly(Long.MIN_VALUE, 9); + } + + private void ensureLongIsEncodedAndDecodedCorrectly(long val, int bytes) throws Exception { + MPInteger value = mp(val); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + value.pack(out); + MPType read = reader.read(new ByteArrayInputStream(out.toByteArray())); + assertThat(out.size(), is(bytes)); + assertThat(read, instanceOf(MPInteger.class)); + assertThat((MPInteger) read, is(value)); + } + @Test public void ensureStringsAreEncodedAndDecodedCorrectly() throws Exception { ensureStringIsEncodedAndDecodedCorrectly(0);