diff --git a/src/main/java/ch/dissem/msgpack/types/MPDouble.java b/src/main/java/ch/dissem/msgpack/types/MPDouble.java deleted file mode 100644 index b76a83a..0000000 --- a/src/main/java/ch/dissem/msgpack/types/MPDouble.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2017 Christian Basler - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.dissem.msgpack.types; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.util.Objects; - -import static ch.dissem.msgpack.types.Utils.bytes; - -/** - * Representation of a msgpack encoded float64 number. - */ -public class MPDouble implements MPType { - private double value; - - public MPDouble(double value) { - this.value = value; - } - - @Override - public Double getValue() { - return value; - } - - public void pack(OutputStream out) throws IOException { - out.write(0xCB); - out.write(ByteBuffer.allocate(8).putDouble(value).array()); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MPDouble mpDouble = (MPDouble) o; - return Double.compare(mpDouble.value, value) == 0; - } - - @Override - public int hashCode() { - return Objects.hash(value); - } - - @Override - public String toString() { - return String.valueOf(value); - } - - @Override - public String toJson() { - return String.valueOf(value); - } - - public static class Unpacker implements MPType.Unpacker { - public boolean is(int firstByte) { - return firstByte == 0xCB; - } - - public MPDouble unpack(int firstByte, InputStream in) throws IOException { - if (firstByte == 0xCB) { - return new MPDouble(bytes(in, 8).getDouble()); - } else { - throw new IllegalArgumentException(String.format("Unexpected first byte 0x%02x", firstByte)); - } - } - } -} diff --git a/src/main/java/ch/dissem/msgpack/types/MPFloat.java b/src/main/java/ch/dissem/msgpack/types/MPFloat.java index 710c98c..20cd7a1 100644 --- a/src/main/java/ch/dissem/msgpack/types/MPFloat.java +++ b/src/main/java/ch/dissem/msgpack/types/MPFloat.java @@ -25,23 +25,45 @@ import java.util.Objects; import static ch.dissem.msgpack.types.Utils.bytes; /** - * Representation of a msgpack encoded float32 number. + * Representation of a msgpack encoded float32 or float64 number. */ -public class MPFloat implements MPType { - private float value; +public class MPFloat implements MPType { + + public enum Precision {FLOAT32, FLOAT64} + + private final double value; + private final Precision precision; public MPFloat(float value) { this.value = value; + this.precision = Precision.FLOAT32; + } + + public MPFloat(double value) { + this.value = value; + this.precision = Precision.FLOAT64; } @Override - public Float getValue() { + public Double getValue() { return value; } + public Precision getPrecision() { + return precision; + } + public void pack(OutputStream out) throws IOException { - out.write(0xCA); - out.write(ByteBuffer.allocate(4).putFloat(value).array()); + switch (precision) { + case FLOAT32: + out.write(0xCA); + out.write(ByteBuffer.allocate(4).putFloat((float) value).array()); + break; + case FLOAT64: + out.write(0xCB); + out.write(ByteBuffer.allocate(8).putDouble(value).array()); + break; + } } @Override @@ -49,7 +71,7 @@ public class MPFloat implements MPType { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MPFloat mpFloat = (MPFloat) o; - return Float.compare(mpFloat.value, value) == 0; + return Double.compare(mpFloat.value, value) == 0; } @Override @@ -69,14 +91,17 @@ public class MPFloat implements MPType { public static class Unpacker implements MPType.Unpacker { public boolean is(int firstByte) { - return firstByte == 0xCA; + return firstByte == 0xCA || firstByte == 0xCB; } public MPFloat unpack(int firstByte, InputStream in) throws IOException { - if (firstByte == 0xCA) { - return new MPFloat(bytes(in, 4).getFloat()); - } else { - throw new IllegalArgumentException(String.format("Unexpected first byte 0x%02x", firstByte)); + switch (firstByte) { + case 0xCA: + return new MPFloat(bytes(in, 4).getFloat()); + case 0xCB: + return new MPFloat(bytes(in, 8).getDouble()); + default: + throw new IllegalArgumentException(String.format("Unexpected first byte 0x%02x", firstByte)); } } } diff --git a/src/test/java/ch/dissem/msgpack/ReaderTest.java b/src/test/java/ch/dissem/msgpack/ReaderTest.java index b69cddb..1504f88 100644 --- a/src/test/java/ch/dissem/msgpack/ReaderTest.java +++ b/src/test/java/ch/dissem/msgpack/ReaderTest.java @@ -27,13 +27,15 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Random; +import static ch.dissem.msgpack.types.Utils.mp; +import static ch.dissem.msgpack.types.Utils.nil; 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(); + private Reader reader = Reader.getInstance(); @Test public void ensureDemoJsonIsParsedCorrectly() throws Exception { @@ -44,9 +46,10 @@ public class ReaderTest { @Test public void ensureDemoJsonIsEncodedCorrectly() throws Exception { + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") MPMap> object = new MPMap<>(); - object.put(new MPString("compact"), new MPBoolean(true)); - object.put(new MPString("schema"), new MPInteger(0)); + object.put(mp("compact"), mp(true)); + object.put(mp("schema"), mp(0)); ByteArrayOutputStream out = new ByteArrayOutputStream(); object.pack(out); assertThat(out.toByteArray(), is(bytes("demo.mp"))); @@ -56,14 +59,14 @@ public class ReaderTest { @SuppressWarnings("unchecked") public void ensureMPArrayIsEncodedAndDecodedCorrectly() throws Exception { MPArray> array = new MPArray<>( - new MPBinary(new byte[]{1, 3, 3, 7}), - new MPBoolean(false), - new MPDouble(Math.PI), - new MPFloat(1.5f), - new MPInteger(42), - new MPMap<>(new HashMap()), - new MPNil(), - new MPString("yay! \uD83E\uDD13") + mp(new byte[]{1, 3, 3, 7}), + mp(false), + mp(Math.PI), + mp(1.5f), + mp(42), + new MPMap(), + nil(), + mp("yay! \uD83E\uDD13") ); ByteArrayOutputStream out = new ByteArrayOutputStream(); array.pack(out); @@ -72,6 +75,31 @@ public class ReaderTest { assertThat((MPArray>) read, is(array)); } + @Test + public void ensureFloatIsEncodedAndDecodedCorrectly() throws Exception { + MPFloat expected = new MPFloat(1.5f); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + expected.pack(out); + MPType read = reader.read(new ByteArrayInputStream(out.toByteArray())); + assertThat(read, instanceOf(MPFloat.class)); + MPFloat actual = (MPFloat) read; + assertThat(actual, is(expected)); + assertThat(actual.getPrecision(), is(MPFloat.Precision.FLOAT32)); + } + + @Test + public void ensureDoubleIsEncodedAndDecodedCorrectly() throws Exception { + MPFloat expected = new MPFloat(Math.PI); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + expected.pack(out); + MPType read = reader.read(new ByteArrayInputStream(out.toByteArray())); + assertThat(read, instanceOf(MPFloat.class)); + MPFloat actual = (MPFloat) read; + assertThat(actual, is(expected)); + assertThat(actual.getValue(), is(Math.PI)); + assertThat(actual.getPrecision(), is(MPFloat.Precision.FLOAT64)); + } + @Test public void ensureStringsAreEncodedAndDecodedCorrectly() throws Exception { ensureStringIsEncodedAndDecodedCorrectly(0);