From 9a57ab118fe8ae5733a6fca0cbaf0984d1783883 Mon Sep 17 00:00:00 2001 From: LoneRifle Date: Wed, 27 Jul 2016 17:22:14 +0800 Subject: [PATCH 001/417] MessagePacker implements Flushable via flush() --- msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 17dc3a169..f12d86a07 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -20,6 +20,7 @@ import org.msgpack.value.Value; import java.io.Closeable; +import java.io.Flushable; import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; @@ -83,7 +84,7 @@ *

*/ public class MessagePacker - implements Closeable + implements Closeable, Flushable { private final int smallStringOptimizationThreshold; From 446da7db21f70daac7837c15e95be19a7e56346c Mon Sep 17 00:00:00 2001 From: Min Date: Thu, 28 Jul 2016 02:13:26 +0900 Subject: [PATCH 002/417] Add ByteBuffer input support again --- .../java/org/msgpack/core/MessagePack.java | 24 ++ .../java/org/msgpack/core/MessagePacker.java | 6 +- .../org/msgpack/core/MessageUnpacker.java | 18 +- .../msgpack/core/buffer/ByteBufferInput.java | 69 +++++ .../msgpack/core/buffer/MessageBuffer.java | 86 ++++++- .../msgpack/core/MessageUnpackerTest.scala | 236 ++++++++++-------- .../msgpack/core/buffer/ByteStringTest.scala | 10 + .../core/buffer/MessageBufferInputTest.scala | 5 + .../core/buffer/MessageBufferTest.scala | 72 +++++- 9 files changed, 398 insertions(+), 128 deletions(-) create mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 7e420c521..7737aa664 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -16,6 +16,7 @@ package org.msgpack.core; import org.msgpack.core.buffer.ArrayBufferInput; +import org.msgpack.core.buffer.ByteBufferInput; import org.msgpack.core.buffer.ChannelBufferInput; import org.msgpack.core.buffer.ChannelBufferOutput; import org.msgpack.core.buffer.InputStreamBufferInput; @@ -25,6 +26,7 @@ import java.io.InputStream; import java.io.OutputStream; +import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.charset.Charset; @@ -236,6 +238,17 @@ public static MessageUnpacker newDefaultUnpacker(byte[] contents, int offset, in return DEFAULT_UNPACKER_CONFIG.newUnpacker(contents, offset, length); } + /** + * Create an unpacker that reads the data from a given ByteBuffer + * + * @param contents + * @return + */ + public static MessageUnpacker newDefaultUnpacker(ByteBuffer contents) + { + return DEFAULT_UNPACKER_CONFIG.newUnpacker(contents); + } + /** * MessagePacker configuration. */ @@ -524,6 +537,17 @@ public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) return newUnpacker(new ArrayBufferInput(contents, offset, length)); } + /** + * Create an unpacker that reads the data from a given ByteBuffer + * + * @param contents + * @return + */ + public MessageUnpacker newUnpacker(ByteBuffer contents) + { + return newUnpacker(new ByteBufferInput(contents)); + } + /** * Allow unpackBinaryHeader to read str format family (default: true) */ diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 17dc3a169..7c6bfae70 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -531,8 +531,7 @@ else if (s.length() < (1 << 8)) { throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); } // move 1 byte backward to expand 3-byte header region to 3 bytes - buffer.putBytes(position + 3, - buffer.array(), buffer.arrayOffset() + position + 2, written); + buffer.putMessageBuffer(position + 3, buffer, position + 2, written); // write 3-byte header buffer.putByte(position++, STR16); buffer.putShort(position, (short) written); @@ -560,8 +559,7 @@ else if (s.length() < (1 << 16)) { throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); } // move 2 bytes backward to expand 3-byte header region to 5 bytes - buffer.putBytes(position + 5, - buffer.array(), buffer.arrayOffset() + position + 3, written); + buffer.putMessageBuffer(position + 5, buffer, position + 3, written); // write 3-byte header header buffer.putByte(position++, STR32); buffer.putInt(position, written); diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index d36d2825c..399e126dc 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -213,14 +213,9 @@ private MessageBuffer prepareNumberBuffer(int readLength) // fill the temporary buffer from the current data fragment and // next fragment(s). - // TODO buffer.array() doesn't work if MessageBuffer is allocated by - // newDirectBuffer. dd copy method to MessageBuffer to solve this issue. - int off = 0; if (remaining > 0) { - numberBuffer.putBytes(0, - buffer.array(), buffer.arrayOffset() + position, - remaining); + numberBuffer.putMessageBuffer(0, buffer, position, remaining); readLength -= remaining; off += remaining; } @@ -229,16 +224,12 @@ private MessageBuffer prepareNumberBuffer(int readLength) nextBuffer(); int nextSize = buffer.size(); if (nextSize >= readLength) { - numberBuffer.putBytes(off, - buffer.array(), buffer.arrayOffset(), - readLength); + numberBuffer.putMessageBuffer(off, buffer, 0, readLength); position = readLength; break; } else { - numberBuffer.putBytes(off, - buffer.array(), buffer.arrayOffset(), - nextSize); + numberBuffer.putMessageBuffer(off, buffer, 0, nextSize); readLength -= nextSize; off += nextSize; } @@ -1041,7 +1032,8 @@ private void handleCoderError(CoderResult cr) private String decodeStringFastPath(int length) { if (actionOnMalformedString == CodingErrorAction.REPLACE && - actionOnUnmappableString == CodingErrorAction.REPLACE) { + actionOnUnmappableString == CodingErrorAction.REPLACE && + buffer.hasArray()) { String s = new String(buffer.array(), buffer.arrayOffset() + position, length, MessagePack.UTF8); position += length; return s; diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java new file mode 100644 index 000000000..13a7db1d7 --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java @@ -0,0 +1,69 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.core.buffer; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import static org.msgpack.core.Preconditions.checkNotNull; + +/** + * {@link MessageBufferInput} adapter for {@link java.nio.ByteBuffer} + */ +public class ByteBufferInput + implements MessageBufferInput +{ + private ByteBuffer input; + private boolean isRead = false; + + public ByteBufferInput(ByteBuffer input) + { + this.input = checkNotNull(input, "input ByteBuffer is null"); + } + + /** + * Reset buffer. This method doesn't close the old resource. + * + * @param input new buffer + * @return the old resource + */ + public ByteBuffer reset(ByteBuffer input) + { + ByteBuffer old = this.input; + this.input = input; + isRead = false; + return old; + } + + @Override + public MessageBuffer next() + throws IOException + { + if (isRead) { + return null; + } + + isRead = true; + return MessageBuffer.wrap(input); + } + + @Override + public void close() + throws IOException + { + // Nothing to do + } +} \ No newline at end of file diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index d4d5f2238..d7eff7ba7 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -43,6 +43,7 @@ public class MessageBuffer * Reference to MessageBuffer Constructors */ private static final Constructor mbArrConstructor; + private static final Constructor mbBBConstructor; /** * The offset from the object memory header to its byte array data @@ -145,6 +146,11 @@ public class MessageBuffer Constructor mbArrCstr = bufferCls.getDeclaredConstructor(byte[].class, int.class, int.class); mbArrCstr.setAccessible(true); mbArrConstructor = mbArrCstr; + + // MessageBufferX(ByteBuffer) constructor + Constructor mbBBCstr = bufferCls.getDeclaredConstructor(ByteBuffer.class); + mbBBCstr.setAccessible(true); + mbBBConstructor = mbBBCstr; } catch (Exception e) { e.printStackTrace(System.err); @@ -170,6 +176,12 @@ public class MessageBuffer */ protected final int size; + /** + * Reference is used to hold a reference to an object that holds the underlying memory so that it cannot be + * released by the garbage collector. + */ + protected final ByteBuffer reference; + public static MessageBuffer allocate(int length) { return wrap(new byte[length]); @@ -185,6 +197,11 @@ public static MessageBuffer wrap(byte[] array, int offset, int length) return newMessageBuffer(array, offset, length); } + public static MessageBuffer wrap(ByteBuffer bb) + { + return newMessageBuffer(bb).slice(bb.position(), bb.remaining()); + } + /** * Creates a new MessageBuffer instance backed by a java heap array * @@ -202,11 +219,32 @@ private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len) } } + /** + * Creates a new MessageBuffer instance backed by ByteBuffer + * + * @param bb + * @return + */ + private static MessageBuffer newMessageBuffer(ByteBuffer bb) + { + checkNotNull(bb); + try { + // We need to use reflection to create MessageBuffer instances in order to prevent TypeProfile generation for getInt method. TypeProfile will be + // generated to resolve one of the method references when two or more classes overrides the method. + return (MessageBuffer) mbBBConstructor.newInstance(bb); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + public static void releaseBuffer(MessageBuffer buffer) { if (isUniversalBuffer || buffer.base instanceof byte[]) { // We have nothing to do. Wait until the garbage-collector collects this array object } + else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.base)) { + DirectBufferAccess.clean(buffer.base); + } else { // Maybe cannot reach here unsafe.freeMemory(buffer.address); @@ -225,6 +263,35 @@ public static void releaseBuffer(MessageBuffer buffer) this.base = arr; this.address = ARRAY_BYTE_BASE_OFFSET + offset; this.size = length; + this.reference = null; + } + + /** + * Create a MessageBuffer instance from a given ByteBuffer instance + * + * @param bb + */ + MessageBuffer(ByteBuffer bb) + { + if (bb.isDirect()) { + if (isUniversalBuffer) { + throw new IllegalStateException("Cannot create MessageBuffer from DirectBuffer"); + } + // Direct buffer or off-heap memory + this.base = null; + this.address = DirectBufferAccess.getAddress(bb); + this.size = bb.capacity(); + this.reference = bb; + } + else if (bb.hasArray()) { + this.base = bb.array(); + this.address = ARRAY_BYTE_BASE_OFFSET; + this.size = bb.array().length; + this.reference = null; + } + else { + throw new IllegalArgumentException("Only the array-backed ByteBuffer or DirectBuffer are supported"); + } } protected MessageBuffer(Object base, long address, int length) @@ -232,6 +299,7 @@ protected MessageBuffer(Object base, long address, int length) this.base = base; this.address = address; this.size = length; + this.reference = null; } /** @@ -393,6 +461,11 @@ else if (src.hasArray()) { } } + public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int len) + { + unsafe.copyMemory(src.base, src.address + srcOffset, base, address + index, len); + } + /** * Create a ByteBuffer view of the range [index, index+length) of this memory * @@ -402,7 +475,13 @@ else if (src.hasArray()) { */ public ByteBuffer sliceAsByteBuffer(int index, int length) { - return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length); + if (hasArray()) { + return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length); + } + else { + assert (!isUniversalBuffer); + return DirectBufferAccess.newByteBuffer(address, index, length, reference); + } } /** @@ -415,6 +494,11 @@ public ByteBuffer sliceAsByteBuffer() return sliceAsByteBuffer(0, size()); } + public boolean hasArray() + { + return base instanceof byte[]; + } + /** * Get a copy of this buffer * diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 96809f626..173620282 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -16,6 +16,7 @@ package org.msgpack.core import java.io._ +import java.nio.ByteBuffer import org.msgpack.core.buffer._ import org.msgpack.value.ValueType @@ -188,33 +189,47 @@ class MessageUnpackerTest extends MessagePackSpec { u.hasNext shouldBe false } + def unpackers(data: Array[Byte]) : Seq[MessageUnpacker] = { + val bb = ByteBuffer.allocate(data.length) + val db = ByteBuffer.allocateDirect(data.length) + bb.put(data).flip() + db.put(data).flip() + Seq( + MessagePack.newDefaultUnpacker(data), + MessagePack.newDefaultUnpacker(bb), + MessagePack.newDefaultUnpacker(db) + ) + } + "MessageUnpacker" should { "parse message packed data" taggedAs ("unpack") in { val arr = testData - val unpacker = MessagePack.newDefaultUnpacker(arr) + for (unpacker <- unpackers(arr)) { - var count = 0 - while (unpacker.hasNext) { - count += 1 - readValue(unpacker) + var count = 0 + while (unpacker.hasNext) { + count += 1 + readValue(unpacker) + } + count shouldBe 6 + unpacker.getTotalReadBytes shouldBe arr.length } - count shouldBe 6 - unpacker.getTotalReadBytes shouldBe arr.length } "skip reading values" in { - val unpacker = MessagePack.newDefaultUnpacker(testData) - var skipCount = 0 - while (unpacker.hasNext) { - unpacker.skipValue() - skipCount += 1 - } + for (unpacker <- unpackers(testData)) { + var skipCount = 0 + while (unpacker.hasNext) { + unpacker.skipValue() + skipCount += 1 + } - skipCount shouldBe 2 - unpacker.getTotalReadBytes shouldBe testData.length + skipCount shouldBe 2 + unpacker.getTotalReadBytes shouldBe testData.length + } } "compare skip performance" taggedAs ("skip") in { @@ -223,21 +238,23 @@ class MessageUnpackerTest extends MessagePackSpec { time("skip performance", repeat = 100) { block("switch") { - val unpacker = MessagePack.newDefaultUnpacker(data) - var skipCount = 0 - while (unpacker.hasNext) { - unpacker.skipValue() - skipCount += 1 + for (unpacker <- unpackers(data)) { + var skipCount = 0 + while (unpacker.hasNext) { + unpacker.skipValue() + skipCount += 1 + } + skipCount shouldBe N } - skipCount shouldBe N } } time("bulk skip performance", repeat = 100) { block("switch") { - val unpacker = MessagePack.newDefaultUnpacker(data) - unpacker.skipValue(N) - unpacker.hasNext shouldBe false + for (unpacker <- unpackers(data)) { + unpacker.skipValue(N) + unpacker.hasNext shouldBe false + } } } @@ -247,26 +264,27 @@ class MessageUnpackerTest extends MessagePackSpec { debug(intSeq.mkString(", ")) - val ib = Seq.newBuilder[Int] + for (unpacker <- unpackers(testData2)) { + val ib = Seq.newBuilder[Int] - val unpacker = MessagePack.newDefaultUnpacker(testData2) - while (unpacker.hasNext) { - val f = unpacker.getNextFormat - f.getValueType match { - case ValueType.INTEGER => - val i = unpacker.unpackInt() - trace(f"read int: $i%,d") - ib += i - case ValueType.BOOLEAN => - val b = unpacker.unpackBoolean() - trace(s"read boolean: $b") - case other => - unpacker.skipValue() + while (unpacker.hasNext) { + val f = unpacker.getNextFormat + f.getValueType match { + case ValueType.INTEGER => + val i = unpacker.unpackInt() + trace(f"read int: $i%,d") + ib += i + case ValueType.BOOLEAN => + val b = unpacker.unpackBoolean() + trace(s"read boolean: $b") + case other => + unpacker.skipValue() + } } - } - ib.result shouldBe intSeq - unpacker.getTotalReadBytes shouldBe testData2.length + ib.result shouldBe intSeq + unpacker.getTotalReadBytes shouldBe testData2.length + } } @@ -276,29 +294,30 @@ class MessageUnpackerTest extends MessagePackSpec { trait SplitTest { val data: Array[Byte] def run { - val unpacker = MessagePack.newDefaultUnpacker(data) - val numElems = { - var c = 0 - while (unpacker.hasNext) { - readValue(unpacker) - c += 1 + for (unpacker <- unpackers(data)) { + val numElems = { + var c = 0 + while (unpacker.hasNext) { + readValue(unpacker) + c += 1 + } + c } - c - } - for (splitPoint <- 1 until data.length - 1) { - debug(s"split at $splitPoint") - val (h, t) = data.splitAt(splitPoint) - val bin = new SplitMessageBufferInput(Array(h, t)) - val unpacker = MessagePack.newDefaultUnpacker(bin) - var count = 0 - while (unpacker.hasNext) { - count += 1 - val f = unpacker.getNextFormat - readValue(unpacker) + for (splitPoint <- 1 until data.length - 1) { + debug(s"split at $splitPoint") + val (h, t) = data.splitAt(splitPoint) + val bin = new SplitMessageBufferInput(Array(h, t)) + val unpacker = MessagePack.newDefaultUnpacker(bin) + var count = 0 + while (unpacker.hasNext) { + count += 1 + val f = unpacker.getNextFormat + readValue(unpacker) + } + count shouldBe numElems + unpacker.getTotalReadBytes shouldBe data.length } - count shouldBe numElems - unpacker.getTotalReadBytes shouldBe data.length } } } @@ -316,7 +335,7 @@ class MessageUnpackerTest extends MessagePackSpec { packer.close val data = packer.toByteArray - val unpacker = MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(data), 8192)) + val unpacker = MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(data), 8192)) (0 until 1170).foreach { i => unpacker.unpackLong() shouldBe 0x0011223344556677L unpacker.unpackString() shouldBe "hello" @@ -349,7 +368,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("v7") { - val unpacker = MessagePack.newDefaultUnpacker(data) + val unpacker = Random.shuffle(unpackers(data)).head var count = 0 try { while (unpacker.hasNext) { @@ -451,7 +470,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("v7") { - val unpacker = MessagePack.newDefaultUnpacker(data) + val unpacker = Random.shuffle(unpackers(data)).head var count = 0 try { while (unpacker.hasNext) { @@ -495,7 +514,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("v7") { - val unpacker = MessagePack.newDefaultUnpacker(b) + val unpacker = Random.shuffle(unpackers(b)).head var i = 0 while (i < R) { val len = unpacker.unpackBinaryHeader() @@ -507,7 +526,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("v7-ref") { - val unpacker = MessagePack.newDefaultUnpacker(b) + val unpacker = Random.shuffle(unpackers(b)).head var i = 0 while (i < R) { val len = unpacker.unpackBinaryHeader() @@ -533,16 +552,17 @@ class MessageUnpackerTest extends MessagePackSpec { packer.writePayload(data) packer.close() - val unpacker = MessagePack.newDefaultUnpacker(b.toByteArray) - val len = unpacker.unpackBinaryHeader() - len shouldBe s - val ref = unpacker.readPayloadAsReference(len) - unpacker.close() - ref.size() shouldBe s - val stored = new Array[Byte](len) - ref.getBytes(0, stored, 0, len) + for (unpacker <- unpackers(b.toByteArray)) { + val len = unpacker.unpackBinaryHeader() + len shouldBe s + val ref = unpacker.readPayloadAsReference(len) + unpacker.close() + ref.size() shouldBe s + val stored = new Array[Byte](len) + ref.getBytes(0, stored, 0, len) - stored shouldBe data + stored shouldBe data + } } } @@ -552,35 +572,36 @@ class MessageUnpackerTest extends MessagePackSpec { val data = intSeq val b = createMessagePackData(packer => data foreach packer.packInt) - val unpacker = MessagePack.newDefaultUnpacker(b) + for (unpacker <- unpackers(b)) { - val unpacked = Array.newBuilder[Int] - while (unpacker.hasNext) { - unpacked += unpacker.unpackInt() - } - unpacker.close - unpacked.result shouldBe data - - val data2 = intSeq - val b2 = createMessagePackData(packer => data2 foreach packer.packInt) - val bi = new ArrayBufferInput(b2) - unpacker.reset(bi) - val unpacked2 = Array.newBuilder[Int] - while (unpacker.hasNext) { - unpacked2 += unpacker.unpackInt() - } - unpacker.close - unpacked2.result shouldBe data2 - - // reused the buffer input instance - bi.reset(b2) - unpacker.reset(bi) - val unpacked3 = Array.newBuilder[Int] - while (unpacker.hasNext) { - unpacked3 += unpacker.unpackInt() + val unpacked = Array.newBuilder[Int] + while (unpacker.hasNext) { + unpacked += unpacker.unpackInt() + } + unpacker.close + unpacked.result shouldBe data + + val data2 = intSeq + val b2 = createMessagePackData(packer => data2 foreach packer.packInt) + val bi = new ArrayBufferInput(b2) + unpacker.reset(bi) + val unpacked2 = Array.newBuilder[Int] + while (unpacker.hasNext) { + unpacked2 += unpacker.unpackInt() + } + unpacker.close + unpacked2.result shouldBe data2 + + // reused the buffer input instance + bi.reset(b2) + unpacker.reset(bi) + val unpacked3 = Array.newBuilder[Int] + while (unpacker.hasNext) { + unpacked3 += unpacker.unpackInt() + } + unpacker.close + unpacked3.result shouldBe data2 } - unpacker.close - unpacked3.result shouldBe data2 } @@ -678,13 +699,14 @@ class MessageUnpackerTest extends MessagePackSpec { Seq(8191, 8192, 8193, 16383, 16384, 16385).foreach { n => val arr = createLargeData(n) - val unpacker = MessagePack.newDefaultUnpacker(arr) + for (unpacker <- unpackers(arr)) { - unpacker.unpackArrayHeader shouldBe 2 - unpacker.unpackString.length shouldBe n - unpacker.unpackInt shouldBe 1 + unpacker.unpackArrayHeader shouldBe 2 + unpacker.unpackString.length shouldBe n + unpacker.unpackInt shouldBe 1 - unpacker.getTotalReadBytes shouldBe arr.length + unpacker.getTotalReadBytes shouldBe arr.length + } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala index 2c080b59a..18876ddb8 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala @@ -43,4 +43,14 @@ class ByteStringTest MessagePack.newDefaultUnpacker(input).unpackString() } + + "Unpacking a ByteString's ByteBuffer" should { + "fail with a regular MessageBuffer" in { + + // can't demonstrate with new ByteBufferInput(byteString.asByteBuffer) + // as Travis tests run with JDK6 that picks up MessageBufferU + a[RuntimeException] shouldBe thrownBy(unpackString(new + MessageBuffer(byteString.asByteBuffer))) + } + } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index 1638806ee..6b1c0da48 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -94,6 +94,11 @@ class MessageBufferInputTest ArrayBufferInput(_)) } + "support ByteBuffers" in { + runTest(b => new + ByteBufferInput(b.toByteBuffer)) + } + "support InputStreams" taggedAs ("is") in { runTest(b => new diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala index 75ef00a11..a585b9537 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala @@ -34,19 +34,28 @@ class MessageBufferTest info(s"MessageBuffer type: ${b.getClass.getName}") } - "wrap ByteBuffer considering position and remaining values" taggedAs ("wrap-bb") in { + "wrap byte array considering position and remaining values" taggedAs ("wrap-ba") in { val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) val mb = MessageBuffer.wrap(d, 2, 2) mb.getByte(0) shouldBe 12 mb.size() shouldBe 2 } + "wrap ByteBuffer considering position and remaining values" taggedAs ("wrap-bb") in { + val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) + val subset = ByteBuffer.wrap(d, 2, 2) + val mb = MessageBuffer.wrap(subset) + mb.getByte(0) shouldBe 12 + mb.size() shouldBe 2 + } + "have better performance than ByteBuffer" in { val N = 1000000 val M = 64 * 1024 * 1024 val ub = MessageBuffer.allocate(M) + val ud = MessageBuffer.wrap(ByteBuffer.allocateDirect(M)) val hb = ByteBuffer.allocate(M) val db = ByteBuffer.allocateDirect(M) @@ -82,6 +91,14 @@ class MessageBufferTest } } + block("unsafe direct") { + var i = 0 + while (i < N) { + ud.getInt((i * 4) % M) + i += 1 + } + } + block("allocate") { var i = 0 while (i < N) { @@ -108,6 +125,14 @@ class MessageBufferTest } } + block("unsafe direct") { + var i = 0 + while (i < N) { + ud.getInt((rs(i) * 4) % M) + i += 1 + } + } + block("allocate") { var i = 0 while (i < N) { @@ -128,7 +153,9 @@ class MessageBufferTest "convert to ByteBuffer" in { for (t <- Seq( - MessageBuffer.allocate(10)) + MessageBuffer.allocate(10), + MessageBuffer.wrap(ByteBuffer.allocate(10)), + MessageBuffer.wrap(ByteBuffer.allocateDirect(10))) ) { val bb = t.sliceAsByteBuffer bb.position shouldBe 0 @@ -139,7 +166,9 @@ class MessageBufferTest "put ByteBuffer on itself" in { for (t <- Seq( - MessageBuffer.allocate(10)) + MessageBuffer.allocate(10), + MessageBuffer.wrap(ByteBuffer.allocate(10)), + MessageBuffer.wrap(ByteBuffer.allocateDirect(10))) ) { val b = Array[Byte](0x02, 0x03) val srcArray = ByteBuffer.wrap(b) @@ -163,11 +192,46 @@ class MessageBufferTest } } + "put MessageBuffer on itself" in { + for (t <- Seq( + MessageBuffer.allocate(10), + MessageBuffer.wrap(ByteBuffer.allocate(10)), + MessageBuffer.wrap(ByteBuffer.allocateDirect(10))) + ) { + val b = Array[Byte](0x02, 0x03) + val srcArray = ByteBuffer.wrap(b) + val srcHeap = ByteBuffer.allocate(b.length) + srcHeap.put(b).flip + val srcOffHeap = ByteBuffer.allocateDirect(b.length) + srcOffHeap.put(b).flip + + for (src <- Seq(MessageBuffer.wrap(srcArray), MessageBuffer.wrap(srcHeap), MessageBuffer.wrap(srcOffHeap))) { + // Write header bytes + val header = Array[Byte](0x00, 0x01) + t.putBytes(0, header, 0, header.length) + // Write src after the header + t.putMessageBuffer(header.length, src, 0, header.length) + + t.getByte(0) shouldBe 0x00 + t.getByte(1) shouldBe 0x01 + t.getByte(2) shouldBe 0x02 + t.getByte(3) shouldBe 0x03 + } + } + } + "copy sliced buffer" in { def prepareBytes : Array[Byte] = { Array[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07) } + def prepareDirectBuffer : ByteBuffer = { + val directBuffer = ByteBuffer.allocateDirect(prepareBytes.length) + directBuffer.put(prepareBytes) + directBuffer.flip + directBuffer + } + def checkSliceAndCopyTo(srcBuffer: MessageBuffer, dstBuffer: MessageBuffer) = { val sliced = srcBuffer.slice(2, 5) @@ -191,6 +255,8 @@ class MessageBufferTest } checkSliceAndCopyTo(MessageBuffer.wrap(prepareBytes), MessageBuffer.wrap(prepareBytes)) + checkSliceAndCopyTo(MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)), MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes))) + checkSliceAndCopyTo(MessageBuffer.wrap(prepareDirectBuffer), MessageBuffer.wrap(prepareDirectBuffer)) } } } From b1db42dfe0c5d4ab4a9d654a7ab9acc28c19c6d7 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Wed, 27 Jul 2016 14:22:44 -0700 Subject: [PATCH 003/417] ArrayBufferInput and ByteBufferInput will never throw IOException --- .../main/java/org/msgpack/core/buffer/ArrayBufferInput.java | 2 -- .../main/java/org/msgpack/core/buffer/ByteBufferInput.java | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java index 3fbc97208..3d11ad9ed 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java @@ -80,7 +80,6 @@ public void reset(byte[] arr, int offset, int len) @Override public MessageBuffer next() - throws IOException { if (isEmpty) { return null; @@ -91,7 +90,6 @@ public MessageBuffer next() @Override public void close() - throws IOException { buffer = null; isEmpty = true; diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java index 13a7db1d7..41936d9ab 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java @@ -50,7 +50,6 @@ public ByteBuffer reset(ByteBuffer input) @Override public MessageBuffer next() - throws IOException { if (isRead) { return null; @@ -62,8 +61,7 @@ public MessageBuffer next() @Override public void close() - throws IOException { // Nothing to do } -} \ No newline at end of file +} From 2908767605d4c00f083f3a647dddc04d55eba136 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Wed, 27 Jul 2016 14:23:22 -0700 Subject: [PATCH 004/417] ByteBufferInput should not be affected when given ByteBuffer's position is modified --- .../java/org/msgpack/core/buffer/ByteBufferInput.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java index 41936d9ab..f644d18d1 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java @@ -31,19 +31,19 @@ public class ByteBufferInput public ByteBufferInput(ByteBuffer input) { - this.input = checkNotNull(input, "input ByteBuffer is null"); + this.input = checkNotNull(input, "input ByteBuffer is null").slice(); } /** - * Reset buffer. This method doesn't close the old resource. + * Reset buffer. * * @param input new buffer - * @return the old resource + * @return the old buffer */ public ByteBuffer reset(ByteBuffer input) { ByteBuffer old = this.input; - this.input = input; + this.input = checkNotNull(input, "input ByteBuffer is null").slice(); isRead = false; return old; } @@ -55,8 +55,9 @@ public MessageBuffer next() return null; } + MessageBuffer b = MessageBuffer.wrap(input); isRead = true; - return MessageBuffer.wrap(input); + return b; } @Override From 131eda02bc7d54518fdf069496e55235dfe499fe Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Wed, 27 Jul 2016 14:23:54 -0700 Subject: [PATCH 005/417] fix import lines at MessagePackExample that made sbt failed --- .../java/org/msgpack/core/example/MessagePackExample.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java index b4250c40c..5feb15dbc 100644 --- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java +++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java @@ -15,9 +15,13 @@ // package org.msgpack.core.example; -import org.msgpack.core.*; +import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePack.PackerConfig; import org.msgpack.core.MessagePack.UnpackerConfig; +import org.msgpack.core.MessageBufferPacker; +import org.msgpack.core.MessageFormat; +import org.msgpack.core.MessagePacker; +import org.msgpack.core.MessageUnpacker; import org.msgpack.value.ArrayValue; import org.msgpack.value.ExtensionValue; import org.msgpack.value.FloatValue; From 51e4a0a18d594c93121e9da4211aee285e663cb2 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Wed, 27 Jul 2016 14:24:51 -0700 Subject: [PATCH 006/417] MessageBuffer: exception and validation fixes with docs --- .../msgpack/core/buffer/MessageBuffer.java | 116 +++++++++++++++--- 1 file changed, 101 insertions(+), 15 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index d7eff7ba7..3fa6a3be2 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -19,6 +19,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -182,24 +183,76 @@ public class MessageBuffer */ protected final ByteBuffer reference; - public static MessageBuffer allocate(int length) + /** + * Allocates a new MessageBuffer backed by a byte array. + * + * @throws IllegalArgumentException If the capacity is a negative integer + * + */ + public static MessageBuffer allocate(int size) { - return wrap(new byte[length]); + if (size < 0) { + throw new IllegalArgumentException("size must not be negative"); + } + return wrap(new byte[size]); } + /** + * Wraps a ByteBuffer into a MessageBuffer. + * + * The new MessageBuffer will be backed by the given byte array. Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa. + * + * The new buffer's size will be array.length. hasArray() will return true. + * + * @param array the byte array that will gack this MessageBuffer + * @return + * + */ public static MessageBuffer wrap(byte[] array) { return newMessageBuffer(array, 0, array.length); } + /** + * Wraps a ByteBuffer into a MessageBuffer. + * + * The new MessageBuffer will be backed by the given byte array. Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa. + * + * The new buffer's size will be length. hasArray() will return true. + * + * @param array the byte array that will gack this MessageBuffer + * @param offset The offset of the subarray to be used; must be non-negative and no larger than array.length + * @param length The length of the subarray to be used; must be non-negative and no larger than array.length - offset + * @return + * + */ public static MessageBuffer wrap(byte[] array, int offset, int length) { return newMessageBuffer(array, offset, length); } + /** + * Wraps a ByteBuffer into a MessageBuffer. + * + * The new MessageBuffer will be backed by the given byte buffer. Modifications to the new MessageBuffer will cause the byte buffer to be modified and vice versa. However, change of position, limit, or mark of given byte buffer doesn't affect MessageBuffer. + * + * The new buffer's size will be bb.remaining(). hasArray() will return the same result with bb.hasArray(). + * + * @param bb the byte buffer that will gack this MessageBuffer + * @throws IllegalArgumentException given byte buffer returns false both from hasArray() and isDirect() + * @throws UnsupportedOperationException given byte buffer is a direct buffer and this platform doesn't support Unsafe API + * @return + * + */ public static MessageBuffer wrap(ByteBuffer bb) { - return newMessageBuffer(bb).slice(bb.position(), bb.remaining()); + MessageBuffer b = newMessageBuffer(bb); + if (bb.position() > 0 || bb.limit() != bb.capacity()) { + return b.slice(bb.position(), bb.remaining()); + } + else { + return b; + } } /** @@ -214,8 +267,24 @@ private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len) try { return (MessageBuffer) mbArrConstructor.newInstance(arr, off, len); } - catch (Throwable e) { - throw new RuntimeException(e); + catch (InstantiationException e) { + // should never happen + throw new IllegalStateException(e); + } + catch (IllegalAccessException e) { + // should never happen unless security manager restricts this reflection + throw new IllegalStateException(e); + } + catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) { + // underlaying constructor may throw RuntimeException + throw (RuntimeException) e.getCause(); + } + else if (e.getCause() instanceof Error) { + throw (Error) e.getCause(); + } + // should never happen + throw new IllegalStateException(e.getCause()); } } @@ -232,18 +301,35 @@ private static MessageBuffer newMessageBuffer(ByteBuffer bb) // We need to use reflection to create MessageBuffer instances in order to prevent TypeProfile generation for getInt method. TypeProfile will be // generated to resolve one of the method references when two or more classes overrides the method. return (MessageBuffer) mbBBConstructor.newInstance(bb); - } catch (Exception e) { - throw new RuntimeException(e); + } + catch (InstantiationException e) { + // should never happen + throw new IllegalStateException(e); + } + catch (IllegalAccessException e) { + // should never happen unless security manager restricts this reflection + throw new IllegalStateException(e); + } + catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) { + // underlaying constructor may throw RuntimeException + throw (RuntimeException) e.getCause(); + } + else if (e.getCause() instanceof Error) { + throw (Error) e.getCause(); + } + // should never happen + throw new IllegalStateException(e.getCause()); } } public static void releaseBuffer(MessageBuffer buffer) { - if (isUniversalBuffer || buffer.base instanceof byte[]) { + if (isUniversalBuffer || buffer.base != null) { // We have nothing to do. Wait until the garbage-collector collects this array object } - else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.base)) { - DirectBufferAccess.clean(buffer.base); + else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.reference)) { + DirectBufferAccess.clean(buffer.reference); } else { // Maybe cannot reach here @@ -260,7 +346,7 @@ else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.base)) { */ MessageBuffer(byte[] arr, int offset, int length) { - this.base = arr; + this.base = arr; // non-null is already checked at newMessageBuffer this.address = ARRAY_BYTE_BASE_OFFSET + offset; this.size = length; this.reference = null; @@ -275,7 +361,7 @@ else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.base)) { { if (bb.isDirect()) { if (isUniversalBuffer) { - throw new IllegalStateException("Cannot create MessageBuffer from DirectBuffer"); + throw new UnsupportedOperationException("Cannot create MessageBuffer from a DirectBuffer on this platform"); } // Direct buffer or off-heap memory this.base = null; @@ -290,7 +376,7 @@ else if (bb.hasArray()) { this.reference = null; } else { - throw new IllegalArgumentException("Only the array-backed ByteBuffer or DirectBuffer are supported"); + throw new IllegalArgumentException("Only the array-backed ByteBuffer or DirectBuffer is supported"); } } @@ -475,7 +561,7 @@ public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int le */ public ByteBuffer sliceAsByteBuffer(int index, int length) { - if (hasArray()) { + if (base != null) { return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length); } else { @@ -496,7 +582,7 @@ public ByteBuffer sliceAsByteBuffer() public boolean hasArray() { - return base instanceof byte[]; + return base != null; } /** From 4cb93245f809dface61c5c3647a41924c05fdc6d Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Thu, 28 Jul 2016 17:21:49 -0700 Subject: [PATCH 007/417] MessageBuffer.base != null check should all call hasArray for ease of future change --- .../main/java/org/msgpack/core/buffer/MessageBuffer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 3fa6a3be2..1d32d2b1d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -325,7 +325,7 @@ else if (e.getCause() instanceof Error) { public static void releaseBuffer(MessageBuffer buffer) { - if (isUniversalBuffer || buffer.base != null) { + if (isUniversalBuffer || buffer.hasArray()) { // We have nothing to do. Wait until the garbage-collector collects this array object } else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.reference)) { @@ -536,7 +536,7 @@ else if (src.hasArray()) { src.position(src.position() + len); } else { - if (base != null) { + if (hasArray()) { src.get((byte[]) base, index, len); } else { @@ -561,7 +561,7 @@ public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int le */ public ByteBuffer sliceAsByteBuffer(int index, int length) { - if (base != null) { + if (hasArray()) { return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length); } else { From ee8c341c1f8bdc23cadb980a433dfe619109eb4e Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Thu, 28 Jul 2016 17:22:23 -0700 Subject: [PATCH 008/417] removed nunsed import --- .../src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java | 2 -- .../src/main/java/org/msgpack/core/buffer/ByteBufferInput.java | 1 - 2 files changed, 3 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java index 3d11ad9ed..5c6454e69 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java @@ -15,8 +15,6 @@ // package org.msgpack.core.buffer; -import java.io.IOException; - import static org.msgpack.core.Preconditions.checkNotNull; /** diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java index f644d18d1..fd0311b83 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java @@ -15,7 +15,6 @@ // package org.msgpack.core.buffer; -import java.io.IOException; import java.nio.ByteBuffer; import static org.msgpack.core.Preconditions.checkNotNull; From 5c77085e7b212bb7105c786bf4aaa18f3814c5de Mon Sep 17 00:00:00 2001 From: "Min(Dongmin Yu)" Date: Thu, 4 Aug 2016 12:50:50 +0900 Subject: [PATCH 009/417] Refactor creating MessageBuffer instance --- .../msgpack/core/buffer/MessageBuffer.java | 40 +++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 1d32d2b1d..0f4b39e0b 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -198,7 +198,7 @@ public static MessageBuffer allocate(int size) } /** - * Wraps a ByteBuffer into a MessageBuffer. + * Wraps a byte array into a MessageBuffer. * * The new MessageBuffer will be backed by the given byte array. Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa. * @@ -214,7 +214,7 @@ public static MessageBuffer wrap(byte[] array) } /** - * Wraps a ByteBuffer into a MessageBuffer. + * Wraps a byte array into a MessageBuffer. * * The new MessageBuffer will be backed by the given byte array. Modifications to the new MessageBuffer will cause the byte array to be modified and vice versa. * @@ -264,28 +264,7 @@ public static MessageBuffer wrap(ByteBuffer bb) private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len) { checkNotNull(arr); - try { - return (MessageBuffer) mbArrConstructor.newInstance(arr, off, len); - } - catch (InstantiationException e) { - // should never happen - throw new IllegalStateException(e); - } - catch (IllegalAccessException e) { - // should never happen unless security manager restricts this reflection - throw new IllegalStateException(e); - } - catch (InvocationTargetException e) { - if (e.getCause() instanceof RuntimeException) { - // underlaying constructor may throw RuntimeException - throw (RuntimeException) e.getCause(); - } - else if (e.getCause() instanceof Error) { - throw (Error) e.getCause(); - } - // should never happen - throw new IllegalStateException(e.getCause()); - } + return newInstance(mbArrConstructor, arr, off, len); } /** @@ -297,10 +276,21 @@ else if (e.getCause() instanceof Error) { private static MessageBuffer newMessageBuffer(ByteBuffer bb) { checkNotNull(bb); + return newInstance(mbBBConstructor, bb); + } + + /** + * Creates a new MessageBuffer instance + * + * @param constructor A MessageBuffer constructor + * @return new MessageBuffer instance + */ + private static MessageBuffer newInstance(Constructor constructor, Object... args) + { try { // We need to use reflection to create MessageBuffer instances in order to prevent TypeProfile generation for getInt method. TypeProfile will be // generated to resolve one of the method references when two or more classes overrides the method. - return (MessageBuffer) mbBBConstructor.newInstance(bb); + return (MessageBuffer) constructor.newInstance(args); } catch (InstantiationException e) { // should never happen From 4ce46a3b987c5d60bd100015ad9da242fe5d03cd Mon Sep 17 00:00:00 2001 From: "Min(Dongmin Yu)" Date: Tue, 9 Aug 2016 10:40:33 +0900 Subject: [PATCH 010/417] Add more tests for ByteBuffer --- .../msgpack/core/MessageUnpackerTest.scala | 189 ++++++++++++++---- 1 file changed, 145 insertions(+), 44 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 173620282..3aaedb8b8 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -345,6 +345,22 @@ class MessageUnpackerTest extends MessagePackSpec { "be faster then msgpack-v6 skip" taggedAs ("cmp-skip") in { + trait Fixture { + val unpacker: MessageUnpacker + def run { + var count = 0 + try { + while (unpacker.hasNext) { + unpacker.skipValue() + count += 1 + } + } + finally { + unpacker.close() + } + } + } + val data = testData3(10000) val N = 100 @@ -367,21 +383,29 @@ class MessageUnpackerTest extends MessagePackSpec { unpacker.close() } - block("v7") { - val unpacker = Random.shuffle(unpackers(data)).head - var count = 0 - try { - while (unpacker.hasNext) { - unpacker.skipValue() - count += 1 - } - } - finally - unpacker.close() + block("v7-array") { + new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(data) }.run + } + + block("v7-array-buffer") { + new Fixture { + val bb = ByteBuffer.allocate(data.length) + bb.put(data).flip() + override val unpacker = MessagePack.newDefaultUnpacker(bb) + }.run + } + block("v7-direct-buffer") { + new Fixture { + val db = ByteBuffer.allocateDirect(data.length) + db.put(data).flip() + override val unpacker = MessagePack.newDefaultUnpacker(db) + }.run } } - t("v7").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + t("v7-array").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + t("v7-array-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax } import org.msgpack.`type`.{ValueType => ValueTypeV6} @@ -448,6 +472,20 @@ class MessageUnpackerTest extends MessagePackSpec { unpacker.skipValue() } } + trait Fixture { + val unpacker : MessageUnpacker + def run { + var count = 0 + try { + while (unpacker.hasNext) { + readValue(unpacker) + count += 1 + } + } + finally + unpacker.close() + } + } val data = testData3(10000) val N = 100 @@ -469,22 +507,29 @@ class MessageUnpackerTest extends MessagePackSpec { unpacker.close() } - block("v7") { - val unpacker = Random.shuffle(unpackers(data)).head - var count = 0 - try { - while (unpacker.hasNext) { - readValue(unpacker) - count += 1 - } - } - finally - unpacker.close() + block("v7-array") { + new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(data) }.run } - } - t("v7").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + block("v7-array-buffer") { + new Fixture { + val bb = ByteBuffer.allocate(data.length) + bb.put(data).flip() + override val unpacker = MessagePack.newDefaultUnpacker(bb) + }.run + } + block("v7-direct-buffer") { + new Fixture { + val db = ByteBuffer.allocateDirect(data.length) + db.put(data).flip() + override val unpacker = MessagePack.newDefaultUnpacker(db) + }.run + } + } + t("v7-array").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + t("v7-array-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax } @@ -500,6 +545,35 @@ class MessageUnpackerTest extends MessagePackSpec { } packer.close() + trait Fixture { + val unpacker : MessageUnpacker + val loop : Int + def run { + var i = 0 + try { + while (i < loop) { + val len = unpacker.unpackBinaryHeader() + val out = new Array[Byte](len) + unpacker.readPayload(out, 0, len) + i += 1 + } + } + finally + unpacker.close() + } + def runRef { + var i = 0 + try { + while (i < loop) { + val len = unpacker.unpackBinaryHeader() + val out = unpacker.readPayloadAsReference(len) + i += 1 + } + } + finally + unpacker.close() + } + } val b = bos.toByteArray time("unpackBinary", repeat = 100) { block("v6") { @@ -513,27 +587,54 @@ class MessageUnpackerTest extends MessagePackSpec { unpacker.close() } - block("v7") { - val unpacker = Random.shuffle(unpackers(b)).head - var i = 0 - while (i < R) { - val len = unpacker.unpackBinaryHeader() - val out = new Array[Byte](len) - unpacker.readPayload(out, 0, len) - i += 1 - } - unpacker.close() + block("v7-array") { + new Fixture { + override val unpacker = MessagePack.newDefaultUnpacker(b) + override val loop = R + }.run } - block("v7-ref") { - val unpacker = Random.shuffle(unpackers(b)).head - var i = 0 - while (i < R) { - val len = unpacker.unpackBinaryHeader() - val out = unpacker.readPayloadAsReference(len) - i += 1 - } - unpacker.close() + block("v7-array-buffer") { + new Fixture { + val bb = ByteBuffer.allocate(b.length) + bb.put(b).flip() + override val unpacker = MessagePack.newDefaultUnpacker(bb) + override val loop = R + }.run + } + + block("v7-direct-buffer") { + new Fixture { + val db = ByteBuffer.allocateDirect(b.length) + db.put(b).flip() + override val unpacker = MessagePack.newDefaultUnpacker(db) + override val loop = R + }.run + } + + block("v7-ref-array") { + new Fixture { + override val unpacker = MessagePack.newDefaultUnpacker(b) + override val loop = R + }.run + } + + block("v7-ref-array-buffer") { + new Fixture { + val bb = ByteBuffer.allocate(b.length) + bb.put(b).flip() + override val unpacker = MessagePack.newDefaultUnpacker(bb) + override val loop = R + }.run + } + + block("v7-ref-direct-buffer") { + new Fixture { + val db = ByteBuffer.allocateDirect(b.length) + db.put(b).flip() + override val unpacker = MessagePack.newDefaultUnpacker(db) + override val loop = R + }.run } } } From c24eb5f7684bd7cd183e69f452dd6f52019d23b6 Mon Sep 17 00:00:00 2001 From: Min Date: Wed, 10 Aug 2016 17:16:41 +0900 Subject: [PATCH 011/417] Add ByteBuffer constructor at MessageBufferU and MessageBufferBE --- .../main/java/org/msgpack/core/buffer/MessageBufferBE.java | 7 +++++++ .../main/java/org/msgpack/core/buffer/MessageBufferU.java | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java index 1326b396e..0676de6da 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java @@ -15,6 +15,8 @@ // package org.msgpack.core.buffer; +import java.nio.ByteBuffer; + import static org.msgpack.core.Preconditions.checkArgument; /** @@ -30,6 +32,11 @@ public class MessageBufferBE super(arr, offset, length); } + MessageBufferBE(ByteBuffer bb) + { + super(bb); + } + private MessageBufferBE(Object base, long address, int length) { super(base, address, length); diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java index 1e8783738..1ac4b129c 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java @@ -37,6 +37,12 @@ public class MessageBufferU this.wrap = bb.slice(); } + MessageBufferU(ByteBuffer bb) + { + super(bb); + this.wrap = bb.slice(); + } + private MessageBufferU(Object base, long address, int length, ByteBuffer wrap) { super(base, address, length); From f09f595b16dac8d3814f4ddacc1b4e30dfbb2d0c Mon Sep 17 00:00:00 2001 From: "Min(Dongmin Yu)" Date: Fri, 12 Aug 2016 14:11:09 +0900 Subject: [PATCH 012/417] Fix test failures at universal MessageBuffer --- .../msgpack/core/buffer/MessageBuffer.java | 16 +++------ .../msgpack/core/buffer/MessageBufferU.java | 11 +++--- .../msgpack/core/MessageUnpackerTest.scala | 27 ++++++++------ .../core/buffer/MessageBufferTest.scala | 35 +++++++++---------- 4 files changed, 45 insertions(+), 44 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 0f4b39e0b..50d472ae5 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -246,13 +246,7 @@ public static MessageBuffer wrap(byte[] array, int offset, int length) */ public static MessageBuffer wrap(ByteBuffer bb) { - MessageBuffer b = newMessageBuffer(bb); - if (bb.position() > 0 || bb.limit() != bb.capacity()) { - return b.slice(bb.position(), bb.remaining()); - } - else { - return b; - } + return newMessageBuffer(bb); } /** @@ -355,14 +349,14 @@ else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.reference)) { } // Direct buffer or off-heap memory this.base = null; - this.address = DirectBufferAccess.getAddress(bb); - this.size = bb.capacity(); + this.address = DirectBufferAccess.getAddress(bb) + bb.position(); + this.size = bb.remaining(); this.reference = bb; } else if (bb.hasArray()) { this.base = bb.array(); - this.address = ARRAY_BYTE_BASE_OFFSET; - this.size = bb.array().length; + this.address = ARRAY_BYTE_BASE_OFFSET + bb.arrayOffset() + bb.position(); + this.size = bb.remaining(); this.reference = null; } else { diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java index 1ac4b129c..6af9f8d7d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java @@ -31,10 +31,7 @@ public class MessageBufferU MessageBufferU(byte[] arr, int offset, int length) { super(arr, offset, length); - ByteBuffer bb = ByteBuffer.wrap(arr); - bb.position(offset); - bb.limit(offset + length); - this.wrap = bb.slice(); + this.wrap = ByteBuffer.wrap(arr, offset, length).slice(); } MessageBufferU(ByteBuffer bb) @@ -248,6 +245,12 @@ public void copyTo(int index, MessageBuffer dst, int offset, int length) } } + @Override + public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int len) + { + putBytes(index, src.toByteArray(), srcOffset, len); + } + @Override public byte[] toByteArray() { diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 3aaedb8b8..8677644ff 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -46,6 +46,7 @@ import MessageUnpackerTest._ class MessageUnpackerTest extends MessagePackSpec { + val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] def testData: Array[Byte] = { val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) @@ -194,11 +195,14 @@ class MessageUnpackerTest extends MessagePackSpec { val db = ByteBuffer.allocateDirect(data.length) bb.put(data).flip() db.put(data).flip() - Seq( - MessagePack.newDefaultUnpacker(data), - MessagePack.newDefaultUnpacker(bb), - MessagePack.newDefaultUnpacker(db) - ) + val builder = Seq.newBuilder[MessageUnpacker] + builder += MessagePack.newDefaultUnpacker(data) + builder += MessagePack.newDefaultUnpacker(bb) + if (!universal) { + builder += MessagePack.newDefaultUnpacker(db) + } + + builder.result() } "MessageUnpacker" should { @@ -394,7 +398,7 @@ class MessageUnpackerTest extends MessagePackSpec { override val unpacker = MessagePack.newDefaultUnpacker(bb) }.run } - block("v7-direct-buffer") { + if (!universal) block("v7-direct-buffer") { new Fixture { val db = ByteBuffer.allocateDirect(data.length) db.put(data).flip() @@ -405,7 +409,7 @@ class MessageUnpackerTest extends MessagePackSpec { t("v7-array").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax t("v7-array-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax - t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + if (!universal) t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax } import org.msgpack.`type`.{ValueType => ValueTypeV6} @@ -518,7 +522,8 @@ class MessageUnpackerTest extends MessagePackSpec { override val unpacker = MessagePack.newDefaultUnpacker(bb) }.run } - block("v7-direct-buffer") { + + if (!universal) block("v7-direct-buffer") { new Fixture { val db = ByteBuffer.allocateDirect(data.length) db.put(data).flip() @@ -529,7 +534,7 @@ class MessageUnpackerTest extends MessagePackSpec { t("v7-array").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax t("v7-array-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax - t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + if (!universal) t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax } @@ -603,7 +608,7 @@ class MessageUnpackerTest extends MessagePackSpec { }.run } - block("v7-direct-buffer") { + if (!universal) block("v7-direct-buffer") { new Fixture { val db = ByteBuffer.allocateDirect(b.length) db.put(b).flip() @@ -628,7 +633,7 @@ class MessageUnpackerTest extends MessagePackSpec { }.run } - block("v7-ref-direct-buffer") { + if (!universal) block("v7-ref-direct-buffer") { new Fixture { val db = ByteBuffer.allocateDirect(b.length) db.put(b).flip() diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala index a585b9537..b7871065b 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala @@ -29,6 +29,7 @@ class MessageBufferTest "MessageBuffer" should { + val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] "check buffer type" in { val b = MessageBuffer.allocate(0) info(s"MessageBuffer type: ${b.getClass.getName}") @@ -55,7 +56,7 @@ class MessageBufferTest val M = 64 * 1024 * 1024 val ub = MessageBuffer.allocate(M) - val ud = MessageBuffer.wrap(ByteBuffer.allocateDirect(M)) + val ud = if (universal) MessageBuffer.wrap(ByteBuffer.allocate(M)) else MessageBuffer.wrap(ByteBuffer.allocateDirect(M)) val hb = ByteBuffer.allocate(M) val db = ByteBuffer.allocateDirect(M) @@ -150,13 +151,14 @@ class MessageBufferTest } } } + val builder = Seq.newBuilder[MessageBuffer] + builder += MessageBuffer.allocate(10) + builder += MessageBuffer.wrap(ByteBuffer.allocate(10)) + if (!universal) builder += MessageBuffer.wrap(ByteBuffer.allocateDirect(10)) + val buffers = builder.result() "convert to ByteBuffer" in { - for (t <- Seq( - MessageBuffer.allocate(10), - MessageBuffer.wrap(ByteBuffer.allocate(10)), - MessageBuffer.wrap(ByteBuffer.allocateDirect(10))) - ) { + for (t <- buffers) { val bb = t.sliceAsByteBuffer bb.position shouldBe 0 bb.limit shouldBe 10 @@ -165,11 +167,7 @@ class MessageBufferTest } "put ByteBuffer on itself" in { - for (t <- Seq( - MessageBuffer.allocate(10), - MessageBuffer.wrap(ByteBuffer.allocate(10)), - MessageBuffer.wrap(ByteBuffer.allocateDirect(10))) - ) { + for (t <- buffers) { val b = Array[Byte](0x02, 0x03) val srcArray = ByteBuffer.wrap(b) val srcHeap = ByteBuffer.allocate(b.length) @@ -193,19 +191,18 @@ class MessageBufferTest } "put MessageBuffer on itself" in { - for (t <- Seq( - MessageBuffer.allocate(10), - MessageBuffer.wrap(ByteBuffer.allocate(10)), - MessageBuffer.wrap(ByteBuffer.allocateDirect(10))) - ) { + for (t <- buffers) { val b = Array[Byte](0x02, 0x03) val srcArray = ByteBuffer.wrap(b) val srcHeap = ByteBuffer.allocate(b.length) srcHeap.put(b).flip val srcOffHeap = ByteBuffer.allocateDirect(b.length) srcOffHeap.put(b).flip + val builder = Seq.newBuilder[ByteBuffer] + builder ++= Seq(srcArray, srcHeap) + if (!universal) builder += srcOffHeap - for (src <- Seq(MessageBuffer.wrap(srcArray), MessageBuffer.wrap(srcHeap), MessageBuffer.wrap(srcOffHeap))) { + for (src <- builder.result().map(d => MessageBuffer.wrap(d))) { // Write header bytes val header = Array[Byte](0x00, 0x01) t.putBytes(0, header, 0, header.length) @@ -256,7 +253,9 @@ class MessageBufferTest checkSliceAndCopyTo(MessageBuffer.wrap(prepareBytes), MessageBuffer.wrap(prepareBytes)) checkSliceAndCopyTo(MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)), MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes))) - checkSliceAndCopyTo(MessageBuffer.wrap(prepareDirectBuffer), MessageBuffer.wrap(prepareDirectBuffer)) + if (!universal) { + checkSliceAndCopyTo(MessageBuffer.wrap(prepareDirectBuffer), MessageBuffer.wrap(prepareDirectBuffer)) + } } } } From ed1c3a33c9aea7e7410a8b69ff654fe66f5d833f Mon Sep 17 00:00:00 2001 From: "Min(Dongmin Yu)" Date: Fri, 12 Aug 2016 14:50:41 +0900 Subject: [PATCH 013/417] Remove side effect of unpacker benchmark --- .../msgpack/core/MessageUnpackerTest.scala | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 8677644ff..1c8864c7c 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -367,6 +367,10 @@ class MessageUnpackerTest extends MessagePackSpec { val data = testData3(10000) val N = 100 + val bb = ByteBuffer.allocate(data.length) + bb.put(data).flip() + val db = ByteBuffer.allocateDirect(data.length) + db.put(data).flip() val t = time("skip performance", repeat = N) { block("v6") { @@ -393,15 +397,11 @@ class MessageUnpackerTest extends MessagePackSpec { block("v7-array-buffer") { new Fixture { - val bb = ByteBuffer.allocate(data.length) - bb.put(data).flip() override val unpacker = MessagePack.newDefaultUnpacker(bb) }.run } if (!universal) block("v7-direct-buffer") { new Fixture { - val db = ByteBuffer.allocateDirect(data.length) - db.put(data).flip() override val unpacker = MessagePack.newDefaultUnpacker(db) }.run } @@ -493,6 +493,11 @@ class MessageUnpackerTest extends MessagePackSpec { val data = testData3(10000) val N = 100 + val bb = ByteBuffer.allocate(data.length) + bb.put(data).flip() + val db = ByteBuffer.allocateDirect(data.length) + db.put(data).flip() + val t = time("unpack performance", repeat = N) { block("v6") { val v6 = new org.msgpack.MessagePack() @@ -517,16 +522,12 @@ class MessageUnpackerTest extends MessagePackSpec { block("v7-array-buffer") { new Fixture { - val bb = ByteBuffer.allocate(data.length) - bb.put(data).flip() override val unpacker = MessagePack.newDefaultUnpacker(bb) }.run } if (!universal) block("v7-direct-buffer") { new Fixture { - val db = ByteBuffer.allocateDirect(data.length) - db.put(data).flip() override val unpacker = MessagePack.newDefaultUnpacker(db) }.run } @@ -580,6 +581,11 @@ class MessageUnpackerTest extends MessagePackSpec { } } val b = bos.toByteArray + val bb = ByteBuffer.allocate(b.length) + bb.put(b).flip() + val db = ByteBuffer.allocateDirect(b.length) + db.put(b).flip() + time("unpackBinary", repeat = 100) { block("v6") { val v6 = new org.msgpack.MessagePack() @@ -601,8 +607,6 @@ class MessageUnpackerTest extends MessagePackSpec { block("v7-array-buffer") { new Fixture { - val bb = ByteBuffer.allocate(b.length) - bb.put(b).flip() override val unpacker = MessagePack.newDefaultUnpacker(bb) override val loop = R }.run @@ -610,8 +614,6 @@ class MessageUnpackerTest extends MessagePackSpec { if (!universal) block("v7-direct-buffer") { new Fixture { - val db = ByteBuffer.allocateDirect(b.length) - db.put(b).flip() override val unpacker = MessagePack.newDefaultUnpacker(db) override val loop = R }.run @@ -621,25 +623,21 @@ class MessageUnpackerTest extends MessagePackSpec { new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(b) override val loop = R - }.run + }.runRef } block("v7-ref-array-buffer") { new Fixture { - val bb = ByteBuffer.allocate(b.length) - bb.put(b).flip() override val unpacker = MessagePack.newDefaultUnpacker(bb) override val loop = R - }.run + }.runRef } if (!universal) block("v7-ref-direct-buffer") { new Fixture { - val db = ByteBuffer.allocateDirect(b.length) - db.put(b).flip() override val unpacker = MessagePack.newDefaultUnpacker(db) override val loop = R - }.run + }.runRef } } } From ead550c175c89d2620b499626d8a47f46a936dbe Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 17 Aug 2016 14:08:58 -0700 Subject: [PATCH 014/417] Add 0.8.9 release notes --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b07e94363..1f8f26460 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Release Notes +## 0.8.9 + * Add DirectByteBuffer support + * Add Flushable interface to MessagePacker + ## 0.8.8 * [Fix Unexpected UTF-8 encoder state](https://github.com/msgpack/msgpack-java/issues/371) * Make MessageUnpacker.hasNext extensible From d43f262ab9b36fa365945e0453e6e00b10cdc954 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 17 Aug 2016 14:10:13 -0700 Subject: [PATCH 015/417] Setting version to 0.8.9 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index a1fd4ca6d..0d4ca1487 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.9-SNAPSHOT" \ No newline at end of file +version in ThisBuild := "0.8.9" \ No newline at end of file From 3f7ae96909a849fea6878367069f532bd8871bea Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 17 Aug 2016 14:11:03 -0700 Subject: [PATCH 016/417] Setting version to 0.8.10-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 0d4ca1487..9610f951b 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.9" \ No newline at end of file +version in ThisBuild := "0.8.10-SNAPSHOT" \ No newline at end of file From 9467f61720ef79826aca15c8506e9b94854fe00e Mon Sep 17 00:00:00 2001 From: Min Date: Fri, 23 Sep 2016 21:51:53 +0900 Subject: [PATCH 017/417] resetDecoder should be called once per decoding --- .../org/msgpack/core/MessageUnpacker.java | 10 +-- .../buffer/SequenceMessageBufferInput.java | 81 +++++++++++++++++++ .../msgpack/core/MessageUnpackerTest.scala | 45 ++++++++++- 3 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 399e126dc..0696cd54c 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -940,12 +940,13 @@ public String unpackString() if (len > stringSizeLimit) { throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, len), len); } + + resetDecoder(); // should be invoked only once per value + if (buffer.size() - position >= len) { return decodeStringFastPath(len); } - resetDecoder(); - try { int rawRemaining = len; while (rawRemaining > 0) { @@ -1039,10 +1040,7 @@ private String decodeStringFastPath(int length) return s; } else { - resetDecoder(); - ByteBuffer bb = buffer.sliceAsByteBuffer(); - bb.limit(position + length); - bb.position(position); + ByteBuffer bb = buffer.sliceAsByteBuffer(position, length); CharBuffer cb; try { cb = decoder.decode(bb); diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java new file mode 100644 index 000000000..59d52acdc --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java @@ -0,0 +1,81 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.core.buffer; + +import java.io.IOException; +import java.util.Enumeration; + +import static org.msgpack.core.Preconditions.checkNotNull; + +/** + * {@link MessageBufferInput} adapter for {@link MessageBufferInput} Enumeration + */ +public class SequenceMessageBufferInput + implements MessageBufferInput +{ + private Enumeration sequence; + private MessageBufferInput input; + + public SequenceMessageBufferInput(Enumeration sequence) + { + this.sequence = checkNotNull(sequence, "input sequence is null"); + try { + nextInput(); + } + catch (IOException ignore) { + } + } + + @Override + public MessageBuffer next() throws IOException + { + if (input == null) { + return null; + } + MessageBuffer buffer = input.next(); + if (buffer == null) { + nextInput(); + return next(); + } + + return buffer; + } + + private void nextInput() throws IOException + { + if (input != null) { + input.close(); + } + + if (sequence.hasMoreElements()) { + input = sequence.nextElement(); + if (input == null) { + throw new NullPointerException(); + } + } + else { + input = null; + } + } + + @Override + public void close() throws IOException + { + do { + nextInput(); + } while (input != null); + } +} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 1c8864c7c..f2ecb8f28 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -17,11 +17,13 @@ package org.msgpack.core import java.io._ import java.nio.ByteBuffer +import java.util.Collections import org.msgpack.core.buffer._ import org.msgpack.value.ValueType import xerial.core.io.IOUtil._ +import scala.collection.JavaConversions._ import scala.util.Random object MessageUnpackerTest { @@ -205,6 +207,34 @@ class MessageUnpackerTest extends MessagePackSpec { builder.result() } + def sequenceUnpackers(data: Array[Byte], size: Int) : Seq[MessageUnpacker] = { + val seqBytes = Seq.newBuilder[MessageBufferInput] + val seqByteBuffers = Seq.newBuilder[MessageBufferInput] + val seqDirectBuffers = Seq.newBuilder[MessageBufferInput] + var left = data.length + var position = 0 + while (left > 0) { + val length = Math.min(size, left) + seqBytes += new ArrayBufferInput(data, position, length); + val bb = ByteBuffer.allocate(length) + val db = ByteBuffer.allocateDirect(length) + bb.put(data, position, length).flip() + db.put(data, position, length).flip() + seqByteBuffers += new ByteBufferInput(bb); + seqDirectBuffers += new ByteBufferInput(db); + left -= length + position += length + } + val builder = Seq.newBuilder[MessageUnpacker] + builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqBytes.result()))) + builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqByteBuffers.result()))) + if (!universal) { + builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqDirectBuffers.result()))) + } + + builder.result() + } + "MessageUnpacker" should { "parse message packed data" taggedAs ("unpack") in { @@ -330,21 +360,28 @@ class MessageUnpackerTest extends MessagePackSpec { new SplitTest {val data = testData3(30)}.run } - "read numeric data at buffer boundary" taggedAs("boundary2") in { + "read data at buffer boundary" taggedAs("boundary2") in { val packer = MessagePack.newDefaultBufferPacker() (0 until 1170).foreach{i => packer.packLong(0x0011223344556677L) - packer.packString("hello") + packer.packString("hello world") } packer.close val data = packer.toByteArray - val unpacker = MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(data), 8192)) + var unpacker = MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(data), 8192)) (0 until 1170).foreach { i => unpacker.unpackLong() shouldBe 0x0011223344556677L - unpacker.unpackString() shouldBe "hello" + unpacker.unpackString() shouldBe "hello world" } unpacker.close() + + for (unpacker <- sequenceUnpackers(data, 32)) { + (0 until 1170).foreach { i => + unpacker.unpackLong() shouldBe 0x0011223344556677L + unpacker.unpackString() shouldBe "hello world" + } + } } "be faster then msgpack-v6 skip" taggedAs ("cmp-skip") in { From 4c3d46084115b0649cca4735fe595c0710ea2c17 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 23 Sep 2016 09:43:34 -0700 Subject: [PATCH 018/417] Fix code style and test cases --- .../buffer/SequenceMessageBufferInput.java | 2 +- .../msgpack/core/MessageUnpackerTest.scala | 48 ++++++++++++++----- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java index 59d52acdc..10b91d20a 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java @@ -63,7 +63,7 @@ private void nextInput() throws IOException if (sequence.hasMoreElements()) { input = sequence.nextElement(); if (input == null) { - throw new NullPointerException(); + throw new NullPointerException("An element in the MessageBufferInput sequence is null"); } } else { diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index f2ecb8f28..db512373b 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -207,21 +207,21 @@ class MessageUnpackerTest extends MessagePackSpec { builder.result() } - def sequenceUnpackers(data: Array[Byte], size: Int) : Seq[MessageUnpacker] = { + def unpackerCollectionWithVariousBuffers(data: Array[Byte], chunkSize: Int) : Seq[MessageUnpacker] = { val seqBytes = Seq.newBuilder[MessageBufferInput] val seqByteBuffers = Seq.newBuilder[MessageBufferInput] val seqDirectBuffers = Seq.newBuilder[MessageBufferInput] var left = data.length var position = 0 while (left > 0) { - val length = Math.min(size, left) - seqBytes += new ArrayBufferInput(data, position, length); + val length = Math.min(chunkSize, left) + seqBytes += new ArrayBufferInput(data, position, length) val bb = ByteBuffer.allocate(length) val db = ByteBuffer.allocateDirect(length) bb.put(data, position, length).flip() db.put(data, position, length).flip() - seqByteBuffers += new ByteBufferInput(bb); - seqDirectBuffers += new ByteBufferInput(db); + seqByteBuffers += new ByteBufferInput(bb) + seqDirectBuffers += new ByteBufferInput(db) left -= length position += length } @@ -360,25 +360,47 @@ class MessageUnpackerTest extends MessagePackSpec { new SplitTest {val data = testData3(30)}.run } - "read data at buffer boundary" taggedAs("boundary2") in { + "read integer at MessageBuffer boundaries" taggedAs("integer-buffer-boundary") in { val packer = MessagePack.newDefaultBufferPacker() (0 until 1170).foreach{i => packer.packLong(0x0011223344556677L) - packer.packString("hello world") } packer.close val data = packer.toByteArray - var unpacker = MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(data), 8192)) - (0 until 1170).foreach { i => - unpacker.unpackLong() shouldBe 0x0011223344556677L - unpacker.unpackString() shouldBe "hello world" + // Boundary test + withResource(MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(data), 8192))) { unpacker => + (0 until 1170).foreach { i => + unpacker.unpackLong() shouldBe 0x0011223344556677L + } } - unpacker.close() - for (unpacker <- sequenceUnpackers(data, 32)) { + // Boundary test for sequences of ByteBuffer, DirectByteBuffer backed MessageInput. + for (unpacker <- unpackerCollectionWithVariousBuffers(data, 32)) { (0 until 1170).foreach { i => unpacker.unpackLong() shouldBe 0x0011223344556677L + } + } + } + + "read string at MessageBuffer boundaries" taggedAs("string-buffer-boundary") in { + val packer = MessagePack.newDefaultBufferPacker() + (0 until 1170).foreach{i => + packer.packString("hello world") + } + packer.close + val data = packer.toByteArray + + // Boundary test + withResource(MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(data), 8192))) { unpacker => + (0 until 1170).foreach { i => + unpacker.unpackString() shouldBe "hello world" + } + } + + // Boundary test for sequences of ByteBuffer, DirectByteBuffer backed MessageInput. + for (unpacker <- unpackerCollectionWithVariousBuffers(data, 32)) { + (0 until 1170).foreach { i => unpacker.unpackString() shouldBe "hello world" } } From d42694a035aac94949402f4eebd1aeaba5f73a2d Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 23 Sep 2016 10:04:40 -0700 Subject: [PATCH 019/417] Add release notes for 0.8.10 --- RELEASE_NOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 1f8f26460..7b827af4f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,8 @@ # Release Notes +## 0.8.10 + * Fixed a bug of unpackString [#387](https://github.com/msgpack/msgpack-java/pull/387) at the buffer boundary + ## 0.8.9 * Add DirectByteBuffer support * Add Flushable interface to MessagePacker From b5687bf1a1c69a91efca4a94a9352601e889fcec Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 23 Sep 2016 10:07:14 -0700 Subject: [PATCH 020/417] Setting version to 0.8.10 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 9610f951b..7345bbadf 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.10-SNAPSHOT" \ No newline at end of file +version in ThisBuild := "0.8.10" \ No newline at end of file From 8e89b99e6097a11ab3badcbfa7374349c01ffe5a Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 23 Sep 2016 10:09:30 -0700 Subject: [PATCH 021/417] Setting version to 0.8.11-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 7345bbadf..d08150e15 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.10" \ No newline at end of file +version in ThisBuild := "0.8.11-SNAPSHOT" \ No newline at end of file From cf0dfacfcbf7f8973d1c2d6e79b631ad1e6fe854 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 30 Sep 2016 14:56:47 -0700 Subject: [PATCH 022/417] Fix #391: Add missing buffer null check --- .../main/java/org/msgpack/core/MessagePacker.java | 6 ++++-- .../scala/org/msgpack/core/MessagePackerTest.scala | 13 +++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index abaf5734c..5559fd4ad 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -729,8 +729,9 @@ public MessagePacker writePayload(byte[] src) public MessagePacker writePayload(byte[] src, int off, int len) throws IOException { - if (buffer.size() - position < len || len > bufferFlushThreshold) { + if (buffer == null || buffer.size() - position < len || len > bufferFlushThreshold) { flush(); // call flush before write + // Directly write payload to the output without using the buffer out.write(src, off, len); totalFlushBytes += len; } @@ -770,8 +771,9 @@ public MessagePacker addPayload(byte[] src) public MessagePacker addPayload(byte[] src, int off, int len) throws IOException { - if (buffer.size() - position < len || len > bufferFlushThreshold) { + if (buffer == null || buffer.size() - position < len || len > bufferFlushThreshold) { flush(); // call flush before add + // Directly add the payload without using the buffer out.add(src, off, len); totalFlushBytes += len; } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index e9e951dea..c64f6f972 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -317,4 +317,17 @@ class MessagePackerTest extends MessagePackSpec { val s = unpacker.unpackString() s shouldBe "small string" } + + "write raw binary" taggedAs("raw-binary") in { + val packer = new MessagePack.PackerConfig().newBufferPacker() + val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) + packer.writePayload(msg) + } + + "append raw binary" taggedAs("append-raw-binary") in { + val packer = new MessagePack.PackerConfig().newBufferPacker() + val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) + packer.addPayload(msg) + } + } From 94859680c0a15296e417d2d36ebef5b02d8f38d7 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 30 Sep 2016 15:06:25 -0700 Subject: [PATCH 023/417] Add release note for 0.8.11 --- RELEASE_NOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7b827af4f..4ec950ce0 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,8 @@ # Release Notes +## 0.8.11 + * Fixed NPE when write(add)Payload are used at the beginning [#392](https://github.com/msgpack/msgpack-java/pull/392) + ## 0.8.10 * Fixed a bug of unpackString [#387](https://github.com/msgpack/msgpack-java/pull/387) at the buffer boundary From ad555bbb5a31c7497b62845bb22a465127e4e681 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 30 Sep 2016 15:07:55 -0700 Subject: [PATCH 024/417] Setting version to 0.8.11 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index d08150e15..6bfe45248 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.11-SNAPSHOT" \ No newline at end of file +version in ThisBuild := "0.8.11" \ No newline at end of file From f764ba3a1074b4f1a1a1f4c906d7feffc5e2befd Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 30 Sep 2016 15:08:27 -0700 Subject: [PATCH 025/417] Setting version to 0.8.12-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 6bfe45248..9a07a88f1 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.11" \ No newline at end of file +version in ThisBuild := "0.8.12-SNAPSHOT" \ No newline at end of file From 742f2bc71787cae58f8bd6966d5bac418c6785fb Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Fri, 30 Sep 2016 15:10:32 -0700 Subject: [PATCH 026/417] move SequenceMessageBufferInput to test package --- .../java/org/msgpack/core/buffer/SequenceMessageBufferInput.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename msgpack-core/src/{main => test}/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java (100%) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java b/msgpack-core/src/test/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java similarity index 100% rename from msgpack-core/src/main/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java rename to msgpack-core/src/test/java/org/msgpack/core/buffer/SequenceMessageBufferInput.java From 5228c5c31e670b86bca3745a5986fedca133de4a Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Tue, 18 Oct 2016 20:48:59 -0700 Subject: [PATCH 027/417] Adding JavaDoc - part 1 --- .../MessageInsufficientBufferException.java | 3 + .../java/org/msgpack/core/MessagePack.java | 249 +++++++++---- .../java/org/msgpack/core/MessagePacker.java | 297 ++++++++++++++-- .../org/msgpack/core/MessageUnpacker.java | 334 ++++++++++++++++-- 4 files changed, 746 insertions(+), 137 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java b/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java index 838dc77ab..099dcac6f 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java @@ -15,6 +15,9 @@ // package org.msgpack.core; +/** + * Exception that indicates end of input. + */ public class MessageInsufficientBufferException extends MessagePackException { diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 7737aa664..2c84d2328 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -33,20 +33,54 @@ import java.nio.charset.CodingErrorAction; /** - * This class has MessagePack prefix code definitions and packer/unpacker factory methods. + * Convenience class to build packer and unpacker classes. + * + * You may choose factory method as following + * + *

+ * Deserializing objects from binary: + * + * + * + * + * + * + * + * + *
Input typeFactory methodReturn type
byte[]{@link #newDefaultUnpacker(byte[], int, int)}{@link MessageUnpacker}
ByteBuffer{@link #newDefaultUnpacker(ByteBuffer)}{@link MessageUnpacker}
InputStream{@link #newDefaultUnpacker(InputStream)}{@link MessageUnpacker}
ReadableByteChannel{@link #newDefaultUnpacker(ReadableByteChannel)}{@link MessageUnpacker}
{@link org.msgpack.core.buffer.MessageBufferInput}{@link #newDefaultUnpacker(MessageBufferInput)}{@link MessageUnpacker}
+ * + *

+ * Serializing objects into binary: + * + * + * + * + * + * + * + *
Output typeFactory methodReturn type
byte[]{@link #newDefaultBufferPacker()}{@link MessageBufferPacker}
OutputStream{@link #newDefaultPacker(OutputStream)}{@link MessagePacker}
WritableByteChannel{@link #newDefaultPacker(WritableByteChannel)}{@link MessagePacker}
{@link org.msgpack.core.buffer.MessageBufferOutput}{@link #newDefaultPacker(MessageBufferOutput)}{@link MessagePacker}
+ * */ public class MessagePack { + /** + * @exclude + * Applications should use java.nio.charset.StandardCharsets.UTF_8 instead since Java 7. + */ public static final Charset UTF8 = Charset.forName("UTF-8"); /** - * Default packer/unpacker configurations + * Configuration of a {@link MessagePacker} created by {@link #newDefaultPacker(MessageBufferOutput)} and {@link #newDefaultBufferPacker()} methods. */ public static final PackerConfig DEFAULT_PACKER_CONFIG = new PackerConfig(); + + /** + * Configuration of a {@link MessageUnpacker} created by {@link #newDefaultUnpacker(MessageBufferInput)} methods. + */ public static final UnpackerConfig DEFAULT_UNPACKER_CONFIG = new UnpackerConfig(); /** - * The prefix code set of MessagePack. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. + * The prefix code set of MessagePack format. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. */ public static final class Code { @@ -139,10 +173,16 @@ private MessagePack() } /** - * Create a packer that outputs the packed data to the specified output + * Creates a packer that serializes objects into the specified output. + *

+ * {@link org.msgpack.core.buffer.MessageBufferOutput} is an interface that lets applications customize memory + * allocation of internal buffer of {@link MessagePacker}. You may prefer {@link #newDefaultBufferPacker()}, + * {@link #newDefaultPacker(OutputStream)}, or {@link #newDefaultPacker(WritableByteChannel)} methods instead. + *

+ * This method is equivalent to DEFAULT_PACKER_CONFIG.newPacker(out). * - * @param out - * @return + * @param out A MessageBufferOutput that allocates buffer chunks and receives the buffer chunks with packed data filled in them + * @return A new MessagePacker instance */ public static MessagePacker newDefaultPacker(MessageBufferOutput out) { @@ -150,10 +190,15 @@ public static MessagePacker newDefaultPacker(MessageBufferOutput out) } /** - * Create a packer that outputs the packed data to a target output stream + * Creates a packer that serializes objects into the specified output stream. + *

+ * Note that you don't have to wrap OutputStream in BufferedOutputStream because MessagePacker has buffering + * internally. + *

+ * This method is equivalent to DEFAULT_PACKER_CONFIG.newPacker(out). * - * @param out - * @return + * @param out The output stream that receives sequence of bytes + * @return A new MessagePacker instance */ public static MessagePacker newDefaultPacker(OutputStream out) { @@ -161,10 +206,12 @@ public static MessagePacker newDefaultPacker(OutputStream out) } /** - * Create a packer that outputs the packed data to a channel + * Creates a packer that serializes objects into the specified writable channel. + *

+ * This method is equivalent to DEFAULT_PACKER_CONFIG.newPacker(channel). * - * @param channel - * @return + * @param channel The output channel that receives sequence of bytes + * @return A new MessagePacker instance */ public static MessagePacker newDefaultPacker(WritableByteChannel channel) { @@ -172,9 +219,13 @@ public static MessagePacker newDefaultPacker(WritableByteChannel channel) } /** - * Create a packer for storing packed data into a byte array + * Creates a packer that serializes objects into byte arrays. + *

+ * This method provides an optimized implementation of newDefaultBufferPacker(new ByteArrayOutputStream()). + * + * This method is equivalent to DEFAULT_PACKER_CONFIG.newBufferPacker(). * - * @return + * @return A new MessageBufferPacker instance */ public static MessageBufferPacker newDefaultBufferPacker() { @@ -182,10 +233,17 @@ public static MessageBufferPacker newDefaultBufferPacker() } /** - * Create an unpacker that reads the data from a given input + * Creates an unpacker that deserializes objects from a specified input. + *

+ * {@link org.msgpack.core.buffer.MessageBufferInput} is an interface that lets applications customize memory + * allocation of internal buffer of {@link MessageUnpacker}. You may prefer + * {@link #newDefaultUnpacker(InputStream)}, {@link #newDefaultUnpacker(ReadableByteChannel)}, + * {@link #newDefaultUnpacker(byte[], int, int)}, or {@link #newDefaultUnpacker(ByteBuffer)} methods instead. + *

+ * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(in). * - * @param in - * @return + * @param in The input stream that provides sequence of buffer chunks and optionally reuses them when MessageUnpacker consumed one completely + * @return A new MessageUnpacker instance */ public static MessageUnpacker newDefaultUnpacker(MessageBufferInput in) { @@ -193,10 +251,15 @@ public static MessageUnpacker newDefaultUnpacker(MessageBufferInput in) } /** - * Create an unpacker that reads the data from a given input stream + * Creates an unpacker that deserializes objects from a specified input stream. + *

+ * Note that you don't have to wrap InputStream in BufferedInputStream because MessageUnpacker has buffering + * internally. + *

+ * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(in). * - * @param in - * @return + * @param in The input stream that provides sequence of bytes + * @return A new MessageUnpacker instance */ public static MessageUnpacker newDefaultUnpacker(InputStream in) { @@ -204,10 +267,12 @@ public static MessageUnpacker newDefaultUnpacker(InputStream in) } /** - * Create an unpacker that reads the data from a given channel + * Creates an unpacker that deserializes objects from a specified readable channel. + *

+ * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(in). * - * @param channel - * @return + * @param channel The input channel that provides sequence of bytes + * @return A new MessageUnpacker instance */ public static MessageUnpacker newDefaultUnpacker(ReadableByteChannel channel) { @@ -215,10 +280,14 @@ public static MessageUnpacker newDefaultUnpacker(ReadableByteChannel channel) } /** - * Create an unpacker that reads the data from a given byte array + * Creates an unpacker that deserializes objects from a specified byte array. + *

+ * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents)). + *

+ * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(contents). * - * @param contents - * @return + * @param contents The byte array that contains packed objects in MessagePack format + * @return A new MessageUnpacker instance that will never throw IOException */ public static MessageUnpacker newDefaultUnpacker(byte[] contents) { @@ -226,12 +295,16 @@ public static MessageUnpacker newDefaultUnpacker(byte[] contents) } /** - * Create an unpacker that reads the data from a given byte array [offset, offset+length) + * Creates an unpacker that deserializes objects from subarray of a specified byte array. + *

+ * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents, offset, length)). + *

+ * This method is equivalent to DEFAULT_UNPACKER_CONFIG.newDefaultUnpacker(contents). * - * @param contents - * @param offset - * @param length - * @return + * @param contents The byte array that contains packed objects + * @param offset The index of the first byte + * @param length The number of bytes + * @return A new MessageUnpacker instance that will never throw IOException */ public static MessageUnpacker newDefaultUnpacker(byte[] contents, int offset, int length) { @@ -239,10 +312,16 @@ public static MessageUnpacker newDefaultUnpacker(byte[] contents, int offset, in } /** - * Create an unpacker that reads the data from a given ByteBuffer + * Creates an unpacker that deserializes objects from a specified ByteBuffer. + *

+ * Note that the returned unpacker reads data from the current position of the ByteBuffer until its limit. + * However, its position does not change when unpacker reads data. You may use + * {@link MessageUnpacker#getTotalReadBytes()} to get actual amount of bytes used in ByteBuffer. + *

+ * This method supports both non-direct buffer and direct buffer. * - * @param contents - * @return + * @param contents The byte buffer that contains packed objects + * @return A new MessageUnpacker instance that will never throw IOException */ public static MessageUnpacker newDefaultUnpacker(ByteBuffer contents) { @@ -305,10 +384,13 @@ public boolean equals(Object obj) } /** - * Create a packer that outputs the packed data to a given output + * Creates a packer that serializes objects into the specified output. + *

+ * {@link org.msgpack.core.buffer.MessageBufferOutput} is an interface that lets applications customize memory + * allocation of internal buffer of {@link MessagePacker}. * - * @param out - * @return + * @param out A MessageBufferOutput that allocates buffer chunks and receives the buffer chunks with packed data filled in them + * @return A new MessagePacker instance */ public MessagePacker newPacker(MessageBufferOutput out) { @@ -316,10 +398,13 @@ public MessagePacker newPacker(MessageBufferOutput out) } /** - * Create a packer that outputs the packed data to a given output stream + * Creates a packer that serializes objects into the specified output stream. + *

+ * Note that you don't have to wrap OutputStream in BufferedOutputStream because MessagePacker has buffering + * internally. * - * @param out - * @return + * @param out The output stream that receives sequence of bytes + * @return A new MessagePacker instance */ public MessagePacker newPacker(OutputStream out) { @@ -327,10 +412,10 @@ public MessagePacker newPacker(OutputStream out) } /** - * Create a packer that outputs the packed data to a given output channel + * Creates a packer that serializes objects into the specified writable channel. * - * @param channel - * @return + * @param channel The output channel that receives sequence of bytes + * @return A new MessagePacker instance */ public MessagePacker newPacker(WritableByteChannel channel) { @@ -338,9 +423,11 @@ public MessagePacker newPacker(WritableByteChannel channel) } /** - * Create a packer for storing packed data into a byte array + * Creates a packer that serializes objects into byte arrays. + *

+ * This method provides an optimized implementation of newDefaultBufferPacker(new ByteArrayOutputStream()). * - * @return + * @return A new MessageBufferPacker instance */ public MessageBufferPacker newBufferPacker() { @@ -348,13 +435,13 @@ public MessageBufferPacker newBufferPacker() } /** - * Use String.getBytes() for converting Java Strings that are smaller than this threshold into UTF8. + * Use String.getBytes() for converting Java Strings that are shorter than this threshold. * Note that this parameter is subject to change. */ - public PackerConfig withSmallStringOptimizationThreshold(int bytes) + public PackerConfig withSmallStringOptimizationThreshold(int length) { PackerConfig copy = clone(); - copy.smallStringOptimizationThreshold = bytes; + copy.smallStringOptimizationThreshold = length; return copy; } @@ -364,8 +451,8 @@ public int getSmallStringOptimizationThreshold() } /** - * When the next payload size exceeds this threshold, MessagePacker will call MessageBufferOutput.flush() before - * packing the data (default: 8192). + * When the next payload size exceeds this threshold, MessagePacker will call + * {@link org.msgpack.core.buffer.MessageBufferOutput#flush()} before writing more data (default: 8192). */ public PackerConfig withBufferFlushThreshold(int bytes) { @@ -380,7 +467,7 @@ public int getBufferFlushThreshold() } /** - * When a packer is created with newPacker(OutputStream) or newPacker(WritableByteChannel), the stream will be + * When a packer is created with {@link #newPacker(OutputStream)} or {@link #newPacker(WritableByteChannel)}, the stream will be * buffered with this size of buffer (default: 8192). */ public PackerConfig withBufferSize(int bytes) @@ -483,10 +570,13 @@ public boolean equals(Object obj) } /** - * Create an unpacker that reads the data from a given input + * Creates an unpacker that deserializes objects from a specified input. + *

+ * {@link org.msgpack.core.buffer.MessageBufferInput} is an interface that lets applications customize memory + * allocation of internal buffer of {@link MessageUnpacker}. * - * @param in - * @return + * @param in The input stream that provides sequence of buffer chunks and optionally reuses them when MessageUnpacker consumed one completely + * @return A new MessageUnpacker instance */ public MessageUnpacker newUnpacker(MessageBufferInput in) { @@ -494,10 +584,13 @@ public MessageUnpacker newUnpacker(MessageBufferInput in) } /** - * Create an unpacker that reads the data from a given input stream + * Creates an unpacker that deserializes objects from a specified input stream. + *

+ * Note that you don't have to wrap InputStream in BufferedInputStream because MessageUnpacker has buffering + * internally. * - * @param in - * @return + * @param in The input stream that provides sequence of bytes + * @return A new MessageUnpacker instance */ public MessageUnpacker newUnpacker(InputStream in) { @@ -505,10 +598,10 @@ public MessageUnpacker newUnpacker(InputStream in) } /** - * Create an unpacker that reads the data from a given channel + * Creates an unpacker that deserializes objects from a specified readable channel. * - * @param channel - * @return + * @param channel The input channel that provides sequence of bytes + * @return A new MessageUnpacker instance */ public MessageUnpacker newUnpacker(ReadableByteChannel channel) { @@ -516,10 +609,12 @@ public MessageUnpacker newUnpacker(ReadableByteChannel channel) } /** - * Create an unpacker that reads the data from a given byte array + * Creates an unpacker that deserializes objects from a specified byte array. + *

+ * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents)). * - * @param contents - * @return + * @param contents The byte array that contains packed objects in MessagePack format + * @return A new MessageUnpacker instance that will never throw IOException */ public MessageUnpacker newUnpacker(byte[] contents) { @@ -527,10 +622,14 @@ public MessageUnpacker newUnpacker(byte[] contents) } /** - * Create an unpacker that reads the data from a given byte array [offset, offset+size) + * Creates an unpacker that deserializes objects from subarray of a specified byte array. + *

+ * This method provides an optimized implementation of newDefaultUnpacker(new ByteArrayInputStream(contents, offset, length)). * - * @param contents - * @return + * @param contents The byte array that contains packed objects + * @param offset The index of the first byte + * @param length The number of bytes + * @return A new MessageUnpacker instance that will never throw IOException */ public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) { @@ -538,10 +637,14 @@ public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) } /** - * Create an unpacker that reads the data from a given ByteBuffer + * Creates an unpacker that deserializes objects from a specified ByteBuffer. + *

+ * Note that the returned unpacker reads data from the current position of the ByteBuffer until its limit. + * However, its position does not change when unpacker reads data. You may use + * {@link MessageUnpacker#getTotalReadBytes()} to get actual amount of bytes used in ByteBuffer. * - * @param contents - * @return + * @param contents The byte buffer that contains packed objects + * @return A new MessageUnpacker instance that will never throw IOException */ public MessageUnpacker newUnpacker(ByteBuffer contents) { @@ -549,7 +652,7 @@ public MessageUnpacker newUnpacker(ByteBuffer contents) } /** - * Allow unpackBinaryHeader to read str format family (default: true) + * Allows unpackBinaryHeader to read str format family (default: true) */ public UnpackerConfig withAllowReadingStringAsBinary(boolean enable) { @@ -564,7 +667,7 @@ public boolean getAllowReadingStringAsBinary() } /** - * Allow unpackString and unpackRawStringHeader and unpackString to read bin format family (default: true) + * Allows unpackString and unpackRawStringHeader and unpackString to read bin format family (default: true) */ public UnpackerConfig withAllowReadingBinaryAsString(boolean enable) { @@ -579,7 +682,7 @@ public boolean getAllowReadingBinaryAsString() } /** - * Action when encountered a malformed input (default: REPLACE) + * Sets action when encountered a malformed input (default: REPLACE) */ public UnpackerConfig withActionOnMalformedString(CodingErrorAction action) { @@ -594,7 +697,7 @@ public CodingErrorAction getActionOnMalformedString() } /** - * Action when an unmappable character is found (default: REPLACE) + * Sets action when an unmappable character is found (default: REPLACE) */ public UnpackerConfig withActionOnUnmappableString(CodingErrorAction action) { diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 5559fd4ad..423886fd8 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -67,21 +67,65 @@ import static org.msgpack.core.Preconditions.checkNotNull; /** - * Writer of message packed data. - *

+ * MessagePack serializer that converts objects into binary. + * You can use factory methods of {@link MessagePack} class or {@link MessagePack.PackerConfig} class to create + * an instance. *

- * MessagePacker provides packXXX methods for writing values in the message pack format. - * To write raw string or binary data, first use packRawStringHeader or packBinaryHeader to specify the data length, - * then call writePayload(...) method. - *

- *

+ * This class provides following primitive methods to write MessagePack values. These primitive methods write + * short bytes (1 to 7 bytes) to the internal buffer at once. There also some complex methods for convenience. *

- * MessagePacker class has no guarantee to produce the correct message-pack format data if it is not used correctly: - * packXXX methods of primitive values always produce the correct format, but - * packXXXHeader (e.g. array, map, ext) must be followed by correct number of array/map/ext type values. - * packRawStringHeader(length) and packBinaryHeader(length) must be followed by writePayload( ... length) to supply - * the binary data of the specified length in the header. - *

+ * Primitive methods: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Java typePacker methodMessagePack type
null{@link #packNil()}Nil
boolean{@link #packBoolean(boolean)}Boolean
byte{@link #packByte(byte)}Integer
short{@link #packShort(short)}Integer
int{@link #packInt(int)}Integer
long{@link #packLong(long)}Integer
BigInteger{@link #packBigInteger(BigInteger)}Integer
float{@link #packFloat(float)}Float
double{@link #packDouble(double)}Float
byte[]{@link #packBinaryHeader(int)}Binary
String{@link #packRawStringHeader(int)}String
List{@link #packArrayHeader(int)}Array
Map{@link #packMapHeader(int)}Map
custom user type{@link #packExtensionTypeHeader(byte, int)}Extension
+ * + *

+ * Complex methods: + * + * + * + * + * + *
Java typePacker methodMessagePack type
String{@link #packString(String)}String
{@link Value}{@link #packValue(Value)}
+ * + *

+ * To write a byte array, first you call {@link #packBinaryHeader} method with length of the byte array. Then, + * you call {@link #writePayload(byte[], int, int)} or {@link #addPayload(byte[], int, int)} method to write the + * contents. + * + *

+ * To write a List, Collection or array, first you call {@link #packArrayHeader(int)} method with the number of + * elements. Then, you call packer methods for each element. You don't have to call anything at the end of + * iteration. + * + *

+ * To write a Map, first you call {@link #packMapHeader(int)} method with size of the map. Then, for each pair, + * you call packer methods for key first, and then value. You will call packer methods twice as many time as the + * size of the map. You don't have to call anything at the end of iteration. + * + *

+ * Note that packXxxHeader methods don't validate number of elements. You must call packer methods for correct + * number of times to produce valid MessagePack data. + * + *

+ * When IOException is thrown, primitive methods guarantee that all data is written to the internal buffer or no data + * is written. This is convenient behavior when you use a non-blocking output channel that may not be writable + * immediately. */ public class MessagePacker implements Closeable, Flushable @@ -92,6 +136,9 @@ public class MessagePacker private final boolean str8FormatSupport; + /** + * Current internal buffer. + */ protected MessageBufferOutput out; private MessageBuffer buffer; @@ -126,10 +173,18 @@ protected MessagePacker(MessageBufferOutput out, MessagePack.PackerConfig config } /** - * Reset output. This method doesn't close the old resource. + * Replaces underlaying output. + *

+ * This method flushes current internal buffer to the output, swaps it with the new given output, then returns + * the old output. + * + *

+ * This method doesn't close the old output. * * @param out new output - * @return the old resource + * @return the old output + * @throws IOException when underlaying output throws IOException + * @throws NullPointerException the given output is null */ public MessageBufferOutput reset(MessageBufferOutput out) throws IOException @@ -148,11 +203,26 @@ public MessageBufferOutput reset(MessageBufferOutput out) return old; } + /** + * Returns total number of written bytes. + *

+ * This method returns total of amount of data flushed to the underlaying output plus size of current + * internal buffer. + * + *

+ * Calling {@link #reset(MessageBufferOutput)} resets this number to 0. + */ public long getTotalWrittenBytes() { return totalFlushBytes + position; } + /** + * Flushes internal buffer to the underlaying output. + *

+ * This method also calls flush method of the underlaying output after writing internal buffer. + */ + @Override public void flush() throws IOException { @@ -162,6 +232,12 @@ public void flush() out.flush(); } + /** + * Closes underlaying output. + *

+ * This method flushes internal buffer before closing. + */ + @Override public void close() throws IOException { @@ -278,6 +354,14 @@ private void writeLong(long v) position += 8; } + /** + * Writes a Nil value. + * + * This method writes a nil byte. + * + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packNil() throws IOException { @@ -285,6 +369,14 @@ public MessagePacker packNil() return this; } + /** + * Writes a Boolean value. + * + * This method writes a true byte or a false byte. + * + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packBoolean(boolean b) throws IOException { @@ -292,6 +384,16 @@ public MessagePacker packBoolean(boolean b) return this; } + /** + * Writes an Integer value. + * + *

+ * This method writes an integer using the smallest format from the int format family. + * + * @param b the integer to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packByte(byte b) throws IOException { @@ -304,6 +406,16 @@ public MessagePacker packByte(byte b) return this; } + /** + * Writes an Integer value. + * + *

+ * This method writes an integer using the smallest format from the int format family. + * + * @param v the integer to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packShort(short v) throws IOException { @@ -329,6 +441,16 @@ else if (v < (1 << 7)) { return this; } + /** + * Writes an Integer value. + * + *

+ * This method writes an integer using the smallest format from the int format family. + * + * @param v the integer to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packInt(int r) throws IOException { @@ -361,6 +483,16 @@ else if (r < (1 << 16)) { return this; } + /** + * Writes an Integer value. + * + *

+ * This method writes an integer using the smallest format from the int format family. + * + * @param v the integer to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packLong(long v) throws IOException { @@ -407,6 +539,16 @@ else if (v < (1 << 7)) { return this; } + /** + * Writes an Integer value. + * + *

+ * This method writes an integer using the smallest format from the int format family. + * + * @param bi the integer to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packBigInteger(BigInteger bi) throws IOException { @@ -422,6 +564,16 @@ else if (bi.bitLength() == 64 && bi.signum() == 1) { return this; } + /** + * Writes a Float value. + * + *

+ * This method writes a float value using float format family. + * + * @param bi the integer to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packFloat(float v) throws IOException { @@ -429,6 +581,16 @@ public MessagePacker packFloat(float v) return this; } + /** + * Writes a Float value. + * + *

+ * This method writes a float value using float format family. + * + * @param bi the integer to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packDouble(double v) throws IOException { @@ -497,11 +659,14 @@ private int encodeStringToBufferAt(int pos, String s) private static final int UTF_8_MAX_CHAR_SIZE = 6; /** - * Pack the input String in UTF-8 encoding + * Writes a String vlaue in UTF-8 encoding. * - * @param s - * @return - * @throws IOException + *

+ * This method writes a UTF-8 string using the smallest format from the str format family by default. If {@link MessagePack.PackerConfig#withStr8FormatSupport(boolean)} is set to false, smallest format from the str format family excepting str8 format. + * + * @param s the string to be written + * @return this + * @throws IOException when underlaying output throws IOException */ public MessagePacker packString(String s) throws IOException @@ -581,6 +746,17 @@ else if (s.length() < (1 << 16)) { return this; } + /** + * Writes header of an Array value. + *

+ * You will call other packer methods for each element after this method call. + *

+ * You don't have to call anything at the end of iteration. + * + * @param arraySize number of elements to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packArrayHeader(int arraySize) throws IOException { @@ -600,6 +776,18 @@ else if (arraySize < (1 << 16)) { return this; } + /** + * Writes header of a Map value. + *

+ * After this method call, for each key-value pair, you will call packer methods for key first, and then value. + * You will call packer methods twice as many time as the size of the map. + *

+ * You don't have to call anything at the end of iteration. + * + * @param mapSize number of pairs to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packMapHeader(int mapSize) throws IOException { @@ -619,6 +807,13 @@ else if (mapSize < (1 << 16)) { return this; } + /** + * Writes a dynamically typed value. + * + * @param v the value to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packValue(Value v) throws IOException { @@ -626,6 +821,15 @@ public MessagePacker packValue(Value v) return this; } + /** + * Writes header of an Extension value. + *

+ * You will call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. + * + * @param len number of bytes of a payload binary to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packExtensionTypeHeader(byte extType, int payloadLen) throws IOException { @@ -669,6 +873,15 @@ else if (payloadLen < (1 << 16)) { return this; } + /** + * Writes header of a Binary value. + *

+ * You will call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. + * + * @param len number of bytes of a binary to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packBinaryHeader(int len) throws IOException { @@ -684,6 +897,18 @@ else if (len < (1 << 16)) { return this; } + /** + * Writes header of a String value. + *

+ * Length must be number of bytes of a string in UTF-8 encoding. + *

+ * You will call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body of the + * UTF-8 encoded string. + * + * @param len number of bytes of a UTF-8 string to be written + * @return this + * @throws IOException when underlaying output throws IOException + */ public MessagePacker packRawStringHeader(int len) throws IOException { @@ -703,12 +928,13 @@ else if (len < (1 << 16)) { } /** - * Writes buffer to the output. - * This method is used with packRawStringHeader or packBinaryHeader. + * Writes a byte array to the output. + *

+ * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. * * @param src the data to add * @return this - * @throws IOException + * @throws IOException when underlaying output throws IOException */ public MessagePacker writePayload(byte[] src) throws IOException @@ -717,14 +943,15 @@ public MessagePacker writePayload(byte[] src) } /** - * Writes buffer to the output. - * This method is used with packRawStringHeader or packBinaryHeader. + * Writes a byte array to the output. + *

+ * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. * * @param src the data to add * @param off the start offset in the data * @param len the number of bytes to add * @return this - * @throws IOException + * @throws IOException when underlaying output throws IOException */ public MessagePacker writePayload(byte[] src, int off, int len) throws IOException @@ -743,13 +970,15 @@ public MessagePacker writePayload(byte[] src, int off, int len) } /** - * Writes buffer to the output. - * Unlike writePayload method, addPayload method doesn't copy the source data. It means that the caller - * must not modify the data after calling this method. + * Writes a byte array to the output. + *

+ * Unlike {@link #writePayload} method, this method doesn't copy the byte array even when given byte array + * is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is faster than + * {@link writePayload} method but caller must not modify the byte array after calling this method. * * @param src the data to add * @return this - * @throws IOException + * @throws IOException when underlaying output throws IOException */ public MessagePacker addPayload(byte[] src) throws IOException @@ -758,15 +987,17 @@ public MessagePacker addPayload(byte[] src) } /** - * Writes buffer to the output. - * Unlike writePayload method, addPayload method doesn't copy the source data. It means that the caller - * must not modify the data after calling this method. + * Writes a byte array to the output. + *

+ * Unlike {@link #writePayload} method, this method doesn't copy the byte array even when given byte array + * is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is faster than + * {@link writePayload} method but caller must not modify the byte array after calling this method. * * @param src the data to add * @param off the start offset in the data * @param len the number of bytes to add * @return this - * @throws IOException + * @throws IOException when underlaying output throws IOException */ public MessagePacker addPayload(byte[] src, int off, int len) throws IOException diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 0696cd54c..0b9c575bf 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -40,31 +40,112 @@ import static org.msgpack.core.Preconditions.checkNotNull; /** - * MessageUnpacker lets an application read message-packed values from a data stream. - * The application needs to call {@link #getNextFormat()} followed by an appropriate unpackXXX method according to the the returned format type. - *

- *

- * 
+ * MessagePack deserializer that converts binary into objects.
+ * You can use factory methods of {@link MessagePack} class or {@link MessagePack.UnpackerConfig} class to create
+ * an instance.
+ * To read values as statically-typed Java objects, there are two typical use cases.
+ * 

+ * One use case is to read objects as {@link Value} using {@link #unpackValue} method. A {@link Value} object + * contains type of the deserialized value as well as the value itself so that you can inspect type of the + * deserialized values later. You can repeat {@link #unpackValue} until {@link hasNext()} method returns false so + * that you can deserialize sequence of MessagePack values. + *

+ * The other use case is to use {@link #getNextFormat()} and {@link MessageFormat#getValueType()} methods followed + * by unpackXxx methods corresponding to returned type. Following code snipet is a typical application code: + *


  *     MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(...);
  *     while(unpacker.hasNext()) {
- *         MessageFormat f = unpacker.getNextFormat();
- *         switch(f) {
- *             case MessageFormat.POSFIXINT:
- *             case MessageFormat.INT8:
- *             case MessageFormat.UINT8: {
- *                int v = unpacker.unpackInt();
- *                break;
+ *         MessageFormat format = unpacker.getNextFormat();
+ *         ValueType type = format.getValueType();
+ *         int length;
+ *         ExtensionTypeHeader extension;
+ *         switch(type) {
+ *             case NIL:
+ *                 unpacker.unpackNil();
+ *                 break;
+ *             case BOOLEAN:
+ *                 unpacker.unpackBoolean();
+ *                 break;
+ *             case INTEGER:
+ *                 switch (format) {
+ *                 case UINT64:
+ *                     unpacker.unpackBigInteger();
+ *                     break;
+ *                 case INT64:
+ *                 case UINT32:
+ *                     unpacker.unpackLong();
+ *                     break;
+ *                 default:
+ *                     unpacker.unpackInt();
+ *                     break;
+ *                 }
+ *                 break;
+ *             case FLOAT:
+ *                 unpacker.unpackDouble();
+ *                 break;
+ *             case STRING:
+ *                 unpacker.unpackString();
+ *                 break;
+ *             case BINARY:
+ *                 length = unpacker.unpackBinaryHeader();
+ *                 unpacker.readPayload(new byte[length]);
+ *                 break;
+ *             case ARRAY:
+ *                 length = unpacker.unpackArrayHeader();
+ *                 for (int i = 0; i < length; i++) {
+ *                     readRecursively(unpack);
+ *                 }
+ *                 break;
+ *             case MAP:
+ *                 length = unpacker.unpackMapHeader();
+ *                 for (int i = 0; i < length; i++) {
+ *                     readRecursively(unpack);  // key
+ *                     readRecursively(unpack);  // value
+ *                 }
+ *                 break;
+ *             case EXTENSION:
+ *                 extension = unpacker.unpackExtensionTypeHeader();
+ *                 unpacker.readPayload(new byte[extension.getLength()]);
+ *                 break;
  *             }
- *             case MessageFormat.STRING: {
- *                String v = unpacker.unpackString();
- *                break;
- *             }
- *             // ...
- *       }
+ *         }
  *     }
  *
- * 
- * 
+ *

+ * Following methods correspond to the MessagePack types: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
MessagePack typeUnpacker methodJava type
Nil{@link #unpackNil()}null
Boolean{@link #unpackBoolean()}boolean
Integer{@link #unpackByte()}byte
Integer{@link #unpackShort()}short
Integer{@link #unpackInt()}int
Integer{@link #unpackLong()}long
Integer{@link #unpackBigInteger()}BigInteger
Float{@link #unpackFloat()}float
Float{@link #unpackDouble()}double
Binary{@link #unpackBinaryHeader()}byte array
String{@link #unpackRawStringHeader()}String
String{@link #unpackString()}String
Array{@link #unpackArrayHeader()}Array
Map{@link #unpackMapHeader()}Map
Extension{@link #unpackExtensionTypeHeader()}{@link ExtensionTypeHeader}
+ * + *

+ * To read a byte array, first you call {@link #unpackBinaryHeader} method to get length of the byte array. Then, + * you call {@link #readPayload(int)} or {@link #readPayloadAsReference(int)} method to read the the contents. + * + *

+ * To read an Array type, first you call {@link #unpackArrayHeader()} method to get number of elements. Then, + * you call unpacker methods for each element. You don't have to call anything at the end of iteration. + * + *

+ * To read a Map, first you call {@link #unpackMapHeader(int)} method to get number of pairs of the map. Then, + * for each pair, you call unpacker methods for key first, and then value. You will call unpacker methods twice + * as many time as the returned count. You don't have to call anything at the end of iteration. + * */ public class MessageUnpacker implements Closeable @@ -139,10 +220,18 @@ protected MessageUnpacker(MessageBufferInput in, MessagePack.UnpackerConfig conf } /** - * Reset input. This method doesn't close the old resource. + * Replaces underlaying input. + *

+ * This method clears internal buffer, swaps the underlaying input with the new given input, then returns + * the old input. * - * @param in new input - * @return the old resource + *

+ * This method doesn't close the old input. + * + * @param out new input + * @return the old input + * @throws IOException never happens unless a subclass overrides this method + * @throws NullPointerException the given input is null */ public MessageBufferInput reset(MessageBufferInput in) throws IOException @@ -160,6 +249,15 @@ public MessageBufferInput reset(MessageBufferInput in) return old; } + /** + * Returns total number of read bytes. + *

+ * This method returns total of amount of data consumed from the underlaying input minus size of data + * remained still unused in the current internal buffer. + * + *

+ * Calling {@link #reset(MessageBufferInput)} resets this number to 0. + */ public long getTotalReadBytes() { return totalReadBytes + position; @@ -274,13 +372,18 @@ private boolean ensureBuffer() } /** - * Returns the next MessageFormat type. This method should be called after {@link #hasNext()} returns true. - * If {@link #hasNext()} returns false, calling this method throws {@link MessageInsufficientBufferException}. - *

- * This method does not proceed the internal cursor. + * Returns format of the next value. + * + *

+ * Note that this method doesn't consume data from the internal buffer unlike the other unpack methods. + * Calling this method twice will return the same value. + * + *

+ * To not throw {@link MessageInsufficientBufferException}, this method should be called only when + * {@link #hasNext()} returns true. * * @return the next MessageFormat - * @throws IOException when failed to read the input data. + * @throws IOException when underlaying input throws IOException * @throws MessageInsufficientBufferException when the end of file reached, i.e. {@link #hasNext()} == false. */ public MessageFormat getNextFormat() @@ -612,6 +715,13 @@ public Variable unpackValue(Variable var) } } + /** + * Reads a Nil byte. + * + * @return the read value + * @throws MessageTypeException when value is not MessagePack Nil type + * @throws IOException when underlaying input throws IOException + */ public void unpackNil() throws IOException { @@ -622,6 +732,13 @@ public void unpackNil() throw unexpected("Nil", b); } + /** + * Reads true or false. + * + * @return the read value + * @throws MessageTypeException when value is not MessagePack Boolean type + * @throws IOException when underlaying input throws IOException + */ public boolean unpackBoolean() throws IOException { @@ -635,6 +752,16 @@ else if (b == Code.TRUE) { throw unexpected("boolean", b); } + /** + * Reads a byte. + * + * This method throws {@link MessageIntegerOverflowException} if the value doesn't fit in the range of byte. This may happen when {@link #getNextFormat()} returns UINT8, INT16, or larger integer formats. + * + * @return the read value + * @throws MessageIntegerOverflowException when value doesn't fit in the range of byte + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlaying input throws IOException + */ public byte unpackByte() throws IOException { @@ -692,6 +819,16 @@ public byte unpackByte() throw unexpected("Integer", b); } + /** + * Reads a short. + * + * This method throws {@link MessageIntegerOverflowException} if the value doesn't fit in the range of short. This may happen when {@link #getNextFormat()} returns UINT16, INT32, or larger integer formats. + * + * @return the read value + * @throws MessageIntegerOverflowException when value doesn't fit in the range of short + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlaying input throws IOException + */ public short unpackShort() throws IOException { @@ -743,6 +880,16 @@ public short unpackShort() throw unexpected("Integer", b); } + /** + * Reads a int. + * + * This method throws {@link MessageIntegerOverflowException} if the value doesn't fit in the range of int. This may happen when {@link #getNextFormat()} returns UINT32, INT64, or larger integer formats. + * + * @return the read value + * @throws MessageIntegerOverflowException when value doesn't fit in the range of int + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlaying input throws IOException + */ public int unpackInt() throws IOException { @@ -788,6 +935,16 @@ public int unpackInt() throw unexpected("Integer", b); } + /** + * Reads a long. + * + * This method throws {@link MessageIntegerOverflowException} if the value doesn't fit in the range of long. This may happen when {@link #getNextFormat()} returns UINT64. + * + * @return the read value + * @throws MessageIntegerOverflowException when value doesn't fit in the range of long + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlaying input throws IOException + */ public long unpackLong() throws IOException { @@ -832,6 +989,13 @@ public long unpackLong() throw unexpected("Integer", b); } + /** + * Reads a BigInteger. + * + * @return the read value + * @throws MessageTypeException when value is not MessagePack Integer type + * @throws IOException when underlaying input throws IOException + */ public BigInteger unpackBigInteger() throws IOException { @@ -879,6 +1043,15 @@ public BigInteger unpackBigInteger() throw unexpected("Integer", b); } + /** + * Reads a float. + * + * This method rounds value to the range of float when precision of the read value is larger than the range of float. This may happen when {@link #getNextFormat()} returns FLOAT64. + * + * @return the read value + * @throws MessageTypeException when value is not MessagePack Float type + * @throws IOException when underlaying input throws IOException + */ public float unpackFloat() throws IOException { @@ -894,6 +1067,13 @@ public float unpackFloat() throw unexpected("Float", b); } + /** + * Reads a double. + * + * @return the read value + * @throws MessageTypeException when value is not MessagePack Float type + * @throws IOException when underlaying input throws IOException + */ public double unpackDouble() throws IOException { @@ -1053,6 +1233,18 @@ private String decodeStringFastPath(int length) } } + /** + * Reads header of an array. + * + *

+ * This method returns number of elements to be read. After this method call, you call unpacker methods for + * each element. You don't have to call anything at the end of iteration. + * + * @return the size of the array to be read + * @throws MessageTypeException when value is not MessagePack Array type + * @throws MessageSizeException when size of the array is larger than 2^31 - 1 + * @throws IOException when underlaying input throws IOException + */ public int unpackArrayHeader() throws IOException { @@ -1073,6 +1265,19 @@ public int unpackArrayHeader() throw unexpected("Array", b); } + /** + * Reads header of a map. + * + *

+ * This method returns number of pairs to be read. After this method call, for each pair, you call unpacker + * methods for key first, and then value. You will call unpacker methods twice as many time as the returned + * count. You don't have to call anything at the end of iteration. + * + * @return the size of the map to be read + * @throws MessageTypeException when value is not MessagePack Map type + * @throws MessageSizeException when size of the map is larger than 2^31 - 1 + * @throws IOException when underlaying input throws IOException + */ public int unpackMapHeader() throws IOException { @@ -1198,6 +1403,22 @@ public int unpackRawStringHeader() throw unexpected("String", b); } + /** + * Reads header of a binary. + * + *

+ * This method returns number of bytes to be read. After this method call, you call a readPayload method such as + * {@link #readPayload(int)} with the returned count. + * + *

+ * You can divide readPayload method into multiple calls. In this case, you must repeat readPayload methods + * until total amount of bytes becomes equal to the returned count. + * + * @return the size of the map to be read + * @throws MessageTypeException when value is not MessagePack Map type + * @throws MessageSizeException when size of the map is larger than 2^31 - 1 + * @throws IOException when underlaying input throws IOException + */ public int unpackBinaryHeader() throws IOException { @@ -1243,6 +1464,16 @@ private void skipPayload(int numBytes) } } + /** + * Reads payload bytes of binary, extension, or raw string types. + * + *

+ * This consumes bytes, copies them to the specified buffer, and moves forward position of the byte buffer + * until ByteBuffer.remaining() returns 0. + * + * @param dst the byte buffer into which the data is read + * @throws IOException when underlaying input throws IOException + */ public void readPayload(ByteBuffer dst) throws IOException { @@ -1261,12 +1492,35 @@ public void readPayload(ByteBuffer dst) } } + /** + * Reads payload bytes of binary, extension, or raw string types. + * + * This consumes specified amount of bytes into the specified byte array. + * + *

+ * This method is equivalent to readPayload(dst, 0, dst.length). + * + * @param dst the byte array into which the data is read + * @throws IOException when underlaying input throws IOException + */ public void readPayload(byte[] dst) throws IOException { readPayload(dst, 0, dst.length); } + /** + * Reads payload bytes of binary, extension, or raw string types. + * + * This method allocates a new byte array and consumes specified amount of bytes into the byte array. + * + *

+ * This method is equivalent to readPayload(new byte[length]). + * + * @param length number of bytes to be read + * @return the new byte array + * @throws IOException when underlaying input throws IOException + */ public byte[] readPayload(int length) throws IOException { @@ -1276,12 +1530,14 @@ public byte[] readPayload(int length) } /** - * Read up to len bytes of data into the destination array + * Reads payload bytes of binary, extension, or raw string types. * - * @param dst the buffer into which the data is read + * This consumes specified amount of bytes into the specified byte array. + * + * @param dst the byte array into which the data is read * @param off the offset in the dst array * @param len the number of bytes to read - * @throws IOException + * @throws IOException when underlaying input throws IOException */ public void readPayload(byte[] dst, int off, int len) throws IOException @@ -1290,6 +1546,17 @@ public void readPayload(byte[] dst, int off, int len) readPayload(ByteBuffer.wrap(dst, off, len)); } + /** + * Reads payload bytes of binary, extension, or raw string types as a reference to internal buffer. + * + *

+ * This consumes specified amount of bytes and returns its reference or copy. This method tries to + * return reference as much as possible because it is faster. However, it may copy data to a newly + * allocated buffer if reference is not applicable. + * + * @param length number of bytes to be read + * @throws IOException when underlaying input throws IOException + */ public MessageBuffer readPayloadAsReference(int length) throws IOException { @@ -1328,6 +1595,11 @@ private int readNextLength32() return u32; } + /** + * Closes underlaying input. + * + * @throws IOException + */ @Override public void close() throws IOException From e5999106bb2c86caedad1c5120a949208163ec96 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Mon, 24 Oct 2016 13:37:04 -0700 Subject: [PATCH 028/417] Adding JavaDoc - part 2 --- .../org/msgpack/core/MessageBufferPacker.java | 33 ++++++++- .../java/org/msgpack/core/MessagePack.java | 6 +- .../java/org/msgpack/core/MessagePacker.java | 6 +- .../org/msgpack/core/MessageUnpacker.java | 4 +- .../core/buffer/ArrayBufferOutput.java | 37 +++++++++- .../msgpack/core/buffer/MessageBuffer.java | 23 ++++--- .../core/buffer/MessageBufferInput.java | 27 ++++++-- .../core/buffer/MessageBufferOutput.java | 34 +++++++--- .../java/org/msgpack/value/ArrayValue.java | 2 +- .../java/org/msgpack/value/BinaryValue.java | 2 +- .../java/org/msgpack/value/BooleanValue.java | 2 +- .../org/msgpack/value/ExtensionValue.java | 2 +- .../java/org/msgpack/value/FloatValue.java | 2 +- .../msgpack/value/ImmutableArrayValue.java | 5 ++ .../msgpack/value/ImmutableBinaryValue.java | 7 ++ .../msgpack/value/ImmutableBooleanValue.java | 5 ++ .../value/ImmutableExtensionValue.java | 5 ++ .../msgpack/value/ImmutableFloatValue.java | 7 ++ .../msgpack/value/ImmutableIntegerValue.java | 5 ++ .../org/msgpack/value/ImmutableMapValue.java | 5 ++ .../org/msgpack/value/ImmutableNilValue.java | 3 + .../msgpack/value/ImmutableNumberValue.java | 6 ++ .../org/msgpack/value/ImmutableRawValue.java | 8 +++ .../msgpack/value/ImmutableStringValue.java | 6 ++ .../org/msgpack/value/ImmutableValue.java | 3 + .../java/org/msgpack/value/IntegerValue.java | 2 +- .../main/java/org/msgpack/value/MapValue.java | 2 +- .../main/java/org/msgpack/value/NilValue.java | 2 +- .../java/org/msgpack/value/NumberValue.java | 2 +- .../main/java/org/msgpack/value/RawValue.java | 2 +- .../java/org/msgpack/value/StringValue.java | 2 +- .../main/java/org/msgpack/value/Value.java | 67 ++++++++++++++++--- .../java/org/msgpack/value/ValueType.java | 8 ++- 33 files changed, 279 insertions(+), 53 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java index 7483010b2..3f6b732a1 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java @@ -23,7 +23,11 @@ import java.util.List; /** - * MessagePacker that is useful to produce byte array output + * MessagePacker that is useful to produce byte array output. + *

+ * This class allocates a new buffer instead of resizing the buffer when data doesn't fit in the initial capacity. + * This is faster than ByteArrayOutputStream especially when size of written bytes is large because resizing a buffer + * usually needs to copy contents of the buffer. */ public class MessageBufferPacker extends MessagePacker @@ -52,11 +56,22 @@ private ArrayBufferOutput getArrayBufferOut() return (ArrayBufferOutput) out; } + /** + * Clears the written data. + */ public void clear() { getArrayBufferOut().clear(); } + /** + * Gets copy of the written data as a byte array. + *

+ * If your application needs better performance and smaller memory consumption, you may prefer + * {@link #toMessageBuffer()} or {@link #toBufferList()} to avoid copying. + * + * @return the byte array + */ public byte[] toByteArray() { try { @@ -69,6 +84,14 @@ public byte[] toByteArray() return getArrayBufferOut().toByteArray(); } + /** + * Gets the written data as a MessageBuffer. + *

+ * Unlike {@link #toByteArray()}, this method omits copy of the contents if size of the written data is smaller + * than a single buffer capacity. + * + * @return the MessageBuffer instance + */ public MessageBuffer toMessageBuffer() { try { @@ -81,6 +104,14 @@ public MessageBuffer toMessageBuffer() return getArrayBufferOut().toMessageBuffer(); } + /** + * Returns the written data as a list of MessageBuffer. + *

+ * Unlike {@link #toByteArray()} or {@link #toMessageBuffer()}, this is the fastest method that doesn't + * copy contents in any cases. + * + * @return the list of MessageBuffer instances + */ public List toBufferList() { try { diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 2c84d2328..ed8b1e405 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -35,7 +35,7 @@ /** * Convenience class to build packer and unpacker classes. * - * You may choose factory method as following + * You can select an appropriate factory method as following. * *

* Deserializing objects from binary: @@ -70,12 +70,12 @@ public class MessagePack public static final Charset UTF8 = Charset.forName("UTF-8"); /** - * Configuration of a {@link MessagePacker} created by {@link #newDefaultPacker(MessageBufferOutput)} and {@link #newDefaultBufferPacker()} methods. + * Configuration of a {@link MessagePacker} used by {@link #newDefaultPacker(MessageBufferOutput)} and {@link #newDefaultBufferPacker()} methods. */ public static final PackerConfig DEFAULT_PACKER_CONFIG = new PackerConfig(); /** - * Configuration of a {@link MessageUnpacker} created by {@link #newDefaultUnpacker(MessageBufferInput)} methods. + * Configuration of a {@link MessageUnpacker} used by {@link #newDefaultUnpacker(MessageBufferInput)} methods. */ public static final UnpackerConfig DEFAULT_UNPACKER_CONFIG = new UnpackerConfig(); diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 423886fd8..0c61b4bd1 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -72,7 +72,7 @@ * an instance. *

* This class provides following primitive methods to write MessagePack values. These primitive methods write - * short bytes (1 to 7 bytes) to the internal buffer at once. There also some complex methods for convenience. + * short bytes (1 to 7 bytes) to the internal buffer at once. There are also some complex methods for convenience. *

* Primitive methods: * @@ -110,13 +110,13 @@ * *

* To write a List, Collection or array, first you call {@link #packArrayHeader(int)} method with the number of - * elements. Then, you call packer methods for each element. You don't have to call anything at the end of + * elements. Then, you call packer methods for each element. * iteration. * *

* To write a Map, first you call {@link #packMapHeader(int)} method with size of the map. Then, for each pair, * you call packer methods for key first, and then value. You will call packer methods twice as many time as the - * size of the map. You don't have to call anything at the end of iteration. + * size of the map. * *

* Note that packXxxHeader methods don't validate number of elements. You must call packer methods for correct diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 0b9c575bf..64d26a29f 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -139,12 +139,12 @@ * *

* To read an Array type, first you call {@link #unpackArrayHeader()} method to get number of elements. Then, - * you call unpacker methods for each element. You don't have to call anything at the end of iteration. + * you call unpacker methods for each element. * *

* To read a Map, first you call {@link #unpackMapHeader(int)} method to get number of pairs of the map. Then, * for each pair, you call unpacker methods for key first, and then value. You will call unpacker methods twice - * as many time as the returned count. You don't have to call anything at the end of iteration. + * as many time as the returned count. * */ public class MessageUnpacker diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java index 186a579af..df952a61a 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java @@ -19,7 +19,11 @@ import java.util.ArrayList; /** - * MessageBufferOutput adapter that packs data into list of byte arrays. + * MessageBufferOutput adapter that writes data into a list of byte arrays. + *

+ * This class allocates a new buffer instead of resizing the buffer when data doesn't fit in the initial capacity. + * This is faster than ByteArrayOutputStream especially when size of written bytes is large because resizing a buffer + * usually needs to copy contents of the buffer. */ public class ArrayBufferOutput implements MessageBufferOutput @@ -39,6 +43,11 @@ public ArrayBufferOutput(int bufferSize) this.list = new ArrayList(); } + /** + * Gets size of the written data. + * + * @return number of bytes + */ public int getSize() { int size = 0; @@ -48,6 +57,14 @@ public int getSize() return size; } + /** + * Gets copy of the written data as a byte array. + *

+ * If your application needs better performance and smaller memory consumption, you may prefer + * {@link #toMessageBuffer()} or {@link #toBufferList()} to avoid copying. + * + * @return the byte array + */ public byte[] toByteArray() { byte[] data = new byte[getSize()]; @@ -59,6 +76,14 @@ public byte[] toByteArray() return data; } + /** + * Gets the written data as a MessageBuffer. + *

+ * Unlike {@link #toByteArray()}, this method omits copy of the contents if size of the written data is smaller + * than a single buffer capacity. + * + * @return the MessageBuffer instance + */ public MessageBuffer toMessageBuffer() { if (list.size() == 1) { @@ -72,13 +97,21 @@ else if (list.isEmpty()) { } } + /** + * Returns the written data as a list of MessageBuffer. + *

+ * Unlike {@link #toByteArray()} or {@link #toMessageBuffer()}, this is the fastest method that doesn't + * copy contents in any cases. + * + * @return the list of MessageBuffer instances + */ public List toBufferList() { return new ArrayList(list); } /** - * Clears the internal buffers + * Clears the written data. */ public void clear() { diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 50d472ae5..65cb6eba3 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -28,12 +28,20 @@ import static org.msgpack.core.Preconditions.checkNotNull; /** - * MessageBuffer class is an abstraction of memory for reading/writing message packed data. - * This MessageBuffers ensures short/int/float/long/double values are written in the big-endian order. - *

- * This class is optimized for fast memory access, so many methods are - * implemented without using any interface method that produces invokeinterface call in JVM. - * Compared to invokevirtual, invokeinterface is 30% slower in general because it needs to find a target function from the table. + * MessageBuffer class is an abstraction of memory with fast methods to serialize and deserialize primitive values + * to/from the memory. All MessageBuffer implementations ensure short/int/float/long/double values are written in + * big-endian order. + *

+ * Applications can allocate a new buffer using {@link #allocate(int)} method, or wrap an byte array or ByteBuffer + * using {@link wrap(byte[], int, int)} methods. {@link wrap(ByteBuffer)} method supports both direct buffers and + * array-backed buffers. + *

+ * MessageBuffer class itself is optimized for little-endian CPU archtectures so that JVM (HotSpot) can take advantage + * of the fastest JIT format which skips TypeProfile checking. To ensure this performance, applications must not load + * unnecessary classes such as MessagePackBE. On big-endian CPU archtectures, implementation uses subclass that + * includes TypeProfile overhead but still faster than ByteBuffer. On JVMs older than Java 7 and JVMs without Unsafe + * API (such as Android), implementation falls back to a universal implementation that uses standard ByteBuffer class + * internally. */ public class MessageBuffer { @@ -69,8 +77,7 @@ public class MessageBuffer try { int major = Integer.parseInt(javaVersion.substring(0, dotPos)); int minor = Integer.parseInt(javaVersion.substring(dotPos + 1)); - isJavaAtLeast7 = major > 1 || (major == 1 && minor >= 7); - } + isJavaAtLeast7 = major > 1 || (major == 1 && minor >= 7); } catch (NumberFormatException e) { e.printStackTrace(System.err); } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java index 46eea243e..2b19b9d99 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java @@ -19,19 +19,38 @@ import java.io.IOException; /** - * Provides a sequence of MessageBuffers that contains message packed data. + * Provides a sequence of MessageBuffer instances. + * + * A MessageBufferInput implementation has control of lifecycle of the memory so that it can reuse previously + * allocated memory, use memory pools, or use memory-mapped files. */ public interface MessageBufferInput extends Closeable { /** - * Get a next buffer to read. + * Returns a next buffer to read. *

- * When this method is called, the formally allocated buffer can be safely discarded. + * This method should return a MessageBuffer instance that has data filled in. When this method is called twice, + * the previously returned buffer is no longer used. Thus implementation of this method can safely discard it. + * This is useful when it uses a memory pool. * * @return the next MessageBuffer, or return null if no more buffer is available. - * @throws IOException when error occurred when reading the data + * @throws IOException when IO error occurred when reading the data */ MessageBuffer next() throws IOException; + + /** + * Closes the input. + *

+ * When this method is called, the buffer previously returned from {@link next()} method is no longer used. + * Thus implementation of this method can safely discard it. + *

+ * If the input is already closed then invoking this method has no effect. + * + * @throws IOException when IO error occurred when closing the data source + */ + @Override + void close() + throws IOException; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java index 024414bae..9ae1b13dd 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java @@ -20,29 +20,40 @@ import java.io.Flushable; /** - * Provides a buffered output stream for packing objects + * Provides a buffered output stream that writes sequence of MessageBuffer instances. + * + * A MessageBufferOutput implementation has total control of the buffer memory so that it can reuse buffer memory, + * use buffer pools, or use memory-mapped files. */ public interface MessageBufferOutput extends Closeable, Flushable { /** - * Allocates the next buffer for writing message packed data. - * If the previously allocated buffer is not flushed yet, this next method should discard - * it without writing it. + * Allocates the next buffer to write. + *

+ * This method should return a MessageBuffer instance that has at least specified size of capacity. + *

+ * When this method is called twice, the previously returned buffer is no longer used. This method may be called + * twice without call of {@link writeBuffer(MessageBuffer)} in between. In this case, the buffer should be + * discarded without flushing it to the output. * * @param minimumSize the mimium required buffer size to allocate - * @return + * @return the MessageBuffer instance with at least minimumSize bytes of capacity * @throws IOException */ MessageBuffer next(int minimumSize) throws IOException; /** - * Flushes the previously allocated buffer. - * This method is not always called because next method also flushes previously allocated buffer. - * This method is called when write method is called or application wants to control the timing of flush. + * Writes the previously allocated buffer. + *

+ * This method should write the buffer previously returned from {@link next(int)} method until specified number of + * bytes. Once the buffer is written, the buffer is no longer used. + *

+ * This method is not always called for each {@link next(int)} call. In this case, the buffer should be discarded + * without flushing it to the output. * - * @param length the size of buffer to flush + * @param length the number of bytes to write * @throws IOException */ void writeBuffer(int length) @@ -63,7 +74,10 @@ void write(byte[] buffer, int offset, int length) /** * Writes an external payload data. - * This buffer is given - this MessageBufferOutput owns the buffer and may modify contents of the buffer. Contents of this buffer won't be modified by the caller. + *

+ * Unlike {@link #write(byte[], int, int)} method, the buffer is given - this MessageBufferOutput implementation + * gets ownership of the buffer and may modify contents of the buffer. Contents of this buffer won't be modified + * by the caller. * * @param buffer the data to add * @param offset the start offset in the data diff --git a/msgpack-core/src/main/java/org/msgpack/value/ArrayValue.java b/msgpack-core/src/main/java/org/msgpack/value/ArrayValue.java index 4d7a6e8c2..05d64d3d7 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ArrayValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ArrayValue.java @@ -19,7 +19,7 @@ import java.util.List; /** - * The interface {@code ArrayValue} represents MessagePack's Array type. + * Representation of MessagePack's Array type. * * MessagePack's Array type can represent sequence of values. */ diff --git a/msgpack-core/src/main/java/org/msgpack/value/BinaryValue.java b/msgpack-core/src/main/java/org/msgpack/value/BinaryValue.java index c66f7a67c..74a413316 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/BinaryValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/BinaryValue.java @@ -16,7 +16,7 @@ package org.msgpack.value; /** - * The interface {@code BinaryValue} represents MessagePack's Binary type. + * Representation of MessagePack's Binary type. * * MessagePack's Binary type can represent a byte array at most 264-1 bytes. * diff --git a/msgpack-core/src/main/java/org/msgpack/value/BooleanValue.java b/msgpack-core/src/main/java/org/msgpack/value/BooleanValue.java index 6ccf5c9ef..b0aa3b9d8 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/BooleanValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/BooleanValue.java @@ -16,7 +16,7 @@ package org.msgpack.value; /** - * The interface {@code BooleanValue} represents MessagePack's Boolean type. + * Representation MessagePack's Boolean type. * * MessagePack's Boolean type can represent {@code true} or {@code false}. */ diff --git a/msgpack-core/src/main/java/org/msgpack/value/ExtensionValue.java b/msgpack-core/src/main/java/org/msgpack/value/ExtensionValue.java index 5a076ecbc..51c50b9a8 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ExtensionValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ExtensionValue.java @@ -16,7 +16,7 @@ package org.msgpack.value; /** - * The interface {@code ExtensionValue} represents MessagePack's Extension type. + * Representation of MessagePack's Extension type. * * MessagePack's Extension type can represent represents a tuple of type information and a byte array where type information is an * integer whose meaning is defined by applications. diff --git a/msgpack-core/src/main/java/org/msgpack/value/FloatValue.java b/msgpack-core/src/main/java/org/msgpack/value/FloatValue.java index dbaf73a18..68fcf9fa5 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/FloatValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/FloatValue.java @@ -16,7 +16,7 @@ package org.msgpack.value; /** - * The interface {@code FloatValue} represents MessagePack's Float type. + * Representation of MessagePack's Float type. * * MessagePack's Float type can represent IEEE 754 double precision floating point numbers including NaN and infinity. This is same with Java's {@code double} type. * diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableArrayValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableArrayValue.java index 9301c2eb8..9aa0687fa 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableArrayValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableArrayValue.java @@ -18,6 +18,11 @@ import java.util.Iterator; import java.util.List; +/** + * Immutable representation of MessagePack's Array type. + * + * MessagePack's Array type can represent sequence of values. + */ public interface ImmutableArrayValue extends ArrayValue, ImmutableValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableBinaryValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableBinaryValue.java index 475241a57..9aefd7bc8 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableBinaryValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableBinaryValue.java @@ -15,6 +15,13 @@ // package org.msgpack.value; +/** + * Immutable representation of MessagePack's Binary type. + * + * MessagePack's Binary type can represent a byte array at most 264-1 bytes. + * + * @see org.msgpack.value.ImmutableRawValue + */ public interface ImmutableBinaryValue extends BinaryValue, ImmutableRawValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableBooleanValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableBooleanValue.java index dd2afad43..dcf221171 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableBooleanValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableBooleanValue.java @@ -15,6 +15,11 @@ // package org.msgpack.value; +/** + * Immutable representation of MessagePack's Boolean type. + * + * MessagePack's Boolean type can represent {@code true} or {@code false}. + */ public interface ImmutableBooleanValue extends BooleanValue, ImmutableValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableExtensionValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableExtensionValue.java index 5e984db05..8c9b73753 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableExtensionValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableExtensionValue.java @@ -15,6 +15,11 @@ // package org.msgpack.value; +/** + * Immutable representation of MessagePack's Extension type. + * + * @see org.msgpack.value.ExtensionValue + */ public interface ImmutableExtensionValue extends ExtensionValue, ImmutableValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableFloatValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableFloatValue.java index 7105483d1..9a30f9b9f 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableFloatValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableFloatValue.java @@ -15,6 +15,13 @@ // package org.msgpack.value; +/** + * Immutable representation of MessagePack's Float type. + * + * MessagePack's Float type can represent IEEE 754 double precision floating point numbers including NaN and infinity. This is same with Java's {@code double} type. + * + * @see org.msgpack.value.ImmutableNumberValue + */ public interface ImmutableFloatValue extends FloatValue, ImmutableNumberValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableIntegerValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableIntegerValue.java index 3482583ff..ec246748e 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableIntegerValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableIntegerValue.java @@ -15,6 +15,11 @@ // package org.msgpack.value; +/** + * Immutable representation of MessagePack's Integer type. + * + * MessagePack's Integer type can represent from -263 to 264-1. + */ public interface ImmutableIntegerValue extends IntegerValue, ImmutableNumberValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableMapValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableMapValue.java index cc3122f03..0c27d5540 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableMapValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableMapValue.java @@ -15,6 +15,11 @@ // package org.msgpack.value; +/** + * Immutable representation of MessagePack's Map type. + * + * MessagePack's Map type can represent sequence of key-value pairs. + */ public interface ImmutableMapValue extends MapValue, ImmutableValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableNilValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableNilValue.java index 8a7857287..36135fcef 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableNilValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableNilValue.java @@ -15,6 +15,9 @@ // package org.msgpack.value; +/** + * Immutable representation of MessagePack's Nil type. + */ public interface ImmutableNilValue extends NilValue, ImmutableValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableNumberValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableNumberValue.java index 42afcf304..0ecd5bb36 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableNumberValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableNumberValue.java @@ -15,6 +15,12 @@ // package org.msgpack.value; +/** + * Immutable base interface of {@link ImmutableIntegerValue} and {@link ImmutableFloatValue} interfaces. To extract primitive type values, call toXXX methods, which may lose some information by rounding or truncation. + * + * @see org.msgpack.value.immutableIntegerValue + * @see org.msgpack.value.immutableFloatValue + */ public interface ImmutableNumberValue extends NumberValue, ImmutableValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableRawValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableRawValue.java index 36698dbeb..d3f2eaab6 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableRawValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableRawValue.java @@ -15,6 +15,14 @@ // package org.msgpack.value; +/** + * Immutable base interface of {@link ImmutableStringValue} and {@link ImmutableBinaryValue} interfaces. + *

+ * MessagePack's Raw type can represent a byte array at most 264-1 bytes. + * + * @see org.msgpack.value.ImmutableStringValue + * @see org.msgpack.value.ImmutableBinaryValue + */ public interface ImmutableRawValue extends RawValue, ImmutableValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableStringValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableStringValue.java index 6e3f95360..2c198ae11 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableStringValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableStringValue.java @@ -15,6 +15,12 @@ // package org.msgpack.value; +/** + * Immutable representation of MessagePack's String type. + * + * @see org.msgpack.value.StringValue + * @see org.msgpack.value.ImmutableRawValue + */ public interface ImmutableStringValue extends StringValue, ImmutableRawValue { diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableValue.java index 6a5740029..88798a13d 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableValue.java @@ -15,6 +15,9 @@ // package org.msgpack.value; +/** + * Immutable declaration of {@link Value} interface. + */ public interface ImmutableValue extends Value { diff --git a/msgpack-core/src/main/java/org/msgpack/value/IntegerValue.java b/msgpack-core/src/main/java/org/msgpack/value/IntegerValue.java index 8480751c4..2776eb78c 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/IntegerValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/IntegerValue.java @@ -20,7 +20,7 @@ import java.math.BigInteger; /** - * The interface {@code IntegerValue} represents MessagePack's Integer type. + * Representation of MessagePack's Integer type. * * MessagePack's Integer type can represent from -263 to 264-1. */ diff --git a/msgpack-core/src/main/java/org/msgpack/value/MapValue.java b/msgpack-core/src/main/java/org/msgpack/value/MapValue.java index fa7f55c8d..a68982a47 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/MapValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/MapValue.java @@ -20,7 +20,7 @@ import java.util.Set; /** - * The interface {@code ArrayValue} represents MessagePack's Map type. + * Representation of MessagePack's Map type. * * MessagePack's Map type can represent sequence of key-value pairs. */ diff --git a/msgpack-core/src/main/java/org/msgpack/value/NilValue.java b/msgpack-core/src/main/java/org/msgpack/value/NilValue.java index 8f5835001..9307ae6f0 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/NilValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/NilValue.java @@ -16,7 +16,7 @@ package org.msgpack.value; /** - * The interface {@code NilValue} represents MessagePack's Nil type. + * Representation of MessagePack's Nil type. */ public interface NilValue extends Value diff --git a/msgpack-core/src/main/java/org/msgpack/value/NumberValue.java b/msgpack-core/src/main/java/org/msgpack/value/NumberValue.java index 3e5bd75e0..828e6353c 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/NumberValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/NumberValue.java @@ -18,7 +18,7 @@ import java.math.BigInteger; /** - * The base interface {@code NumberValue} of {@code IntegerValue} and {@code FloatValue}. To extract primitive type values, call toXXX methods, which may lose some information by rounding or truncation. + * Base interface of {@link IntegerValue} and {@link FloatValue} interfaces. To extract primitive type values, call toXXX methods, which may lose some information by rounding or truncation. * * @see org.msgpack.value.IntegerValue * @see org.msgpack.value.FloatValue diff --git a/msgpack-core/src/main/java/org/msgpack/value/RawValue.java b/msgpack-core/src/main/java/org/msgpack/value/RawValue.java index 8857b5340..9ce62463f 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/RawValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/RawValue.java @@ -18,7 +18,7 @@ import java.nio.ByteBuffer; /** - * The interface {@code RawValue} represents MessagePack's Raw type, which means Binary or String type. + * Base interface of {@link StringValue} and {@link BinaryValue} interfaces. *

* MessagePack's Raw type can represent a byte array at most 264-1 bytes. * diff --git a/msgpack-core/src/main/java/org/msgpack/value/StringValue.java b/msgpack-core/src/main/java/org/msgpack/value/StringValue.java index 0c812d58d..de2ec1eae 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/StringValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/StringValue.java @@ -16,7 +16,7 @@ package org.msgpack.value; /** - * The interface {@code StringValue} represents MessagePack's String type. + * Representation of MessagePack's String type. * * MessagePack's String type can represent a UTF-8 string at most 264-1 bytes. * diff --git a/msgpack-core/src/main/java/org/msgpack/value/Value.java b/msgpack-core/src/main/java/org/msgpack/value/Value.java index 2fae838b4..546dfbbf4 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/Value.java +++ b/msgpack-core/src/main/java/org/msgpack/value/Value.java @@ -20,11 +20,60 @@ import java.io.IOException; /** - * Value is an implementation of MessagePack type system. To retrieve values from a Value object, - * You need to check its {@link ValueType} then call an appropriate asXXXValue method. + * Value stores a value and its type in MessagePack type system. * + *

Type conversion

+ *

+ * You can check type first using isXxx() methods or {@link #getValueType()} method, then convert the value to a + * subtype using asXxx() methods. You can also call asXxx() methods directly and catch + * {@link org.msgpack.core.MessageTypeCastException}. * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
MessagePack typeCheck methodConvert methodValue type
Nil{@link #isNilValue()}{@link #asNumberValue()}{@link NilValue}
Boolean{@link #isBooleanValue()}{@link #asBooleanValue()}{@link BooleanValue}
Integer or Float{@link #isNumberValue()}{@link #asNumberValue()}{@link NumberValue}
Integer{@link #isIntegerValue()}{@link #asIntegerValue()}{@link IntegerValue}
Float{@link #isFloatValue()}{@link #asFloatValue()}{@link FloatValue}
String or Binary{@link #isRawValue()}{@link #asRawValue()}{@link RawValue}
String{@link #isStringValue()}{@link #asStringValue()}{@link StringValue}
Binary{@link #isBinaryValue()}{@link #asBinaryValue()}{@link BinaryValue}
Array{@link #isArrayValue()}{@link #asArrayValue()}{@link ArrayValue}
Map{@link #isMapValue()}{@link #asMapValue()}{@link MapValue}
Extension{@link #isExtensionValue()}{@link #asExtensionValue()}{@link ExtensionValue}
* + *

Immutable interface

+ *

+ * Value interface is the base interface of all Value interfaces. Immutable subtypes are useful so that you can + * declare that a (final) field or elements of a container object are immutable. Method arguments should be a + * regular Value interface generally. + *

+ * You can use {@link #immutableValue()} method to get immutable subtypes. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
MessagePack typeSubtype methodImmutable value type
any types{@link Value}.{@link Value#immutableValue()}{@link ImmutableValue}
Nil{@link NilValue}.{@link NilValue#immutableValue()}{@link ImmutableNilValue}
Boolean{@link BooleanValue}.{@link BooleanValue#immutableValue()}{@link ImmutableBooleanValue}
Integer{@link IntegerValue}.{@link IntegerValue#immutableValue()}{@link ImmutableIntegerValue}
Float{@link FloatValue}.{@link FloatValue#immutableValue()}{@link ImmutableFloatValue}
Integer or Float{@link NumberValue}.{@link NumberValue#immutableValue()}{@link ImmutableNumberValue}
String or Binary{@link RawValue}.{@link RawValue#immutableValue()}{@link ImmutableRawValue}
String{@link StringValue}.{@link StringValue#immutableValue()}{@link ImmutableStringValue}
Binary{@link BinaryValue}.{@link BinaryValue#immutableValue()}{@link ImmutableBinaryValue}
Array{@link ArrayValue}.{@link ArrayValue#immutableValue()}{@link ImmutableArrayValue}
Map{@link MapValue}.{@link MapValue#immutableValue()}{@link ImmutableMapValue}
Extension{@link ExtensionValue}.{@link ExtensionValue#immutableValue()}{@link ImmutableExtensionValue}
+ * + *

Converting to JSON

+ *

+ * {@link #toJson()} method returns JSON representation of a Value. See its documents for details. + *

+ * toString() also returns a string representation of a Value that is similar to JSON. However, unlike toJson() method, + * toString() may return a special format that is not be compatible with JSON when JSON doesn't support the type such + * as ExtensionValue. */ public interface Value { @@ -249,14 +298,16 @@ void writeTo(MessagePacker pk) /** * Returns json representation of this Value. - * + *

* Following behavior is not configurable at this release and they might be changed at future releases: * - * * if a key of MapValue is not string, the key is converted to a string using toString method. - * * NaN and Infinity of DoubleValue are converted to null. - * * ExtensionValue is converted to a 2-element array where first element is a number and second element is the data encoded in hex. - * * BinaryValue is converted to a string using UTF-8 encoding. Invalid byte sequence is replaced with U+FFFD replacement character. - * * Invalid UTF-8 byte sequences in StringValue is replaced with U+FFFD replacement character + *

    + *
  • if a key of MapValue is not string, the key is converted to a string using toString method.
  • + *
  • NaN and Infinity of DoubleValue are converted to null.
  • + *
  • ExtensionValue is converted to a 2-element array where first element is a number and second element is the data encoded in hex.
  • + *
  • BinaryValue is converted to a string using UTF-8 encoding. Invalid byte sequence is replaced with U+FFFD replacement character.
  • + *
  • Invalid UTF-8 byte sequences in StringValue is replaced with U+FFFD replacement character
  • + *
      */ String toJson(); } diff --git a/msgpack-core/src/main/java/org/msgpack/value/ValueType.java b/msgpack-core/src/main/java/org/msgpack/value/ValueType.java index 91b2a585f..b06936697 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ValueType.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ValueType.java @@ -16,7 +16,13 @@ package org.msgpack.value; /** - * MessageTypeFamily is a group of {@link org.msgpack.core.MessageFormat}s + * Representation of MessagePack types. + *

      + * MessagePack uses hierarchical type system. Integer and Float are subypte of Number, Thus {@link isNumberType()} + * returns true if type is Integer or Float. String and Binary are subtype of Raw. Thus {@link isRawType()} returns + * true if type is String or Binary. + * + * @see org.msgpack.core.MessageFormat */ public enum ValueType { From 462c2a04b796e10f3784639d48fa67d92eaf3fea Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Wed, 26 Oct 2016 10:12:56 -0700 Subject: [PATCH 029/417] docs: minor fixes --- .../main/java/org/msgpack/core/buffer/MessageBuffer.java | 9 +++++---- .../org/msgpack/core/buffer/MessageBufferOutput.java | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 65cb6eba3..05eccbfce 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -38,9 +38,9 @@ *

      * MessageBuffer class itself is optimized for little-endian CPU archtectures so that JVM (HotSpot) can take advantage * of the fastest JIT format which skips TypeProfile checking. To ensure this performance, applications must not load - * unnecessary classes such as MessagePackBE. On big-endian CPU archtectures, implementation uses subclass that - * includes TypeProfile overhead but still faster than ByteBuffer. On JVMs older than Java 7 and JVMs without Unsafe - * API (such as Android), implementation falls back to a universal implementation that uses standard ByteBuffer class + * unnecessary classes such as MessagePackBE. On big-endian CPU archtectures, it automatically uses a subclass that + * includes TypeProfile overhead but still faster than stndard ByteBuffer class. On JVMs older than Java 7 and JVMs + * without Unsafe API (such as Android), implementation falls back to an universal implementation that uses ByteBuffer * internally. */ public class MessageBuffer @@ -77,7 +77,8 @@ public class MessageBuffer try { int major = Integer.parseInt(javaVersion.substring(0, dotPos)); int minor = Integer.parseInt(javaVersion.substring(dotPos + 1)); - isJavaAtLeast7 = major > 1 || (major == 1 && minor >= 7); } + isJavaAtLeast7 = major > 1 || (major == 1 && minor >= 7); + } catch (NumberFormatException e) { e.printStackTrace(System.err); } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java index 9ae1b13dd..66a5c43ea 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java @@ -31,7 +31,7 @@ public interface MessageBufferOutput /** * Allocates the next buffer to write. *

      - * This method should return a MessageBuffer instance that has at least specified size of capacity. + * This method should return a MessageBuffer instance that has specified size of capacity at least. *

      * When this method is called twice, the previously returned buffer is no longer used. This method may be called * twice without call of {@link writeBuffer(MessageBuffer)} in between. In this case, the buffer should be @@ -51,7 +51,7 @@ MessageBuffer next(int minimumSize) * bytes. Once the buffer is written, the buffer is no longer used. *

      * This method is not always called for each {@link next(int)} call. In this case, the buffer should be discarded - * without flushing it to the output. + * without flushing it to the output when the next {@link next(int)} is called. * * @param length the number of bytes to write * @throws IOException From 629f8052027dc00ac0d564240a4c96604694a6f1 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Wed, 26 Oct 2016 10:25:17 -0700 Subject: [PATCH 030/417] docs: fixes warnings --- .../java/org/msgpack/core/MessagePacker.java | 22 ++++++++++--------- .../org/msgpack/core/MessageUnpacker.java | 7 +++--- .../msgpack/core/buffer/MessageBuffer.java | 15 ++++++++----- .../core/buffer/MessageBufferInput.java | 2 +- .../core/buffer/MessageBufferOutput.java | 10 ++++----- .../msgpack/value/ImmutableNumberValue.java | 4 ++-- .../java/org/msgpack/value/IntegerValue.java | 3 ++- .../main/java/org/msgpack/value/RawValue.java | 2 +- .../java/org/msgpack/value/ValueType.java | 4 ++-- 9 files changed, 36 insertions(+), 33 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 0c61b4bd1..3a6627f71 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -447,7 +447,7 @@ else if (v < (1 << 7)) { *

      * This method writes an integer using the smallest format from the int format family. * - * @param v the integer to be written + * @param r the integer to be written * @return this * @throws IOException when underlaying output throws IOException */ @@ -570,7 +570,7 @@ else if (bi.bitLength() == 64 && bi.signum() == 1) { *

      * This method writes a float value using float format family. * - * @param bi the integer to be written + * @param v the value to be written * @return this * @throws IOException when underlaying output throws IOException */ @@ -587,7 +587,7 @@ public MessagePacker packFloat(float v) *

      * This method writes a float value using float format family. * - * @param bi the integer to be written + * @param v the value to be written * @return this * @throws IOException when underlaying output throws IOException */ @@ -826,7 +826,8 @@ public MessagePacker packValue(Value v) *

      * You will call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. * - * @param len number of bytes of a payload binary to be written + * @param extType the extension type tag to be written + * @param payloadLen number of bytes of a payload binary to be written * @return this * @throws IOException when underlaying output throws IOException */ @@ -972,9 +973,9 @@ public MessagePacker writePayload(byte[] src, int off, int len) /** * Writes a byte array to the output. *

      - * Unlike {@link #writePayload} method, this method doesn't copy the byte array even when given byte array - * is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is faster than - * {@link writePayload} method but caller must not modify the byte array after calling this method. + * Unlike {@link #writePayload(byte[])} method, this method doesn't copy the byte array even when given byte + * array is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is faster than + * {@link #writePayload(byte[])} method but caller must not modify the byte array after calling this method. * * @param src the data to add * @return this @@ -989,9 +990,10 @@ public MessagePacker addPayload(byte[] src) /** * Writes a byte array to the output. *

      - * Unlike {@link #writePayload} method, this method doesn't copy the byte array even when given byte array - * is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is faster than - * {@link writePayload} method but caller must not modify the byte array after calling this method. + * Unlike {@link #writePayload(byte[], int, int)} method, this method doesn't copy the byte array even when + * given byte array is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. + * This is faster than {@link #writePayload(byte[], int, int)} method but caller must not modify the byte array + * after calling this method. * * @param src the data to add * @param off the start offset in the data diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 64d26a29f..99a42a5fb 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -47,7 +47,7 @@ *

      * One use case is to read objects as {@link Value} using {@link #unpackValue} method. A {@link Value} object * contains type of the deserialized value as well as the value itself so that you can inspect type of the - * deserialized values later. You can repeat {@link #unpackValue} until {@link hasNext()} method returns false so + * deserialized values later. You can repeat {@link #unpackValue} until {@link #hasNext()} method returns false so * that you can deserialize sequence of MessagePack values. *

      * The other use case is to use {@link #getNextFormat()} and {@link MessageFormat#getValueType()} methods followed @@ -142,7 +142,7 @@ * you call unpacker methods for each element. * *

      - * To read a Map, first you call {@link #unpackMapHeader(int)} method to get number of pairs of the map. Then, + * To read a Map, first you call {@link #unpackMapHeader()} method to get number of pairs of the map. Then, * for each pair, you call unpacker methods for key first, and then value. You will call unpacker methods twice * as many time as the returned count. * @@ -228,7 +228,7 @@ protected MessageUnpacker(MessageBufferInput in, MessagePack.UnpackerConfig conf *

      * This method doesn't close the old input. * - * @param out new input + * @param in new input * @return the old input * @throws IOException never happens unless a subclass overrides this method * @throws NullPointerException the given input is null @@ -718,7 +718,6 @@ public Variable unpackValue(Variable var) /** * Reads a Nil byte. * - * @return the read value * @throws MessageTypeException when value is not MessagePack Nil type * @throws IOException when underlaying input throws IOException */ diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 05eccbfce..730cd245b 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -33,7 +33,7 @@ * big-endian order. *

      * Applications can allocate a new buffer using {@link #allocate(int)} method, or wrap an byte array or ByteBuffer - * using {@link wrap(byte[], int, int)} methods. {@link wrap(ByteBuffer)} method supports both direct buffers and + * using {@link #wrap(byte[], int, int)} methods. {@link #wrap(ByteBuffer)} method supports both direct buffers and * array-backed buffers. *

      * MessageBuffer class itself is optimized for little-endian CPU archtectures so that JVM (HotSpot) can take advantage @@ -213,7 +213,7 @@ public static MessageBuffer allocate(int size) * The new buffer's size will be array.length. hasArray() will return true. * * @param array the byte array that will gack this MessageBuffer - * @return + * @return the new MessageBuffer * */ public static MessageBuffer wrap(byte[] array) @@ -231,7 +231,7 @@ public static MessageBuffer wrap(byte[] array) * @param array the byte array that will gack this MessageBuffer * @param offset The offset of the subarray to be used; must be non-negative and no larger than array.length * @param length The length of the subarray to be used; must be non-negative and no larger than array.length - offset - * @return + * @return the new MessageBuffer * */ public static MessageBuffer wrap(byte[] array, int offset, int length) @@ -249,7 +249,7 @@ public static MessageBuffer wrap(byte[] array, int offset, int length) * @param bb the byte buffer that will gack this MessageBuffer * @throws IllegalArgumentException given byte buffer returns false both from hasArray() and isDirect() * @throws UnsupportedOperationException given byte buffer is a direct buffer and this platform doesn't support Unsafe API - * @return + * @return the new MessageBuffer * */ public static MessageBuffer wrap(ByteBuffer bb) @@ -381,9 +381,12 @@ protected MessageBuffer(Object base, long address, int length) } /** - * byte size of the buffer + * Gets size of the buffer. * - * @return + * MessageBuffer doesn't have limit unlike ByteBuffer. Instead, you can use {@link #slice(int, int)} to get a + * part of the buffer. + * + * @return number of bytes */ public int size() { diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java index 2b19b9d99..77f7a06f6 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java @@ -43,7 +43,7 @@ MessageBuffer next() /** * Closes the input. *

      - * When this method is called, the buffer previously returned from {@link next()} method is no longer used. + * When this method is called, the buffer previously returned from {@link #next()} method is no longer used. * Thus implementation of this method can safely discard it. *

      * If the input is already closed then invoking this method has no effect. diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java index 66a5c43ea..a9a51fbcc 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java @@ -34,7 +34,7 @@ public interface MessageBufferOutput * This method should return a MessageBuffer instance that has specified size of capacity at least. *

      * When this method is called twice, the previously returned buffer is no longer used. This method may be called - * twice without call of {@link writeBuffer(MessageBuffer)} in between. In this case, the buffer should be + * twice without call of {@link #writeBuffer(int)} in between. In this case, the buffer should be * discarded without flushing it to the output. * * @param minimumSize the mimium required buffer size to allocate @@ -47,11 +47,11 @@ MessageBuffer next(int minimumSize) /** * Writes the previously allocated buffer. *

      - * This method should write the buffer previously returned from {@link next(int)} method until specified number of + * This method should write the buffer previously returned from {@link #next(int)} method until specified number of * bytes. Once the buffer is written, the buffer is no longer used. *

      - * This method is not always called for each {@link next(int)} call. In this case, the buffer should be discarded - * without flushing it to the output when the next {@link next(int)} is called. + * This method is not always called for each {@link #next(int)} call. In this case, the buffer should be discarded + * without flushing it to the output when the next {@link #next(int)} is called. * * @param length the number of bytes to write * @throws IOException @@ -66,7 +66,6 @@ void writeBuffer(int length) * @param buffer the data to write * @param offset the start offset in the data * @param length the number of bytes to write - * @return * @throws IOException */ void write(byte[] buffer, int offset, int length) @@ -82,7 +81,6 @@ void write(byte[] buffer, int offset, int length) * @param buffer the data to add * @param offset the start offset in the data * @param length the number of bytes to add - * @return * @throws IOException */ void add(byte[] buffer, int offset, int length) diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableNumberValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableNumberValue.java index 0ecd5bb36..a3b984af6 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableNumberValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableNumberValue.java @@ -18,8 +18,8 @@ /** * Immutable base interface of {@link ImmutableIntegerValue} and {@link ImmutableFloatValue} interfaces. To extract primitive type values, call toXXX methods, which may lose some information by rounding or truncation. * - * @see org.msgpack.value.immutableIntegerValue - * @see org.msgpack.value.immutableFloatValue + * @see org.msgpack.value.ImmutableIntegerValue + * @see org.msgpack.value.ImmutableFloatValue */ public interface ImmutableNumberValue extends NumberValue, ImmutableValue diff --git a/msgpack-core/src/main/java/org/msgpack/value/IntegerValue.java b/msgpack-core/src/main/java/org/msgpack/value/IntegerValue.java index 2776eb78c..b23378261 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/IntegerValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/IntegerValue.java @@ -49,7 +49,8 @@ public interface IntegerValue /** * Returns the most succinct MessageFormat type to represent this integer value. - * @return + * + * @return the smallest integer type of MessageFormat that is big enough to store the value. */ MessageFormat mostSuccinctMessageFormat(); diff --git a/msgpack-core/src/main/java/org/msgpack/value/RawValue.java b/msgpack-core/src/main/java/org/msgpack/value/RawValue.java index 9ce62463f..ba327a835 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/RawValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/RawValue.java @@ -38,7 +38,7 @@ public interface RawValue /** * Returns the value as {@code ByteBuffer}. * - * Returned ByteBuffer is read-only. See {@code#asReadOnlyBuffer()}. + * Returned ByteBuffer is read-only. See also {@link java.nio.ByteBuffer#asReadOnlyBuffer()}. * This method doesn't copy the byte array as much as possible. */ ByteBuffer asByteBuffer(); diff --git a/msgpack-core/src/main/java/org/msgpack/value/ValueType.java b/msgpack-core/src/main/java/org/msgpack/value/ValueType.java index b06936697..b06478402 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ValueType.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ValueType.java @@ -18,8 +18,8 @@ /** * Representation of MessagePack types. *

      - * MessagePack uses hierarchical type system. Integer and Float are subypte of Number, Thus {@link isNumberType()} - * returns true if type is Integer or Float. String and Binary are subtype of Raw. Thus {@link isRawType()} returns + * MessagePack uses hierarchical type system. Integer and Float are subypte of Number, Thus {@link #isNumberType()} + * returns true if type is Integer or Float. String and Binary are subtype of Raw. Thus {@link #isRawType()} returns * true if type is String or Binary. * * @see org.msgpack.core.MessageFormat From c0357ddb41ca8fc18bed91148b21c444c6782f04 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Thu, 3 Nov 2016 23:29:01 -0700 Subject: [PATCH 031/417] Upgrade to sbt 0.13.13 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 02cb92b32..24be09b28 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=0.13.9 +sbt.version=0.13.13 From 49ed7abfde095ec46ff93ef5440e9320cefa4967 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Sat, 26 Nov 2016 16:30:10 -0800 Subject: [PATCH 032/417] applied review comments to javadoc --- .../org/msgpack/core/MessageBufferPacker.java | 6 +- .../java/org/msgpack/core/MessagePacker.java | 62 +++++++++---------- .../org/msgpack/core/MessageUnpacker.java | 62 +++++++++---------- .../core/buffer/ArrayBufferOutput.java | 4 +- .../msgpack/core/buffer/MessageBuffer.java | 12 ++-- 5 files changed, 73 insertions(+), 73 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java index 3f6b732a1..38962dbe2 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java @@ -78,7 +78,7 @@ public byte[] toByteArray() flush(); } catch (IOException ex) { - // IOException must not happen because underlaying ArrayBufferOutput never throws IOException + // IOException must not happen because underlying ArrayBufferOutput never throws IOException throw new RuntimeException(ex); } return getArrayBufferOut().toByteArray(); @@ -98,7 +98,7 @@ public MessageBuffer toMessageBuffer() flush(); } catch (IOException ex) { - // IOException must not happen because underlaying ArrayBufferOutput never throws IOException + // IOException must not happen because underlying ArrayBufferOutput never throws IOException throw new RuntimeException(ex); } return getArrayBufferOut().toMessageBuffer(); @@ -118,7 +118,7 @@ public List toBufferList() flush(); } catch (IOException ex) { - // IOException must not happen because underlaying ArrayBufferOutput never throws IOException + // IOException must not happen because underlying ArrayBufferOutput never throws IOException throw new RuntimeException(ex); } return getArrayBufferOut().toBufferList(); diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 3a6627f71..1cd9a9801 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -72,7 +72,7 @@ * an instance. *

      * This class provides following primitive methods to write MessagePack values. These primitive methods write - * short bytes (1 to 7 bytes) to the internal buffer at once. There are also some complex methods for convenience. + * short bytes (1 to 7 bytes) to the internal buffer at once. There are also some utility methods for convenience. *

      * Primitive methods: * @@ -95,7 +95,7 @@ * * *

      - * Complex methods: + * Utility methods: * * * @@ -173,7 +173,7 @@ protected MessagePacker(MessageBufferOutput out, MessagePack.PackerConfig config } /** - * Replaces underlaying output. + * Replaces underlying output. *

      * This method flushes current internal buffer to the output, swaps it with the new given output, then returns * the old output. @@ -183,7 +183,7 @@ protected MessagePacker(MessageBufferOutput out, MessagePack.PackerConfig config * * @param out new output * @return the old output - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException * @throws NullPointerException the given output is null */ public MessageBufferOutput reset(MessageBufferOutput out) @@ -206,7 +206,7 @@ public MessageBufferOutput reset(MessageBufferOutput out) /** * Returns total number of written bytes. *

      - * This method returns total of amount of data flushed to the underlaying output plus size of current + * This method returns total of amount of data flushed to the underlying output plus size of current * internal buffer. * *

      @@ -218,9 +218,9 @@ public long getTotalWrittenBytes() } /** - * Flushes internal buffer to the underlaying output. + * Flushes internal buffer to the underlying output. *

      - * This method also calls flush method of the underlaying output after writing internal buffer. + * This method also calls flush method of the underlying output after writing internal buffer. */ @Override public void flush() @@ -233,7 +233,7 @@ public void flush() } /** - * Closes underlaying output. + * Closes underlying output. *

      * This method flushes internal buffer before closing. */ @@ -360,7 +360,7 @@ private void writeLong(long v) * This method writes a nil byte. * * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packNil() throws IOException @@ -375,7 +375,7 @@ public MessagePacker packNil() * This method writes a true byte or a false byte. * * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packBoolean(boolean b) throws IOException @@ -392,7 +392,7 @@ public MessagePacker packBoolean(boolean b) * * @param b the integer to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packByte(byte b) throws IOException @@ -414,7 +414,7 @@ public MessagePacker packByte(byte b) * * @param v the integer to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packShort(short v) throws IOException @@ -449,7 +449,7 @@ else if (v < (1 << 7)) { * * @param r the integer to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packInt(int r) throws IOException @@ -491,7 +491,7 @@ else if (r < (1 << 16)) { * * @param v the integer to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packLong(long v) throws IOException @@ -547,7 +547,7 @@ else if (v < (1 << 7)) { * * @param bi the integer to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packBigInteger(BigInteger bi) throws IOException @@ -572,7 +572,7 @@ else if (bi.bitLength() == 64 && bi.signum() == 1) { * * @param v the value to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packFloat(float v) throws IOException @@ -589,7 +589,7 @@ public MessagePacker packFloat(float v) * * @param v the value to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packDouble(double v) throws IOException @@ -666,7 +666,7 @@ private int encodeStringToBufferAt(int pos, String s) * * @param s the string to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packString(String s) throws IOException @@ -755,7 +755,7 @@ else if (s.length() < (1 << 16)) { * * @param arraySize number of elements to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packArrayHeader(int arraySize) throws IOException @@ -786,7 +786,7 @@ else if (arraySize < (1 << 16)) { * * @param mapSize number of pairs to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packMapHeader(int mapSize) throws IOException @@ -812,7 +812,7 @@ else if (mapSize < (1 << 16)) { * * @param v the value to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packValue(Value v) throws IOException @@ -824,12 +824,12 @@ public MessagePacker packValue(Value v) /** * Writes header of an Extension value. *

      - * You will call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. + * You MUST call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. * * @param extType the extension type tag to be written * @param payloadLen number of bytes of a payload binary to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packExtensionTypeHeader(byte extType, int payloadLen) throws IOException @@ -877,11 +877,11 @@ else if (payloadLen < (1 << 16)) { /** * Writes header of a Binary value. *

      - * You will call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. + * You MUST call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body binary. * * @param len number of bytes of a binary to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packBinaryHeader(int len) throws IOException @@ -903,12 +903,12 @@ else if (len < (1 << 16)) { *

      * Length must be number of bytes of a string in UTF-8 encoding. *

      - * You will call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body of the + * You MUST call {@link #writePayload(byte[])} or {@link #addPayload(byte[])} method to write body of the * UTF-8 encoded string. * * @param len number of bytes of a UTF-8 string to be written * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker packRawStringHeader(int len) throws IOException @@ -935,7 +935,7 @@ else if (len < (1 << 16)) { * * @param src the data to add * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker writePayload(byte[] src) throws IOException @@ -952,7 +952,7 @@ public MessagePacker writePayload(byte[] src) * @param off the start offset in the data * @param len the number of bytes to add * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker writePayload(byte[] src, int off, int len) throws IOException @@ -979,7 +979,7 @@ public MessagePacker writePayload(byte[] src, int off, int len) * * @param src the data to add * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker addPayload(byte[] src) throws IOException @@ -999,7 +999,7 @@ public MessagePacker addPayload(byte[] src) * @param off the start offset in the data * @param len the number of bytes to add * @return this - * @throws IOException when underlaying output throws IOException + * @throws IOException when underlying output throws IOException */ public MessagePacker addPayload(byte[] src, int off, int len) throws IOException diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 99a42a5fb..82ed9d15f 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -93,14 +93,14 @@ * case ARRAY: * length = unpacker.unpackArrayHeader(); * for (int i = 0; i < length; i++) { - * readRecursively(unpack); + * readRecursively(unpacker); * } * break; * case MAP: * length = unpacker.unpackMapHeader(); * for (int i = 0; i < length; i++) { - * readRecursively(unpack); // key - * readRecursively(unpack); // value + * readRecursively(unpacker); // key + * readRecursively(unpacker); // value * } * break; * case EXTENSION: @@ -134,16 +134,16 @@ *

      Java typePacker methodMessagePack type
      * *

      - * To read a byte array, first you call {@link #unpackBinaryHeader} method to get length of the byte array. Then, - * you call {@link #readPayload(int)} or {@link #readPayloadAsReference(int)} method to read the the contents. + * To read a byte array, first call {@link #unpackBinaryHeader} method to get length of the byte array. Then, + * call {@link #readPayload(int)} or {@link #readPayloadAsReference(int)} method to read the the contents. * *

      - * To read an Array type, first you call {@link #unpackArrayHeader()} method to get number of elements. Then, - * you call unpacker methods for each element. + * To read an Array type, first call {@link #unpackArrayHeader()} method to get number of elements. Then, + * call unpacker methods for each element. * *

      - * To read a Map, first you call {@link #unpackMapHeader()} method to get number of pairs of the map. Then, - * for each pair, you call unpacker methods for key first, and then value. You will call unpacker methods twice + * To read a Map, first call {@link #unpackMapHeader()} method to get number of pairs of the map. Then, + * for each pair, call unpacker methods for key first, and then value. will call unpacker methods twice * as many time as the returned count. * */ @@ -220,9 +220,9 @@ protected MessageUnpacker(MessageBufferInput in, MessagePack.UnpackerConfig conf } /** - * Replaces underlaying input. + * Replaces underlying input. *

      - * This method clears internal buffer, swaps the underlaying input with the new given input, then returns + * This method clears internal buffer, swaps the underlying input with the new given input, then returns * the old input. * *

      @@ -252,7 +252,7 @@ public MessageBufferInput reset(MessageBufferInput in) /** * Returns total number of read bytes. *

      - * This method returns total of amount of data consumed from the underlaying input minus size of data + * This method returns total of amount of data consumed from the underlying input minus size of data * remained still unused in the current internal buffer. * *

      @@ -383,7 +383,7 @@ private boolean ensureBuffer() * {@link #hasNext()} returns true. * * @return the next MessageFormat - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException * @throws MessageInsufficientBufferException when the end of file reached, i.e. {@link #hasNext()} == false. */ public MessageFormat getNextFormat() @@ -719,7 +719,7 @@ public Variable unpackValue(Variable var) * Reads a Nil byte. * * @throws MessageTypeException when value is not MessagePack Nil type - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public void unpackNil() throws IOException @@ -736,7 +736,7 @@ public void unpackNil() * * @return the read value * @throws MessageTypeException when value is not MessagePack Boolean type - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public boolean unpackBoolean() throws IOException @@ -759,7 +759,7 @@ else if (b == Code.TRUE) { * @return the read value * @throws MessageIntegerOverflowException when value doesn't fit in the range of byte * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public byte unpackByte() throws IOException @@ -826,7 +826,7 @@ public byte unpackByte() * @return the read value * @throws MessageIntegerOverflowException when value doesn't fit in the range of short * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public short unpackShort() throws IOException @@ -887,7 +887,7 @@ public short unpackShort() * @return the read value * @throws MessageIntegerOverflowException when value doesn't fit in the range of int * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public int unpackInt() throws IOException @@ -942,7 +942,7 @@ public int unpackInt() * @return the read value * @throws MessageIntegerOverflowException when value doesn't fit in the range of long * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public long unpackLong() throws IOException @@ -993,7 +993,7 @@ public long unpackLong() * * @return the read value * @throws MessageTypeException when value is not MessagePack Integer type - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public BigInteger unpackBigInteger() throws IOException @@ -1049,7 +1049,7 @@ public BigInteger unpackBigInteger() * * @return the read value * @throws MessageTypeException when value is not MessagePack Float type - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public float unpackFloat() throws IOException @@ -1071,7 +1071,7 @@ public float unpackFloat() * * @return the read value * @throws MessageTypeException when value is not MessagePack Float type - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public double unpackDouble() throws IOException @@ -1242,7 +1242,7 @@ private String decodeStringFastPath(int length) * @return the size of the array to be read * @throws MessageTypeException when value is not MessagePack Array type * @throws MessageSizeException when size of the array is larger than 2^31 - 1 - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public int unpackArrayHeader() throws IOException @@ -1275,7 +1275,7 @@ public int unpackArrayHeader() * @return the size of the map to be read * @throws MessageTypeException when value is not MessagePack Map type * @throws MessageSizeException when size of the map is larger than 2^31 - 1 - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public int unpackMapHeader() throws IOException @@ -1416,7 +1416,7 @@ public int unpackRawStringHeader() * @return the size of the map to be read * @throws MessageTypeException when value is not MessagePack Map type * @throws MessageSizeException when size of the map is larger than 2^31 - 1 - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public int unpackBinaryHeader() throws IOException @@ -1471,7 +1471,7 @@ private void skipPayload(int numBytes) * until ByteBuffer.remaining() returns 0. * * @param dst the byte buffer into which the data is read - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public void readPayload(ByteBuffer dst) throws IOException @@ -1500,7 +1500,7 @@ public void readPayload(ByteBuffer dst) * This method is equivalent to readPayload(dst, 0, dst.length). * * @param dst the byte array into which the data is read - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public void readPayload(byte[] dst) throws IOException @@ -1518,7 +1518,7 @@ public void readPayload(byte[] dst) * * @param length number of bytes to be read * @return the new byte array - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public byte[] readPayload(int length) throws IOException @@ -1536,7 +1536,7 @@ public byte[] readPayload(int length) * @param dst the byte array into which the data is read * @param off the offset in the dst array * @param len the number of bytes to read - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public void readPayload(byte[] dst, int off, int len) throws IOException @@ -1554,7 +1554,7 @@ public void readPayload(byte[] dst, int off, int len) * allocated buffer if reference is not applicable. * * @param length number of bytes to be read - * @throws IOException when underlaying input throws IOException + * @throws IOException when underlying input throws IOException */ public MessageBuffer readPayloadAsReference(int length) throws IOException @@ -1595,7 +1595,7 @@ private int readNextLength32() } /** - * Closes underlaying input. + * Closes underlying input. * * @throws IOException */ diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java index df952a61a..cd31e6453 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java @@ -44,7 +44,7 @@ public ArrayBufferOutput(int bufferSize) } /** - * Gets size of the written data. + * Gets the size of the written data. * * @return number of bytes */ @@ -58,7 +58,7 @@ public int getSize() } /** - * Gets copy of the written data as a byte array. + * Gets a copy of the written data as a byte array. *

      * If your application needs better performance and smaller memory consumption, you may prefer * {@link #toMessageBuffer()} or {@link #toBufferList()} to avoid copying. diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 730cd245b..246e678a7 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -37,7 +37,7 @@ * array-backed buffers. *

      * MessageBuffer class itself is optimized for little-endian CPU archtectures so that JVM (HotSpot) can take advantage - * of the fastest JIT format which skips TypeProfile checking. To ensure this performance, applications must not load + * of the fastest JIT format which skips TypeProfile checking. To ensure this performance, applications must not import * unnecessary classes such as MessagePackBE. On big-endian CPU archtectures, it automatically uses a subclass that * includes TypeProfile overhead but still faster than stndard ByteBuffer class. On JVMs older than Java 7 and JVMs * without Unsafe API (such as Android), implementation falls back to an universal implementation that uses ByteBuffer @@ -213,7 +213,7 @@ public static MessageBuffer allocate(int size) * The new buffer's size will be array.length. hasArray() will return true. * * @param array the byte array that will gack this MessageBuffer - * @return the new MessageBuffer + * @return a new MessageBuffer that wraps the given byte array * */ public static MessageBuffer wrap(byte[] array) @@ -231,7 +231,7 @@ public static MessageBuffer wrap(byte[] array) * @param array the byte array that will gack this MessageBuffer * @param offset The offset of the subarray to be used; must be non-negative and no larger than array.length * @param length The length of the subarray to be used; must be non-negative and no larger than array.length - offset - * @return the new MessageBuffer + * @return a new MessageBuffer that wraps the given byte array * */ public static MessageBuffer wrap(byte[] array, int offset, int length) @@ -249,7 +249,7 @@ public static MessageBuffer wrap(byte[] array, int offset, int length) * @param bb the byte buffer that will gack this MessageBuffer * @throws IllegalArgumentException given byte buffer returns false both from hasArray() and isDirect() * @throws UnsupportedOperationException given byte buffer is a direct buffer and this platform doesn't support Unsafe API - * @return the new MessageBuffer + * @return a new MessageBuffer that wraps the given byte array * */ public static MessageBuffer wrap(ByteBuffer bb) @@ -304,7 +304,7 @@ private static MessageBuffer newInstance(Constructor constructor, Object... a } catch (InvocationTargetException e) { if (e.getCause() instanceof RuntimeException) { - // underlaying constructor may throw RuntimeException + // underlying constructor may throw RuntimeException throw (RuntimeException) e.getCause(); } else if (e.getCause() instanceof Error) { @@ -381,7 +381,7 @@ protected MessageBuffer(Object base, long address, int length) } /** - * Gets size of the buffer. + * Gets the size of the buffer. * * MessageBuffer doesn't have limit unlike ByteBuffer. Instead, you can use {@link #slice(int, int)} to get a * part of the buffer. From 3a6ea2603dbf5a87129e658344194345808852bd Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sun, 27 Nov 2016 11:56:15 +0900 Subject: [PATCH 033/417] fix warning in build.sbt ``` /home/travis/build/msgpack/msgpack-java/build.sbt:59: warning: `<<=` operator is deprecated. Use `key := { x.value }` or `key ~= (old => { newValue })`. See http://www.scala-sbt.org/0.13/docs/Migrating-from-sbt-012x.html compile <<= (compile in Compile) dependsOn (jcheckStyle in Compile), ^ /home/travis/build/msgpack/msgpack-java/build.sbt:60: warning: `<<=` operator is deprecated. Use `key := { x.value }` or `key ~= (old => { newValue })`. See http://www.scala-sbt.org/0.13/docs/Migrating-from-sbt-012x.html compile <<= (compile in Test) dependsOn (jcheckStyle in Test) ^ ``` https://travis-ci.org/msgpack/msgpack-java/jobs/179129836#L277 --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 257e6b28f..ccb366cae 100644 --- a/build.sbt +++ b/build.sbt @@ -56,8 +56,8 @@ val buildSettings = findbugsSettings ++ jacoco.settings ++ osgiSettings ++ Seq[S jcheckStyleConfig := "facebook", // Run jcheckstyle both for main and test codes - compile <<= (compile in Compile) dependsOn (jcheckStyle in Compile), - compile <<= (compile in Test) dependsOn (jcheckStyle in Test) + (compile in Compile) := ((compile in Compile) dependsOn (jcheckStyle in Compile)).value, + (compile in Test) := ((compile in Test) dependsOn (jcheckStyle in Test)).value ) val junitInterface = "com.novocode" % "junit-interface" % "0.11" % "test" From 8ec7368b9a6eabf310ad6e2e9f97788e7d04614c Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 12 Dec 2016 17:36:46 -0800 Subject: [PATCH 034/417] Fix #403: Add authors --- AUTHORS | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..3401c83b9 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,5 @@ +FURUHASHI Sadayuki +Muga Nishizawa +Taro L. Saito +Mitsunori Komatsu +OZAWA Tsuyoshi From f669234af982314b39d1c9af9655a1d6dd0fa21d Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Mon, 12 Dec 2016 22:14:48 -0800 Subject: [PATCH 035/417] AUTHORS: updated --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 3401c83b9..cfcf3a089 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,4 @@ -FURUHASHI Sadayuki +Sadayuki Furuhashi Muga Nishizawa Taro L. Saito Mitsunori Komatsu From a4b0f3f922952169b30dfd6812c584c8100181ae Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 12 Jan 2017 00:33:16 +0900 Subject: [PATCH 036/417] Override MessagePackExtensionType#equals and hashCode Also, added an unit test of deserialization of MessagePackExtensionType based on type. --- .../dataformat/MessagePackExtensionType.java | 27 +++++++++ .../dataformat/MessagePackParserTest.java | 56 +++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java index 1906757f5..00b4f7de8 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.io.IOException; +import java.util.Arrays; @JsonSerialize(using = MessagePackExtensionType.Serializer.class) public class MessagePackExtensionType @@ -30,6 +31,32 @@ public byte[] getData() return data; } + @Override + public boolean equals(Object o) + { + if (this == o) { + return true; + } + if (!(o instanceof MessagePackExtensionType)) { + return false; + } + + MessagePackExtensionType that = (MessagePackExtensionType) o; + + if (type != that.type) { + return false; + } + return Arrays.equals(data, that.data); + } + + @Override + public int hashCode() + { + int result = (int) type; + result = 31 * result + Arrays.hashCode(data); + return result; + } + public static class Serializer extends JsonSerializer { @Override diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 112390598..8bab30926 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -23,11 +23,13 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import org.junit.Test; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -41,6 +43,9 @@ import java.util.List; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -671,4 +676,55 @@ public Object deserializeKey(String key, DeserializationContext ctxt) assertEquals((Integer) 2, map.get(true)); assertEquals((Integer) 3, map.get(false)); } + + public static class MyExtTypeDeserializer extends UntypedObjectDeserializer.Vanilla + { + @Override + public Object deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException + { + Object obj = super.deserialize(p, ctxt); + if (obj instanceof MessagePackExtensionType) { + MessagePackExtensionType ext = (MessagePackExtensionType) obj; + if (ext.getType() == 31) { + if (Arrays.equals(ext.getData(), new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE})) { + return "Java"; + } + return "Not Java"; + } + } + return obj; + } + } + + @Test + public void customDeserializationForExtType() + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + MessagePacker packer = MessagePack.newDefaultPacker(out); + packer.packArrayHeader(4); + packer.packString("foo bar"); + packer.packExtensionTypeHeader((byte) 31, 4); + packer.addPayload(new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}); + packer.packArrayHeader(1); + packer.packInt(42); + packer.packExtensionTypeHeader((byte) 32, 2); + packer.addPayload(new byte[] {(byte) 0xAB, (byte) 0xCD}); + packer.close(); + + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + SimpleModule module = new SimpleModule("MyModule").addDeserializer(Object.class, new MyExtTypeDeserializer()); + objectMapper.registerModule(module); + + List values = objectMapper.readValue(new ByteArrayInputStream(out.toByteArray()), new TypeReference>() {}); + assertThat(values.size(), is(4)); + assertThat((String) values.get(0), is("foo bar")); + assertThat((String) values.get(1), is("Java")); + assertThat(values.get(2), is(instanceOf(List.class))); + List nested = (List) values.get(2); + assertThat(nested.size(), is(1)); + assertThat((Integer) nested.get(0), is(42)); + assertThat((MessagePackExtensionType) values.get(3), is(new MessagePackExtensionType((byte) 32, new byte[] {(byte) 0xAB, (byte) 0xCD}))); + } } From 4112c0e3026b7c2d04907c7af69664f5ee3b5362 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 19 Jan 2017 00:55:22 +0900 Subject: [PATCH 037/417] Add MessagePackExtensionType.TypeBasedDeserializer --- .../dataformat/MessagePackExtensionType.java | 86 ++++++++++++++ .../dataformat/MessagePackFactory.java | 10 +- .../jackson/dataformat/MessagePackParser.java | 47 +++++++- .../dataformat/MessagePackParserTest.java | 109 ++++++++++++------ 4 files changed, 209 insertions(+), 43 deletions(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java index 00b4f7de8..65f350f2c 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java @@ -1,13 +1,20 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer; import java.io.IOException; import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; @JsonSerialize(using = MessagePackExtensionType.Serializer.class) public class MessagePackExtensionType @@ -72,4 +79,83 @@ public void serialize(MessagePackExtensionType value, JsonGenerator gen, Seriali } } } + + public interface Deser + { + Object deserialize(byte[] data) + throws IOException; + } + + public static class TypeBasedDeserializer + extends UntypedObjectDeserializer.Vanilla + { + private final ObjectMapper objectMapper; + private Map deserTable = new ConcurrentHashMap(); + + public TypeBasedDeserializer() + { + MessagePackFactory messagePackFactory = new MessagePackFactory(); + messagePackFactory.setReuseResourceInParser(false); + objectMapper = new ObjectMapper(messagePackFactory); + } + + public void addTargetClass(byte type, final Class klass) + { + deserTable.put(type, new Deser() { + @Override + public Object deserialize(byte[] data) + throws IOException + { + return objectMapper.readValue(data, klass); + } + }); + } + + public void addTargetTypeReference(byte type, final TypeReference typeReference) + { + deserTable.put(type, new Deser() { + @Override + public Object deserialize(byte[] data) + throws IOException + { + return objectMapper.readValue(data, typeReference); + } + }); + } + + public void addCustomDeser(byte type, final Deser deser) + { + deserTable.put(type, new Deser() { + @Override + public Object deserialize(byte[] data) + throws IOException + { + return deser.deserialize(data); + } + }); + } + + public void clearEntries() + { + deserTable.clear(); + } + + @Override + public Object deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException + { + Object obj = super.deserialize(p, ctxt); + if (! (obj instanceof MessagePackExtensionType)) { + return obj; + } + + MessagePackExtensionType ext = (MessagePackExtensionType) obj; + Deser deser = deserTable.get(ext.getType()); + if (deser == null) { + return obj; + } + + return deser.deserialize(ext.getData()); + } + } } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index 532fd85d6..964a0f796 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -38,6 +38,7 @@ public class MessagePackFactory private final MessagePack.PackerConfig packerConfig; private boolean reuseResourceInGenerator = true; + private boolean reuseResourceInParser = true; public MessagePackFactory() { @@ -54,6 +55,11 @@ public void setReuseResourceInGenerator(boolean reuseResourceInGenerator) this.reuseResourceInGenerator = reuseResourceInGenerator; } + public void setReuseResourceInParser(boolean reuseResourceInParser) + { + this.reuseResourceInParser = reuseResourceInParser; + } + @Override public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException @@ -95,7 +101,7 @@ public JsonParser createParser(InputStream in) protected MessagePackParser _createParser(InputStream in, IOContext ctxt) throws IOException { - MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, in); + MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, in, reuseResourceInParser); return parser; } @@ -106,7 +112,7 @@ protected JsonParser _createParser(byte[] data, int offset, int len, IOContext c if (offset != 0 || len != data.length) { data = Arrays.copyOfRange(data, offset, offset + len); } - MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, data); + MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, data, reuseResourceInParser); return parser; } } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index e1ef0c7ad..0c069cf5e 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -49,6 +49,7 @@ public class MessagePackParser { private static final ThreadLocal> messageUnpackerHolder = new ThreadLocal>(); + private final MessageUnpacker messageUnpacker; private static final BigInteger LONG_MIN = BigInteger.valueOf((long) Long.MIN_VALUE); private static final BigInteger LONG_MAX = BigInteger.valueOf((long) Long.MAX_VALUE); @@ -74,6 +75,7 @@ private enum Type private String stringValue; private BigInteger biValue; private MessagePackExtensionType extensionTypeValue; + private boolean reuseResourceInParser; private abstract static class StackItem { @@ -116,16 +118,43 @@ private static class StackItemForArray public MessagePackParser(IOContext ctxt, int features, ObjectCodec objectCodec, InputStream in) throws IOException { - this(ctxt, features, new InputStreamBufferInput(in), objectCodec, in); + this(ctxt, features, objectCodec, in, true); + } + + public MessagePackParser( + IOContext ctxt, + int features, + ObjectCodec objectCodec, + InputStream in, + boolean reuseResourceInParser) + throws IOException + { + this(ctxt, features, new InputStreamBufferInput(in), objectCodec, in, reuseResourceInParser); } public MessagePackParser(IOContext ctxt, int features, ObjectCodec objectCodec, byte[] bytes) throws IOException { - this(ctxt, features, new ArrayBufferInput(bytes), objectCodec, bytes); + this(ctxt, features, objectCodec, bytes, true); } - private MessagePackParser(IOContext ctxt, int features, MessageBufferInput input, ObjectCodec objectCodec, Object src) + public MessagePackParser( + IOContext ctxt, + int features, + ObjectCodec objectCodec, + byte[] bytes, + boolean reuseResourceInParser) + throws IOException + { + this(ctxt, features, new ArrayBufferInput(bytes), objectCodec, bytes, reuseResourceInParser); + } + + private MessagePackParser(IOContext ctxt, + int features, + MessageBufferInput input, + ObjectCodec objectCodec, + Object src, + boolean reuseResourceInParser) throws IOException { super(features); @@ -135,6 +164,14 @@ private MessagePackParser(IOContext ctxt, int features, MessageBufferInput input DupDetector dups = Feature.STRICT_DUPLICATE_DETECTION.enabledIn(features) ? DupDetector.rootDetector(this) : null; parsingContext = JsonReadContext.createRootContext(dups); + this.reuseResourceInParser = reuseResourceInParser; + if (!reuseResourceInParser) { + this.messageUnpacker = MessagePack.newDefaultUnpacker(input); + return; + } + else { + this.messageUnpacker = null; + } MessageUnpacker messageUnpacker; Tuple messageUnpackerTuple = messageUnpackerHolder.get(); @@ -607,6 +644,10 @@ public String getCurrentName() private MessageUnpacker getMessageUnpacker() { + if (!reuseResourceInParser) { + return this.messageUnpacker; + } + Tuple messageUnpackerTuple = messageUnpackerHolder.get(); if (messageUnpackerTuple == null) { throw new IllegalStateException("messageUnpacker is null"); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 8bab30926..c2d9bfbdf 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -23,7 +23,6 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import org.junit.Test; import org.msgpack.core.MessagePack; @@ -40,6 +39,7 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -677,54 +677,87 @@ public Object deserializeKey(String key, DeserializationContext ctxt) assertEquals((Integer) 3, map.get(false)); } - public static class MyExtTypeDeserializer extends UntypedObjectDeserializer.Vanilla - { - @Override - public Object deserialize(JsonParser p, DeserializationContext ctxt) - throws IOException - { - Object obj = super.deserialize(p, ctxt); - if (obj instanceof MessagePackExtensionType) { - MessagePackExtensionType ext = (MessagePackExtensionType) obj; - if (ext.getType() == 31) { - if (Arrays.equals(ext.getData(), new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE})) { - return "Java"; - } - return "Not Java"; - } - } - return obj; - } - } - @Test - public void customDeserializationForExtType() + public void typeBasedDeserialize() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); MessagePacker packer = MessagePack.newDefaultPacker(out); - packer.packArrayHeader(4); - packer.packString("foo bar"); - packer.packExtensionTypeHeader((byte) 31, 4); - packer.addPayload(new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}); - packer.packArrayHeader(1); + packer.packArrayHeader(5); + // 0: Integer packer.packInt(42); - packer.packExtensionTypeHeader((byte) 32, 2); - packer.addPayload(new byte[] {(byte) 0xAB, (byte) 0xCD}); + // 1: String + packer.packString("foo bar"); + // 2: ExtensionType(class desr) + { + TinyPojo t0 = new TinyPojo(); + t0.t = "t0"; + TinyPojo t1 = new TinyPojo(); + t1.t = "t1"; + NestedListComplexPojo parent = new NestedListComplexPojo(); + parent.s = "parent"; + parent.foos = Arrays.asList(t0, t1); + byte[] bytes = objectMapper.writeValueAsBytes(parent); + packer.packExtensionTypeHeader((byte) 17, bytes.length); + packer.addPayload(bytes); + } + // 3: ExtensionType(type reference deser) + { + Map map = new HashMap(); + map.put("one", 1); + map.put("two", 2); + byte[] bytes = objectMapper.writeValueAsBytes(map); + packer.packExtensionTypeHeader((byte) 99, bytes.length); + packer.addPayload(bytes); + } + // 4: ExtensionType(custom deser) + { + packer.packExtensionTypeHeader((byte) 31, 4); + packer.addPayload(new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}); + } packer.close(); ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - SimpleModule module = new SimpleModule("MyModule").addDeserializer(Object.class, new MyExtTypeDeserializer()); + MessagePackExtensionType.TypeBasedDeserializer typeBasedDeserializer + = new MessagePackExtensionType.TypeBasedDeserializer(); + typeBasedDeserializer.addTargetClass((byte) 17, NestedListComplexPojo.class); + typeBasedDeserializer.addTargetTypeReference((byte) 99, new TypeReference>() {}); + typeBasedDeserializer.addCustomDeser((byte) 31, new MessagePackExtensionType.Deser() { + @Override + public Object deserialize(byte[] data) + throws IOException + { + if (Arrays.equals(data, new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE})) { + return "Java"; + } + return "Not Java"; + } + } + ); + SimpleModule module = new SimpleModule("MyModule").addDeserializer(Object.class, typeBasedDeserializer); objectMapper.registerModule(module); List values = objectMapper.readValue(new ByteArrayInputStream(out.toByteArray()), new TypeReference>() {}); - assertThat(values.size(), is(4)); - assertThat((String) values.get(0), is("foo bar")); - assertThat((String) values.get(1), is("Java")); - assertThat(values.get(2), is(instanceOf(List.class))); - List nested = (List) values.get(2); - assertThat(nested.size(), is(1)); - assertThat((Integer) nested.get(0), is(42)); - assertThat((MessagePackExtensionType) values.get(3), is(new MessagePackExtensionType((byte) 32, new byte[] {(byte) 0xAB, (byte) 0xCD}))); + assertThat(values.size(), is(5)); + assertThat((Integer) values.get(0), is(42)); + assertThat((String) values.get(1), is("foo bar")); + { + Object v = values.get(2); + assertThat(v, is(instanceOf(NestedListComplexPojo.class))); + NestedListComplexPojo pojo = (NestedListComplexPojo) v; + assertThat(pojo.s, is("parent")); + assertThat(pojo.foos.size(), is(2)); + assertThat(pojo.foos.get(0).t, is("t0")); + assertThat(pojo.foos.get(1).t, is("t1")); + } + { + Object v = values.get(3); + assertThat(v, is(instanceOf(Map.class))); + Map map = (Map) v; + assertThat(map.size(), is(2)); + assertThat(map.get("one"), is(1)); + assertThat(map.get("two"), is(2)); + } + assertThat((String) values.get(4), is("Java")); } } From 473268ebbcf08f6824c0f41ffaf1a8e78b78e78d Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 20 Jan 2017 00:14:32 +0900 Subject: [PATCH 038/417] Add MessagePackFactory#setExtTypeCustomDesers --- .../ExtensionTypeCustomDeserializers.java | 89 +++++++++++++++++++ .../dataformat/MessagePackExtensionType.java | 86 ------------------ .../dataformat/MessagePackFactory.java | 19 +++- .../jackson/dataformat/MessagePackParser.java | 12 +++ .../dataformat/MessagePackParserTest.java | 16 ++-- 5 files changed, 125 insertions(+), 97 deletions(-) create mode 100644 msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java new file mode 100644 index 000000000..6d61ce53b --- /dev/null +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java @@ -0,0 +1,89 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.jackson.dataformat; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ExtensionTypeCustomDeserializers +{ + private final ObjectMapper objectMapper; + private Map deserTable = new ConcurrentHashMap(); + + public ExtensionTypeCustomDeserializers() + { + objectMapper = new ObjectMapper(new MessagePackFactory().setReuseResourceInParser(false)); + } + + public void addTargetClass(byte type, final Class klass) + { + deserTable.put(type, new Deser() + { + @Override + public Object deserialize(byte[] data) + throws IOException + { + return objectMapper.readValue(data, klass); + } + }); + } + + public void addTargetTypeReference(byte type, final TypeReference typeReference) + { + deserTable.put(type, new Deser() + { + @Override + public Object deserialize(byte[] data) + throws IOException + { + return objectMapper.readValue(data, typeReference); + } + }); + } + + public void addCustomDeser(byte type, final Deser deser) + { + deserTable.put(type, new Deser() + { + @Override + public Object deserialize(byte[] data) + throws IOException + { + return deser.deserialize(data); + } + }); + } + + public Deser getDeser(byte type) + { + return deserTable.get(type); + } + + public void clearEntries() + { + deserTable.clear(); + } + + public interface Deser + { + Object deserialize(byte[] data) + throws IOException; + } +} diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java index 65f350f2c..00b4f7de8 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java @@ -1,20 +1,13 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer; import java.io.IOException; import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; @JsonSerialize(using = MessagePackExtensionType.Serializer.class) public class MessagePackExtensionType @@ -79,83 +72,4 @@ public void serialize(MessagePackExtensionType value, JsonGenerator gen, Seriali } } } - - public interface Deser - { - Object deserialize(byte[] data) - throws IOException; - } - - public static class TypeBasedDeserializer - extends UntypedObjectDeserializer.Vanilla - { - private final ObjectMapper objectMapper; - private Map deserTable = new ConcurrentHashMap(); - - public TypeBasedDeserializer() - { - MessagePackFactory messagePackFactory = new MessagePackFactory(); - messagePackFactory.setReuseResourceInParser(false); - objectMapper = new ObjectMapper(messagePackFactory); - } - - public void addTargetClass(byte type, final Class klass) - { - deserTable.put(type, new Deser() { - @Override - public Object deserialize(byte[] data) - throws IOException - { - return objectMapper.readValue(data, klass); - } - }); - } - - public void addTargetTypeReference(byte type, final TypeReference typeReference) - { - deserTable.put(type, new Deser() { - @Override - public Object deserialize(byte[] data) - throws IOException - { - return objectMapper.readValue(data, typeReference); - } - }); - } - - public void addCustomDeser(byte type, final Deser deser) - { - deserTable.put(type, new Deser() { - @Override - public Object deserialize(byte[] data) - throws IOException - { - return deser.deserialize(data); - } - }); - } - - public void clearEntries() - { - deserTable.clear(); - } - - @Override - public Object deserialize(JsonParser p, DeserializationContext ctxt) - throws IOException - { - Object obj = super.deserialize(p, ctxt); - if (! (obj instanceof MessagePackExtensionType)) { - return obj; - } - - MessagePackExtensionType ext = (MessagePackExtensionType) obj; - Deser deser = deserTable.get(ext.getType()); - if (deser == null) { - return obj; - } - - return deser.deserialize(ext.getData()); - } - } } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index 964a0f796..11b5ee88f 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -39,6 +39,7 @@ public class MessagePackFactory private final MessagePack.PackerConfig packerConfig; private boolean reuseResourceInGenerator = true; private boolean reuseResourceInParser = true; + private ExtensionTypeCustomDeserializers extTypeCustomDesers; public MessagePackFactory() { @@ -50,14 +51,22 @@ public MessagePackFactory(MessagePack.PackerConfig packerConfig) this.packerConfig = packerConfig; } - public void setReuseResourceInGenerator(boolean reuseResourceInGenerator) + public MessagePackFactory setReuseResourceInGenerator(boolean reuseResourceInGenerator) { this.reuseResourceInGenerator = reuseResourceInGenerator; + return this; } - public void setReuseResourceInParser(boolean reuseResourceInParser) + public MessagePackFactory setReuseResourceInParser(boolean reuseResourceInParser) { this.reuseResourceInParser = reuseResourceInParser; + return this; + } + + public MessagePackFactory setExtTypeCustomDesers(ExtensionTypeCustomDeserializers extTypeCustomDesers) + { + this.extTypeCustomDesers = extTypeCustomDesers; + return this; } @Override @@ -102,6 +111,9 @@ protected MessagePackParser _createParser(InputStream in, IOContext ctxt) throws IOException { MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, in, reuseResourceInParser); + if (extTypeCustomDesers != null) { + parser.setExtensionTypeCustomDeserializers(extTypeCustomDesers); + } return parser; } @@ -113,6 +125,9 @@ protected JsonParser _createParser(byte[] data, int offset, int len, IOContext c data = Arrays.copyOfRange(data, offset, offset + len); } MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, data, reuseResourceInParser); + if (extTypeCustomDesers != null) { + parser.setExtensionTypeCustomDeserializers(extTypeCustomDesers); + } return parser; } } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 0c069cf5e..9d73bef81 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -62,6 +62,7 @@ public class MessagePackParser private long tokenPosition; private long currentPosition; private final IOContext ioContext; + private ExtensionTypeCustomDeserializers extTypeCustomDesers; private enum Type { @@ -191,6 +192,11 @@ private MessagePackParser(IOContext ctxt, messageUnpackerHolder.set(new Tuple(src, messageUnpacker)); } + public void setExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers extTypeCustomDesers) + { + this.extTypeCustomDesers = extTypeCustomDesers; + } + @Override public ObjectCodec getCodec() { @@ -551,6 +557,12 @@ public Object getEmbeddedObject() case BYTES: return bytesValue; case EXT: + if (extTypeCustomDesers != null) { + ExtensionTypeCustomDeserializers.Deser deser = extTypeCustomDesers.getDeser(extensionTypeValue.getType()); + if (deser != null) { + return deser.deserialize(extensionTypeValue.getData()); + } + } return extensionTypeValue; default: throw new IllegalStateException("Invalid type=" + type); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index c2d9bfbdf..9555e6b65 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -678,7 +678,7 @@ public Object deserializeKey(String key, DeserializationContext ctxt) } @Test - public void typeBasedDeserialize() + public void extensionTypeCustomDeserializers() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -717,12 +717,10 @@ public void typeBasedDeserialize() } packer.close(); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - MessagePackExtensionType.TypeBasedDeserializer typeBasedDeserializer - = new MessagePackExtensionType.TypeBasedDeserializer(); - typeBasedDeserializer.addTargetClass((byte) 17, NestedListComplexPojo.class); - typeBasedDeserializer.addTargetTypeReference((byte) 99, new TypeReference>() {}); - typeBasedDeserializer.addCustomDeser((byte) 31, new MessagePackExtensionType.Deser() { + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addTargetClass((byte) 17, NestedListComplexPojo.class); + extTypeCustomDesers.addTargetTypeReference((byte) 99, new TypeReference>() {}); + extTypeCustomDesers.addCustomDeser((byte) 31, new ExtensionTypeCustomDeserializers.Deser() { @Override public Object deserialize(byte[] data) throws IOException @@ -734,8 +732,8 @@ public Object deserialize(byte[] data) } } ); - SimpleModule module = new SimpleModule("MyModule").addDeserializer(Object.class, typeBasedDeserializer); - objectMapper.registerModule(module); + ObjectMapper objectMapper = + new ObjectMapper(new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); List values = objectMapper.readValue(new ByteArrayInputStream(out.toByteArray()), new TypeReference>() {}); assertThat(values.size(), is(5)); From f536c935ab4428257f1092c808b446d6197029f8 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 22 Jan 2017 00:14:35 +0900 Subject: [PATCH 039/417] Avoid using CharsetEncoder of Android 4.x Android 4.x has a bug in CharsetEncoder where offset calculation is wrong. See - https://github.com/msgpack/msgpack-java/issues/405 - https://github.com/msgpack/msgpack-java/issues/406 --- .../java/org/msgpack/core/MessagePacker.java | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 1cd9a9801..7c6700bd3 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -22,6 +22,9 @@ import java.io.Closeable; import java.io.Flushable; import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -130,6 +133,46 @@ public class MessagePacker implements Closeable, Flushable { + private static final boolean CORRUPTED_CHARSET_ENCODER; + + static { + boolean corruptedCharsetEncoder = false; + try { + Class klass = Class.forName("android.os.Build$VERSION"); + Constructor constructor = klass.getConstructor(); + Object version = constructor.newInstance(); + Field sdkIntField = klass.getField("SDK_INT"); + int sdkInt = sdkIntField.getInt(version); + // Android 4.x has a bug in CharsetEncoder where offset calculation is wrong. + // See + // - https://github.com/msgpack/msgpack-java/issues/405 + // - https://github.com/msgpack/msgpack-java/issues/406 + // Android 5 and later and 3.x don't have this bug. + if (sdkInt >= 14 && sdkInt < 21) { + corruptedCharsetEncoder = true; + } + } + catch (ClassNotFoundException e) { + // This platform isn't Android + } + catch (NoSuchMethodException e) { + e.printStackTrace(); + } + catch (IllegalAccessException e) { + e.printStackTrace(); + } + catch (InstantiationException e) { + e.printStackTrace(); + } + catch (InvocationTargetException e) { + e.printStackTrace(); + } + catch (NoSuchFieldException e) { + e.printStackTrace(); + } + CORRUPTED_CHARSET_ENCODER = corruptedCharsetEncoder; + } + private final int smallStringOptimizationThreshold; private final int bufferFlushThreshold; @@ -675,8 +718,9 @@ public MessagePacker packString(String s) packRawStringHeader(0); return this; } - else if (s.length() < smallStringOptimizationThreshold) { - // Using String.getBytes is generally faster for small strings + else if (CORRUPTED_CHARSET_ENCODER || s.length() < smallStringOptimizationThreshold) { + // Using String.getBytes is generally faster for small strings. + // Also, when running on a platform that has a corrupted CharsetEncoder (i.e. Android 4.x), avoid using it. packStringWithGetBytes(s); return this; } From 3f5787cf69e67b881a3e654f82b89dbeece89fa0 Mon Sep 17 00:00:00 2001 From: pocketberserker Date: Sun, 12 Feb 2017 11:44:12 +0900 Subject: [PATCH 040/417] fix typos --- .../java/org/msgpack/core/buffer/ArrayBufferOutput.java | 6 +++--- .../java/org/msgpack/core/buffer/ChannelBufferOutput.java | 6 +++--- .../org/msgpack/core/buffer/OutputStreamBufferOutput.java | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java index cd31e6453..955d48ad4 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java @@ -119,13 +119,13 @@ public void clear() } @Override - public MessageBuffer next(int mimimumSize) + public MessageBuffer next(int minimumSize) { - if (lastBuffer != null && lastBuffer.size() > mimimumSize) { + if (lastBuffer != null && lastBuffer.size() > minimumSize) { return lastBuffer; } else { - int size = Math.max(bufferSize, mimimumSize); + int size = Math.max(bufferSize, minimumSize); MessageBuffer buffer = MessageBuffer.allocate(size); lastBuffer = buffer; return buffer; diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java index 32969f29a..155c86b12 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java @@ -56,11 +56,11 @@ public WritableByteChannel reset(WritableByteChannel channel) } @Override - public MessageBuffer next(int mimimumSize) + public MessageBuffer next(int minimumSize) throws IOException { - if (buffer.size() < mimimumSize) { - buffer = MessageBuffer.allocate(mimimumSize); + if (buffer.size() < minimumSize) { + buffer = MessageBuffer.allocate(minimumSize); } return buffer; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java index 08fd3960b..cbba1333e 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java @@ -55,11 +55,11 @@ public OutputStream reset(OutputStream out) } @Override - public MessageBuffer next(int mimimumSize) + public MessageBuffer next(int minimumSize) throws IOException { - if (buffer.size() < mimimumSize) { - buffer = MessageBuffer.allocate(mimimumSize); + if (buffer.size() < minimumSize) { + buffer = MessageBuffer.allocate(minimumSize); } return buffer; } From a7368340ceab589966109751021c0899bea7f627 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Tue, 14 Feb 2017 15:21:08 -0800 Subject: [PATCH 041/417] Update msgpack.org.md --- msgpack.org.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack.org.md b/msgpack.org.md index 17cbc0720..580febac6 100644 --- a/msgpack.org.md +++ b/msgpack.org.md @@ -1,6 +1,6 @@ # MessagePack for Java -QuickStart for msgpack-java is available [here](https://github.com/msgpack/msgpack-java/wiki/QuickStart). +[JavaDoc is available at javadoc.io](https://www.javadoc.io/doc/org.msgpack/msgpack-core). ## How to install From e2d0058821202209e9e901beccc15cfe96e8a658 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Tue, 14 Feb 2017 15:21:34 -0800 Subject: [PATCH 042/417] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c31dd1371..021c144a5 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ MessagePack for Java MessagePack v7 (or later) is a faster implementation of the previous version [v06](https://github.com/msgpack/msgpack-java/tree/v06), and supports all of the message pack types, including [extension format](https://github.com/msgpack/msgpack/blob/master/spec.md#formats-ext). +[JavaDoc is available at javadoc.io](https://www.javadoc.io/doc/org.msgpack/msgpack-core). + ## Quick Start [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.msgpack/msgpack-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.msgpack/msgpack-core/) From dc42c9e4a05586af1f5e402cb5319f739bc62ab8 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 19 Feb 2017 22:52:02 +0900 Subject: [PATCH 043/417] Add release note for 0.8.12 --- RELEASE_NOTES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4ec950ce0..80146d7de 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,10 @@ # Release Notes +## 0.8.12 + * Fix warnings in build.sbt[#402](https://github.com/msgpack/msgpack-java/pull/402) + * Add ExtensionTypeCustomDeserializers and MessagePackFactory#setExtTypeCustomDesers[#408](https://github.com/msgpack/msgpack-java/pull/408) + * Avoid a CharsetEncoder bug of Android 4.x at MessagePacker#packString[#409](https://github.com/msgpack/msgpack-java/pull/409) + ## 0.8.11 * Fixed NPE when write(add)Payload are used at the beginning [#392](https://github.com/msgpack/msgpack-java/pull/392) From 7142d1778311c1ad034696035485f2568f017ff0 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 19 Feb 2017 22:54:12 +0900 Subject: [PATCH 044/417] Setting version to 0.8.12 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 9a07a88f1..641fb4bf9 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.12-SNAPSHOT" \ No newline at end of file +version in ThisBuild := "0.8.12" \ No newline at end of file From 430bc1652dccc25c167d47a96467428662e86b15 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 19 Feb 2017 22:54:55 +0900 Subject: [PATCH 045/417] Setting version to 0.8.13-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 641fb4bf9..4dbb0518e 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.12" \ No newline at end of file +version in ThisBuild := "0.8.13-SNAPSHOT" \ No newline at end of file From 2733a81868bbe054432631bc6ecce52505bd43ee Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Mon, 13 Mar 2017 14:38:59 +0900 Subject: [PATCH 046/417] fix ambiguous overload in Java 9 - http://download.java.net/java/jdk9/docs/api/java/nio/Buffer.html#limit-int- - http://download.java.net/java/jdk9/docs/api/java/nio/ByteBuffer.html#position-int- ``` [error] /home/travis/build/xuwei-k/msgpack-java/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala:163: ambiguous reference to overloaded definition, [error] both method position in class ByteBuffer of type (x$1: Int)java.nio.ByteBuffer [error] and method position in class Buffer of type ()Int [error] match expected type ? [error] bb.position shouldBe 0 [error] ^ [error] /home/travis/build/xuwei-k/msgpack-java/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala:164: ambiguous reference to overloaded definition, [error] both method limit in class ByteBuffer of type (x$1: Int)java.nio.ByteBuffer [error] and method limit in class Buffer of type ()Int [error] match expected type ? [error] bb.limit shouldBe 10 [error] ^ [error] two errors found ``` --- .../scala/org/msgpack/core/buffer/MessageBufferTest.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala index b7871065b..40a185148 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala @@ -160,8 +160,8 @@ class MessageBufferTest "convert to ByteBuffer" in { for (t <- buffers) { val bb = t.sliceAsByteBuffer - bb.position shouldBe 0 - bb.limit shouldBe 10 + bb.position() shouldBe 0 + bb.limit() shouldBe 10 bb.capacity shouldBe 10 } } From 51cf272f05dffdb4a2f606831f0acf1a98f88933 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Tue, 25 Apr 2017 23:44:29 +0900 Subject: [PATCH 047/417] Make MessagePackParser accept a string as a byte array field --- .../jackson/dataformat/MessagePackParser.java | 11 +++++++--- .../MessagePackDataformatTestBase.java | 6 +++++ .../dataformat/MessagePackParserTest.java | 22 +++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 9d73bef81..5df9632ab 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -32,7 +32,6 @@ import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePack; import org.msgpack.core.MessageUnpacker; -import org.msgpack.core.Preconditions; import org.msgpack.core.buffer.ArrayBufferInput; import org.msgpack.core.buffer.InputStreamBufferInput; import org.msgpack.core.buffer.MessageBufferInput; @@ -419,8 +418,14 @@ public int getTextOffset() public byte[] getBinaryValue(Base64Variant b64variant) throws IOException, JsonParseException { - Preconditions.checkArgument(type == Type.BYTES); - return bytesValue; + switch (type) { + case BYTES: + return bytesValue; + case STRING: + return stringValue.getBytes(MessagePack.UTF8); + default: + throw new IllegalStateException("Invalid type=" + type); + } } @Override diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java index 33d7c4fa1..d2d3d456a 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java @@ -160,6 +160,12 @@ public void setS(String s) } } + public static class BinKeyPojo + { + public byte[] b; + public String s; + } + public static class UsingCustomConstructorPojo { final String name; diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 9555e6b65..ffc5854be 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -758,4 +758,26 @@ public Object deserialize(byte[] data) } assertThat((String) values.get(4), is("Java")); } + + @Test + public void parserShouldReadStrAsBin() + throws IOException + { + MessagePacker packer = MessagePack.newDefaultPacker(out); + packer.packMapHeader(2); + // #1 + packer.packString("s"); + packer.packString("foo"); + // #2 + packer.packString("b"); + packer.packString("bar"); + + packer.flush(); + + byte[] bytes = out.toByteArray(); + + BinKeyPojo binKeyPojo = objectMapper.readValue(bytes, BinKeyPojo.class); + assertEquals("foo", binKeyPojo.s); + assertArrayEquals("bar".getBytes(), binKeyPojo.b); + } } From 0659227393ac08112ab6e281e748ba217adce63b Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 14 May 2017 22:32:02 +0900 Subject: [PATCH 048/417] Add MessagePackGenerator#writeNumber(String) --- .../dataformat/MessagePackGenerator.java | 38 ++++- .../dataformat/MessagePackGeneratorTest.java | 152 ++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index b95db72f3..0aef84e12 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -25,6 +25,7 @@ import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; import org.msgpack.core.buffer.OutputStreamBufferOutput; +import org.msgpack.value.FloatValue; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -438,7 +439,42 @@ public void writeNumber(BigDecimal dec) public void writeNumber(String encodedValue) throws IOException, JsonGenerationException, UnsupportedOperationException { - throw new UnsupportedOperationException("writeNumber(String encodedValue) isn't supported yet"); + // There is a room to improve this API's performance while the implementation is robust. + // If users can use other MessagePackGenerator#writeNumber APIs that accept + // proper numeric types not String, it's better to use the other APIs instead. + try { + long l = Long.parseLong(encodedValue); + addValueToStackTop(l); + return; + } + catch (NumberFormatException e) { + } + + try { + double d = Double.parseDouble(encodedValue); + addValueToStackTop(d); + return; + } + catch (NumberFormatException e) { + } + + try { + BigInteger bi = new BigInteger(encodedValue); + addValueToStackTop(bi); + return; + } + catch (NumberFormatException e) { + } + + try { + BigDecimal bc = new BigDecimal(encodedValue); + addValueToStackTop(bc); + return; + } + catch (NumberFormatException e) { + } + + throw new NumberFormatException(encodedValue); } @Override diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index 73fce0cb2..7a8db2805 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -17,8 +17,12 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonEncoding; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.module.SimpleModule; import org.junit.Test; import org.msgpack.core.ExtensionTypeHeader; import org.msgpack.core.MessagePack; @@ -732,4 +736,152 @@ public void testComplexTypeKeyWithV06Format() assertThat(unpacker.unpackString(), is("foo")); assertThat(unpacker.unpackInt(), is(42)); } + + // Test serializers that store a string as a number + + public static class IntegerSerializerStoringAsString + extends JsonSerializer + { + @Override + public void serialize(Integer value, JsonGenerator gen, SerializerProvider serializers) + throws IOException, JsonProcessingException + { + gen.writeNumber(String.valueOf(value)); + } + } + + @Test + public void serializeStringAsInteger() + throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.registerModule( + new SimpleModule().addSerializer(Integer.class, new IntegerSerializerStoringAsString())); + + assertThat( + MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(Integer.MAX_VALUE)).unpackInt(), + is(Integer.MAX_VALUE)); + } + + public static class LongSerializerStoringAsString + extends JsonSerializer + { + @Override + public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) + throws IOException, JsonProcessingException + { + gen.writeNumber(String.valueOf(value)); + } + } + + @Test + public void serializeStringAsLong() + throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.registerModule( + new SimpleModule().addSerializer(Long.class, new LongSerializerStoringAsString())); + + assertThat( + MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(Long.MIN_VALUE)).unpackLong(), + is(Long.MIN_VALUE)); + } + + public static class FloatSerializerStoringAsString + extends JsonSerializer + { + @Override + public void serialize(Float value, JsonGenerator gen, SerializerProvider serializers) + throws IOException, JsonProcessingException + { + gen.writeNumber(String.valueOf(value)); + } + } + + @Test + public void serializeStringAsFloat() + throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.registerModule( + new SimpleModule().addSerializer(Float.class, new FloatSerializerStoringAsString())); + + assertThat( + MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(Float.MAX_VALUE)).unpackFloat(), + is(Float.MAX_VALUE)); + } + + public static class DoubleSerializerStoringAsString + extends JsonSerializer + { + @Override + public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) + throws IOException, JsonProcessingException + { + gen.writeNumber(String.valueOf(value)); + } + } + + @Test + public void serializeStringAsDouble() + throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.registerModule( + new SimpleModule().addSerializer(Double.class, new DoubleSerializerStoringAsString())); + + assertThat( + MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(Double.MIN_VALUE)).unpackDouble(), + is(Double.MIN_VALUE)); + } + + public static class BigDecimalSerializerStoringAsString + extends JsonSerializer + { + @Override + public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) + throws IOException, JsonProcessingException + { + gen.writeNumber(String.valueOf(value)); + } + } + + @Test + public void serializeStringAsBigDecimal() + throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.registerModule( + new SimpleModule().addSerializer(BigDecimal.class, new BigDecimalSerializerStoringAsString())); + + BigDecimal bd = BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.ONE); + assertThat( + MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(bd)).unpackDouble(), + is(bd.doubleValue())); + } + + public static class BigIntegerSerializerStoringAsString + extends JsonSerializer + { + @Override + public void serialize(BigInteger value, JsonGenerator gen, SerializerProvider serializers) + throws IOException, JsonProcessingException + { + gen.writeNumber(String.valueOf(value)); + } + } + + @Test + public void serializeStringAsBigInteger() + throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.registerModule( + new SimpleModule().addSerializer(BigInteger.class, new BigIntegerSerializerStoringAsString())); + + BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); + assertThat( + MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(bi)).unpackDouble(), + is(bi.doubleValue())); + } } From 46de775c07c3a3ae9a4b131380ab407697d63eaa Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 14 May 2017 23:38:39 +0900 Subject: [PATCH 049/417] Add tests that deserialize a string value as a number type --- .../dataformat/MessagePackParserTest.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index ffc5854be..088cd2bcb 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -780,4 +780,75 @@ public void parserShouldReadStrAsBin() assertEquals("foo", binKeyPojo.s); assertArrayEquals("bar".getBytes(), binKeyPojo.b); } + + // Test deserializers that parse a string as a number. + // Actually, com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseInteger() takes care of it. + + @Test + public void deserializeStringAsInteger() + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + MessagePack.newDefaultPacker(out).packString(String.valueOf(Integer.MAX_VALUE)).close(); + + Integer v = objectMapper.readValue(out.toByteArray(), Integer.class); + assertThat(v, is(Integer.MAX_VALUE)); + } + + @Test + public void deserializeStringAsLong() + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + MessagePack.newDefaultPacker(out).packString(String.valueOf(Long.MIN_VALUE)).close(); + + Long v = objectMapper.readValue(out.toByteArray(), Long.class); + assertThat(v, is(Long.MIN_VALUE)); + } + + @Test + public void deserializeStringAsFloat() + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + MessagePack.newDefaultPacker(out).packString(String.valueOf(Float.MAX_VALUE)).close(); + + Float v = objectMapper.readValue(out.toByteArray(), Float.class); + assertThat(v, is(Float.MAX_VALUE)); + } + + @Test + public void deserializeStringAsDouble() + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + MessagePack.newDefaultPacker(out).packString(String.valueOf(Double.MIN_VALUE)).close(); + + Double v = objectMapper.readValue(out.toByteArray(), Double.class); + assertThat(v, is(Double.MIN_VALUE)); + } + + @Test + public void deserializeStringAsBigInteger() + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); + MessagePack.newDefaultPacker(out).packString(bi.toString()).close(); + + BigInteger v = objectMapper.readValue(out.toByteArray(), BigInteger.class); + assertThat(v, is(bi)); + } + + @Test + public void deserializeStringAsBigDecimal() + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BigDecimal bd = BigDecimal.valueOf(Double.MAX_VALUE); + MessagePack.newDefaultPacker(out).packString(bd.toString()).close(); + + BigDecimal v = objectMapper.readValue(out.toByteArray(), BigDecimal.class); + assertThat(v, is(bd)); + } } From 31f4cef4135788ab1c5fe7d7f786795b811aaf62 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Mon, 15 May 2017 01:06:53 +0900 Subject: [PATCH 050/417] Remove unused import --- .../org/msgpack/jackson/dataformat/MessagePackGenerator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index 0aef84e12..988817a30 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -25,7 +25,6 @@ import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; import org.msgpack.core.buffer.OutputStreamBufferOutput; -import org.msgpack.value.FloatValue; import java.io.ByteArrayOutputStream; import java.io.IOException; From 284f4d99cdd72530b1bae089665f39ef8b62e50e Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Wed, 17 May 2017 14:08:15 +0900 Subject: [PATCH 051/417] add Java 9 test --- .travis.yml | 22 ++++++++++++++++++++++ project/build.properties | 2 +- project/plugins.sbt | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a36ab9791..ecaccfab8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,3 +21,25 @@ script: - ./sbt jcheckStyle - ./sbt test - ./sbt test -J-Dmsgpack.universal-buffer=true + +matrix: + include: + - dist: trusty + group: edge + sudo: required + jdk: oraclejdk9 + script: + # https://github.com/sbt/sbt/pull/2951 + - git clone https://github.com/retronym/java9-rt-export + - cd java9-rt-export/ + - git checkout 1019a2873d057dd7214f4135e84283695728395d + - jdk_switcher use oraclejdk8 + - sbt package + - jdk_switcher use oraclejdk9 + - mkdir -p $HOME/.sbt/0.13/java9-rt-ext; java -jar target/java9-rt-export-*.jar $HOME/.sbt/0.13/java9-rt-ext/rt.jar + - jar tf $HOME/.sbt/0.13/java9-rt-ext/rt.jar | grep java/lang/Object + - cd .. + - rm sbt + - wget https://raw.githubusercontent.com/paulp/sbt-extras/3ba0e52f32d32c0454ec3a926caae2db0caaca12/sbt && chmod +x ./sbt + - ./sbt -Dscala.ext.dirs=$HOME/.sbt/0.13/java9-rt-ext test + - ./sbt -Dscala.ext.dirs=$HOME/.sbt/0.13/java9-rt-ext -Dmsgpack.universal-buffer=true test diff --git a/project/build.properties b/project/build.properties index 24be09b28..6818e9c44 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=0.13.13 +sbt.version=0.13.15 diff --git a/project/plugins.sbt b/project/plugins.sbt index 71e5596da..f5f97360f 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -9,7 +9,7 @@ addSbtPlugin("de.johoop" % "findbugs4sbt" % "1.3.0") addSbtPlugin("de.johoop" % "jacoco4sbt" % "2.1.6") -addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.1.2") +addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.1.4") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.7.0") From 061ab997f3d406406e04a9e359e92b6eee0361e3 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 24 May 2017 19:01:56 +0900 Subject: [PATCH 052/417] Add the updates of 0.8.13 to release note --- RELEASE_NOTES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 80146d7de..5836fa72e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,10 @@ # Release Notes +## 0.8.13 + * Fix ambiguous overload in Java 9[#415](https://github.com/msgpack/msgpack-java/pull/415) + * Make MessagePackParser accept a string as a byte array field[#420](https://github.com/msgpack/msgpack-java/pull/420) + * Support MessagePackGenerator#writeNumber(String)[#422](https://github.com/msgpack/msgpack-java/pull/422) + ## 0.8.12 * Fix warnings in build.sbt[#402](https://github.com/msgpack/msgpack-java/pull/402) * Add ExtensionTypeCustomDeserializers and MessagePackFactory#setExtTypeCustomDesers[#408](https://github.com/msgpack/msgpack-java/pull/408) From dcf2b80f5c7759e986ad95bf5264ac8011dacdc3 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 24 May 2017 19:06:23 +0900 Subject: [PATCH 053/417] Update RELEASE_NOTES.md --- RELEASE_NOTES.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 5836fa72e..31b3f0619 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,14 +1,14 @@ # Release Notes ## 0.8.13 - * Fix ambiguous overload in Java 9[#415](https://github.com/msgpack/msgpack-java/pull/415) - * Make MessagePackParser accept a string as a byte array field[#420](https://github.com/msgpack/msgpack-java/pull/420) - * Support MessagePackGenerator#writeNumber(String)[#422](https://github.com/msgpack/msgpack-java/pull/422) + * Fix ambiguous overload in Java 9 [#415](https://github.com/msgpack/msgpack-java/pull/415) + * Make MessagePackParser accept a string as a byte array field [#420](https://github.com/msgpack/msgpack-java/pull/420) + * Support MessagePackGenerator#writeNumber(String) [#422](https://github.com/msgpack/msgpack-java/pull/422) ## 0.8.12 - * Fix warnings in build.sbt[#402](https://github.com/msgpack/msgpack-java/pull/402) - * Add ExtensionTypeCustomDeserializers and MessagePackFactory#setExtTypeCustomDesers[#408](https://github.com/msgpack/msgpack-java/pull/408) - * Avoid a CharsetEncoder bug of Android 4.x at MessagePacker#packString[#409](https://github.com/msgpack/msgpack-java/pull/409) + * Fix warnings in build.sbt [#402](https://github.com/msgpack/msgpack-java/pull/402) + * Add ExtensionTypeCustomDeserializers and MessagePackFactory#setExtTypeCustomDesers [#408](https://github.com/msgpack/msgpack-java/pull/408) + * Avoid a CharsetEncoder bug of Android 4.x at MessagePacker#packString [#409](https://github.com/msgpack/msgpack-java/pull/409) ## 0.8.11 * Fixed NPE when write(add)Payload are used at the beginning [#392](https://github.com/msgpack/msgpack-java/pull/392) From e047e52dbb4157181bf630a02c207c5c06a06c5c Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 24 May 2017 19:38:09 +0900 Subject: [PATCH 054/417] Setting version to 0.8.13 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 4dbb0518e..87506d86a 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.13-SNAPSHOT" \ No newline at end of file +version in ThisBuild := "0.8.13" \ No newline at end of file From 97ac3798c6b1d0084044985050fc970c1a0cc5cb Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 24 May 2017 19:39:05 +0900 Subject: [PATCH 055/417] Setting version to 0.8.14-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 87506d86a..35fa32f46 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.13" \ No newline at end of file +version in ThisBuild := "0.8.14-SNAPSHOT" \ No newline at end of file From 42a5a29200bb7ff94b63a5d15f6a31f0b650d185 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Tue, 4 Jul 2017 12:37:59 +0900 Subject: [PATCH 056/417] fix java9 build --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index ecaccfab8..f4717d59c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,10 @@ matrix: group: edge sudo: required jdk: oraclejdk9 + addons: + apt: + packages: + - oracle-java9-installer script: # https://github.com/sbt/sbt/pull/2951 - git clone https://github.com/retronym/java9-rt-export From 60ddba3cf6ec2f14bf2555f2f122892c644ad38c Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 23 Jun 2017 00:45:06 +0900 Subject: [PATCH 057/417] Fix a bug ChannelBufferInput#next blocks until the buffer is filled --- .../java/org/msgpack/core/buffer/ChannelBufferInput.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java index f00cb0c30..922e5cf08 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java @@ -62,11 +62,9 @@ public MessageBuffer next() throws IOException { ByteBuffer b = buffer.sliceAsByteBuffer(); - while (b.remaining() > 0) { - int ret = channel.read(b); - if (ret == -1) { - break; - } + int ret = channel.read(b); + if (ret == -1) { + return null; } b.flip(); return b.remaining() == 0 ? null : buffer.slice(0, b.limit()); From c52d80652cc9e10c832a463db4a4298bec5f56b8 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 24 Jun 2017 18:26:26 +0900 Subject: [PATCH 058/417] Don't need to consider the case ReadableByteChannel#read returns 0 since the buffer size must be more than 0 --- .../main/java/org/msgpack/core/buffer/ChannelBufferInput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java index 922e5cf08..e8d7c1de8 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java @@ -67,7 +67,7 @@ public MessageBuffer next() return null; } b.flip(); - return b.remaining() == 0 ? null : buffer.slice(0, b.limit()); + return buffer.slice(0, b.limit()); } @Override From 323a5c3cf268a2de07657dc99a66ce5c6d0c4b77 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 24 Jun 2017 21:30:14 +0900 Subject: [PATCH 059/417] Add a unit test --- .../core/buffer/MessageBufferInputTest.scala | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index 6b1c0da48..324448343 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -16,12 +16,17 @@ package org.msgpack.core.buffer import java.io._ +import java.net.{InetSocketAddress, ServerSocket, Socket} import java.nio.ByteBuffer +import java.nio.channels.{ServerSocketChannel, SocketChannel} +import java.util.concurrent +import java.util.concurrent.{Callable, Executors, TimeUnit} import java.util.zip.{GZIPInputStream, GZIPOutputStream} import org.msgpack.core.{MessagePack, MessagePackSpec, MessageUnpacker} import xerial.core.io.IOUtil._ +import scala.concurrent.Future import scala.util.Random class MessageBufferInputTest @@ -201,5 +206,44 @@ class MessageBufferInputTest buf.reset(in1) readInt(buf) shouldBe 42 } + + "unpack without blocking" in { + val server = ServerSocketChannel.open.bind(new InetSocketAddress("localhost", 0)) + val executorService = Executors.newCachedThreadPool + + try { + executorService.execute(new Runnable { + override def run { + val server_ch = server.accept + val packer = MessagePack.newDefaultPacker(server_ch) + packer.packString("0123456789") + packer.flush + // Keep the connection open + while (!executorService.isShutdown) { + TimeUnit.SECONDS.sleep(1) + } + packer.close + } + }) + + val future = executorService.submit(new Callable[String] { + override def call: String = { + val conn_ch = SocketChannel.open(new InetSocketAddress("localhost", server.socket.getLocalPort)) + val unpacker = MessagePack.newDefaultUnpacker(conn_ch) + val s = unpacker.unpackString + unpacker.close + s + } + }) + + future.get(5, TimeUnit.SECONDS) shouldBe "0123456789" + } + finally { + executorService.shutdown + if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { + executorService.shutdownNow + } + } + } } } From fdddf4902f8734905cc97a935d3649f08cd9c3f0 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 24 Jun 2017 22:21:08 +0900 Subject: [PATCH 060/417] Remove unused `import`s --- .../org/msgpack/core/buffer/MessageBufferInputTest.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index 324448343..a7653797e 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -16,17 +16,15 @@ package org.msgpack.core.buffer import java.io._ -import java.net.{InetSocketAddress, ServerSocket, Socket} +import java.net.{InetSocketAddress} import java.nio.ByteBuffer import java.nio.channels.{ServerSocketChannel, SocketChannel} -import java.util.concurrent import java.util.concurrent.{Callable, Executors, TimeUnit} import java.util.zip.{GZIPInputStream, GZIPOutputStream} -import org.msgpack.core.{MessagePack, MessagePackSpec, MessageUnpacker} +import org.msgpack.core.{MessagePack, MessagePackSpec} import xerial.core.io.IOUtil._ -import scala.concurrent.Future import scala.util.Random class MessageBufferInputTest From a907865b076d5a712060949ec98355fa58133241 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Tue, 4 Jul 2017 14:09:24 +0900 Subject: [PATCH 061/417] update test library dependencies --- build.sbt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build.sbt b/build.sbt index ccb366cae..344da23e1 100644 --- a/build.sbt +++ b/build.sbt @@ -6,7 +6,7 @@ val buildSettings = findbugsSettings ++ jacoco.settings ++ osgiSettings ++ Seq[S organizationName := "MessagePack", organizationHomepage := Some(new URL("http://msgpack.org/")), description := "MessagePack for Java", - scalaVersion := "2.11.7", + scalaVersion := "2.11.11", logBuffered in Test := false, autoScalaLibrary := false, crossPaths := false, @@ -91,12 +91,12 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) libraryDependencies ++= Seq( // msgpack-core should have no external dependencies junitInterface, - "org.scalatest" %% "scalatest" % "2.2.4" % "test", - "org.scalacheck" %% "scalacheck" % "1.12.2" % "test", - "org.xerial" % "xerial-core" % "3.3.6" % "test", - "org.msgpack" % "msgpack" % "0.6.11" % "test", + "org.scalatest" %% "scalatest" % "3.0.3" % "test", + "org.scalacheck" %% "scalacheck" % "1.13.5" % "test", + "org.xerial" %% "xerial-core" % "3.6.0" % "test", + "org.msgpack" % "msgpack" % "0.6.12" % "test", "commons-codec" % "commons-codec" % "1.10" % "test", - "com.typesafe.akka" %% "akka-actor" % "2.3.9" % "test" + "com.typesafe.akka" %% "akka-actor" % "2.3.16" % "test" ) ) @@ -113,7 +113,7 @@ lazy val msgpackJackson = Project(id = "msgpack-jackson", base = file("msgpack-j libraryDependencies ++= Seq( "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.1", junitInterface, - "org.apache.commons" % "commons-math3" % "3.4.1" % "test" + "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") ).dependsOn(msgpackCore) From a45ce432f585eb2211a64ddfcaa12cb81e2c71a2 Mon Sep 17 00:00:00 2001 From: "Min(Dongmin Yu)" Date: Thu, 12 Oct 2017 02:24:42 +0900 Subject: [PATCH 062/417] Improve readPayload performance --- .../org/msgpack/core/MessageUnpacker.java | 36 +++++++++++++++++-- .../msgpack/core/buffer/MessageBufferU.java | 2 +- .../msgpack/core/MessageUnpackerTest.scala | 2 +- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 82ed9d15f..019b73ff3 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -1491,6 +1491,37 @@ public void readPayload(ByteBuffer dst) } } + /** + * Reads payload bytes of binary, extension, or raw string types. + * + *

      + * This consumes bytes, copies them to the specified buffer + * This is usually faster than readPayload(ByteBuffer) by using unsafe.copyMemory + * + * @param dst the Message buffer into which the data is read + * @param off the offset in the Message buffer + * @param len the number of bytes to read + * @throws IOException when underlying input throws IOException + */ + public void readPayload(MessageBuffer dst, int off, int len) + throws IOException + { + while (true) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= len) { + dst.putMessageBuffer(off, buffer, position, len); + position += len; + return; + } + dst.putMessageBuffer(off, buffer, position, bufferRemaining); + off += bufferRemaining; + len -= bufferRemaining; + position += bufferRemaining; + + nextBuffer(); + } + } + /** * Reads payload bytes of binary, extension, or raw string types. * @@ -1541,8 +1572,7 @@ public byte[] readPayload(int length) public void readPayload(byte[] dst, int off, int len) throws IOException { - // TODO optimize - readPayload(ByteBuffer.wrap(dst, off, len)); + readPayload(MessageBuffer.wrap(dst), off, len); } /** @@ -1566,7 +1596,7 @@ public MessageBuffer readPayloadAsReference(int length) return slice; } MessageBuffer dst = MessageBuffer.allocate(length); - readPayload(dst.sliceAsByteBuffer()); + readPayload(dst, 0, length); return dst; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java index 6af9f8d7d..4369bdf3c 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java @@ -248,7 +248,7 @@ public void copyTo(int index, MessageBuffer dst, int offset, int length) @Override public void putMessageBuffer(int index, MessageBuffer src, int srcOffset, int len) { - putBytes(index, src.toByteArray(), srcOffset, len); + putByteBuffer(index, src.sliceAsByteBuffer(srcOffset, len), len); } @Override diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index db512373b..bd8e4e693 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -406,7 +406,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "be faster then msgpack-v6 skip" taggedAs ("cmp-skip") in { + "be faster than msgpack-v6 skip" taggedAs ("cmp-skip") in { trait Fixture { val unpacker: MessageUnpacker From 55c3346a0a5cf58fff361c359da7c325f2a611b2 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Fri, 13 Oct 2017 17:02:23 -0700 Subject: [PATCH 063/417] Add MessageUnpacker.tryUnpackNil() method When a code deals with an Optional value, a common way is to serialize a Nil value if the value is absent. To deserialize it, we check whether the next value is nil or not first. If it is nil, skip the byte. Otherwise, read a value. For this common use case, tryUnpackNil simplifies the deserialization code. It does "check whether the next value is nil or not first. If it is nil, skip the byte" in one method call. --- .../org/msgpack/core/MessageUnpacker.java | 27 ++++++++++++++++++- .../org/msgpack/core/MessagePackTest.scala | 13 +++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 82ed9d15f..10c6f5f44 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -389,7 +389,7 @@ private boolean ensureBuffer() public MessageFormat getNextFormat() throws IOException { - // makes sure that buffer has at leat 1 byte + // makes sure that buffer has at least 1 byte if (!ensureBuffer()) { throw new MessageInsufficientBufferException(); } @@ -731,6 +731,31 @@ public void unpackNil() throw unexpected("Nil", b); } + /** + * Peeks a Nil byte and reads it if next byte is a nil value. + * + * The difference from {@link unpackNil} is that unpackNil throws an exception if the next byte is not nil value + * while this tryUnpackNil method returns false without changing position. + * + * @return true if a nil value is read + * @throws MessageInsufficientBufferException when the end of file reached + * @throws IOException when underlying input throws IOException + */ + public boolean tryUnpackNil() + throws IOException + { + // makes sure that buffer has at least 1 byte + if (!ensureBuffer()) { + throw new MessageInsufficientBufferException(); + } + byte b = buffer.getByte(position); + if (b == Code.NIL) { + readByte(); + return true; + } + return false; + } + /** * Reads true or false. * diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 1bcf640d5..1a6893157 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -240,6 +240,19 @@ class MessagePackTest extends MessagePackSpec { check(null, _.packNil, { unpacker => unpacker.unpackNil(); null }) } + "skipping a nil value" taggedAs ("try") in { + check(true, _.packNil, _.tryUnpackNil) + check(false, { packer => packer.packString("val") }, { unpacker => unpacker.tryUnpackNil() }) + check("val", { packer => packer.packString("val") }, { unpacker => unpacker.tryUnpackNil(); unpacker.unpackString() }) + check("val", { packer => packer.packNil(); packer.packString("val") }, { unpacker => unpacker.tryUnpackNil(); unpacker.unpackString() }) + try { + checkException(null, { _ => }, _.tryUnpackNil) + } + catch { + case e: MessageInsufficientBufferException => // OK + } + } + "pack/unpack integer values" taggedAs ("int") in { val sampleData = Seq[Long](Int.MinValue.toLong - 10, -65535, -8191, -1024, -255, -127, -63, -31, -15, -7, -3, -1, 0, 2, 4, 8, 16, 32, 64, 128, 256, 1024, 8192, 65536, From 8dce150094dd2eb90dd1cdd67b71cc62f7486288 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Sun, 22 Oct 2017 17:50:27 +0900 Subject: [PATCH 064/417] remove oraclejdk7 test travis-ci no longer support oraclejdk7 - https://github.com/travis-ci/travis-ci/issues/7884#issuecomment-308451879 - http://www.webupd8.org/2017/06/why-oracle-java-7-and-6-installers-no.html --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f4717d59c..2f9c6bfb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ sudo: false jdk: - openjdk7 - - oraclejdk7 - oraclejdk8 branches: From 12e2f4c09b285480cb022f6f956a5f61f164a025 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sun, 22 Oct 2017 17:56:33 +0900 Subject: [PATCH 065/417] fix java 9 build --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f4717d59c..33e692ccf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,9 +37,8 @@ matrix: - git clone https://github.com/retronym/java9-rt-export - cd java9-rt-export/ - git checkout 1019a2873d057dd7214f4135e84283695728395d - - jdk_switcher use oraclejdk8 + - echo "sbt.version=1.0.2" > project/build.properties - sbt package - - jdk_switcher use oraclejdk9 - mkdir -p $HOME/.sbt/0.13/java9-rt-ext; java -jar target/java9-rt-export-*.jar $HOME/.sbt/0.13/java9-rt-ext/rt.jar - jar tf $HOME/.sbt/0.13/java9-rt-ext/rt.jar | grep java/lang/Object - cd .. From bccc1e1b0c8fde3c5cafb8382cad1d6f62daf810 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Nov 2017 22:09:29 -0800 Subject: [PATCH 066/417] Upgrade to sbt 1.0.4 --- build.sbt | 25 ++++++++++++------------- project/build.properties | 2 +- project/plugins.sbt | 22 +++++++++------------- 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/build.sbt b/build.sbt index 344da23e1..5609f4661 100644 --- a/build.sbt +++ b/build.sbt @@ -1,13 +1,13 @@ -import de.johoop.findbugs4sbt.ReportType import ReleaseTransformations._ -val buildSettings = findbugsSettings ++ jacoco.settings ++ osgiSettings ++ Seq[Setting[_]]( +val buildSettings = Seq[Setting[_]]( organization := "org.msgpack", organizationName := "MessagePack", organizationHomepage := Some(new URL("http://msgpack.org/")), description := "MessagePack for Java", - scalaVersion := "2.11.11", + scalaVersion := "2.12.4", logBuffered in Test := false, + // msgpack-java should be a pure-java library, so remove Scala specific configurations autoScalaLibrary := false, crossPaths := false, // For performance testing, ensure each test run one-by-one @@ -15,12 +15,12 @@ val buildSettings = findbugsSettings ++ jacoco.settings ++ osgiSettings ++ Seq[S Tags.limit(Tags.Test, 1) ), // JVM options for building - scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-target:jvm-1.6", "-feature"), + scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-target:jvm-1.7", "-feature"), javaOptions in Test ++= Seq("-ea"), - javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation", "-source", "1.6", "-target", "1.6"), + javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation", "-source", "1.7", "-target", "1.7"), // Use lenient validation mode when generating Javadoc (for Java8) javacOptions in doc := { - val opts = Seq("-source", "1.6") + val opts = Seq("-source", "1.7") if (scala.util.Properties.isJavaAtLeast("1.8")) { opts ++ Seq("-Xdoclint:none") } @@ -38,18 +38,15 @@ val buildSettings = findbugsSettings ++ jacoco.settings ++ osgiSettings ++ Seq[S setReleaseVersion, commitReleaseVersion, tagRelease, - ReleaseStep(action = Command.process("publishSigned", _)), + releaseStepCommand("publishSigned"), setNextVersion, commitNextVersion, - ReleaseStep(action = Command.process("sonatypeReleaseAll", _)), + releaseStepCommand("sonatypeReleaseAll"), pushChanges ), - // Jacoco code coverage report - parallelExecution in jacoco.Config := false, - // Find bugs - findbugsReportType := Some(ReportType.FancyHtml), + findbugsReportType := Some(FindbugsReport.FancyHtml), findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html"), // Style check config: (sbt-jchekcstyle) @@ -76,6 +73,7 @@ lazy val root = Project(id = "msgpack-java", base = file(".")) ).aggregate(msgpackCore, msgpackJackson) lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) + .enablePlugins(SbtOsgi) .settings( buildSettings, description := "Core library of the MessagePack for Java", @@ -96,11 +94,12 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.xerial" %% "xerial-core" % "3.6.0" % "test", "org.msgpack" % "msgpack" % "0.6.12" % "test", "commons-codec" % "commons-codec" % "1.10" % "test", - "com.typesafe.akka" %% "akka-actor" % "2.3.16" % "test" + "com.typesafe.akka" %% "akka-actor" % "2.5.7" % "test" ) ) lazy val msgpackJackson = Project(id = "msgpack-jackson", base = file("msgpack-jackson")) + .enablePlugins(SbtOsgi) .settings( buildSettings, name := "jackson-dataformat-msgpack", diff --git a/project/build.properties b/project/build.properties index 6818e9c44..cd928eac3 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=0.13.15 +sbt.version=1.0.4 diff --git a/project/plugins.sbt b/project/plugins.sbt index f5f97360f..85c54f812 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,16 +1,12 @@ +addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.6") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") +addSbtPlugin("com.github.sbt" % "sbt-findbugs" % "2.0.0") +addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.0.3") +addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.2") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC12") +addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.3.0") -addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.0") - -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1") - -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") - -addSbtPlugin("de.johoop" % "findbugs4sbt" % "1.3.0") - -addSbtPlugin("de.johoop" % "jacoco4sbt" % "2.1.6") - -addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.1.4") - -addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.7.0") scalacOptions ++= Seq("-deprecation", "-feature") From 2b38e70eeb2f5e73040d76c3bdd8709cdf998839 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Nov 2017 22:13:37 -0800 Subject: [PATCH 067/417] Reformat --- .scalafmt.conf | 3 + build.sbt | 140 ++++--- .../core/MessageBufferPackerTest.scala | 10 +- .../org/msgpack/core/MessageFormatTest.scala | 14 +- .../org/msgpack/core/MessagePackSpec.scala | 18 +- .../org/msgpack/core/MessagePackTest.scala | 376 ++++++++++-------- .../org/msgpack/core/MessagePackerTest.scala | 147 +++---- .../msgpack/core/MessageUnpackerTest.scala | 230 +++++------ .../msgpack/core/buffer/ByteStringTest.scala | 14 +- .../core/buffer/MessageBufferInputTest.scala | 77 ++-- .../core/buffer/MessageBufferOutputTest.scala | 16 +- .../core/buffer/MessageBufferTest.scala | 37 +- .../core/example/MessagePackExampleTest.scala | 7 +- .../value/RawStringValueImplTest.scala | 7 +- .../org/msgpack/value/ValueFactoryTest.scala | 34 +- .../scala/org/msgpack/value/ValueTest.scala | 53 ++- .../org/msgpack/value/ValueTypeTest.scala | 10 +- project/plugins.sbt | 19 +- 18 files changed, 605 insertions(+), 607 deletions(-) create mode 100644 .scalafmt.conf diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 000000000..bda502a5c --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,3 @@ +maxColumn = 180 +style = defaultWithAlign +optIn.breaksInsideChains = true diff --git a/build.sbt b/build.sbt index 5609f4661..bdeeef21a 100644 --- a/build.sbt +++ b/build.sbt @@ -23,35 +23,31 @@ val buildSettings = Seq[Setting[_]]( val opts = Seq("-source", "1.7") if (scala.util.Properties.isJavaAtLeast("1.8")) { opts ++ Seq("-Xdoclint:none") - } - else { + } else { opts } }, // Release settings releaseTagName := { (version in ThisBuild).value }, releaseProcess := Seq[ReleaseStep]( - checkSnapshotDependencies, - inquireVersions, - runClean, - runTest, - setReleaseVersion, - commitReleaseVersion, - tagRelease, - releaseStepCommand("publishSigned"), - setNextVersion, - commitNextVersion, - releaseStepCommand("sonatypeReleaseAll"), - pushChanges - ), - + checkSnapshotDependencies, + inquireVersions, + runClean, + runTest, + setReleaseVersion, + commitReleaseVersion, + tagRelease, + releaseStepCommand("publishSigned"), + setNextVersion, + commitNextVersion, + releaseStepCommand("sonatypeReleaseAll"), + pushChanges + ), // Find bugs findbugsReportType := Some(FindbugsReport.FancyHtml), findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html"), - // Style check config: (sbt-jchekcstyle) jcheckStyleConfig := "facebook", - // Run jcheckstyle both for main and test codes (compile in Compile) := ((compile in Compile) dependsOn (jcheckStyle in Compile)).value, (compile in Test) := ((compile in Test) dependsOn (jcheckStyle in Test)).value @@ -61,59 +57,61 @@ val junitInterface = "com.novocode" % "junit-interface" % "0.11" % "test" // Project settings lazy val root = Project(id = "msgpack-java", base = file(".")) - .settings( - buildSettings, - // Do not publish the root project - publishArtifact := false, - publish := {}, - publishLocal := {}, - findbugs := { - // do not run findbugs for the root project - } - ).aggregate(msgpackCore, msgpackJackson) + .settings( + buildSettings, + // Do not publish the root project + publishArtifact := false, + publish := {}, + publishLocal := {}, + findbugs := { + // do not run findbugs for the root project + } + ) + .aggregate(msgpackCore, msgpackJackson) lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) - .enablePlugins(SbtOsgi) - .settings( - buildSettings, - description := "Core library of the MessagePack for Java", - OsgiKeys.bundleSymbolicName := "org.msgpack.msgpack-core", - OsgiKeys.exportPackage := Seq( - // TODO enumerate used packages automatically - "org.msgpack.core", - "org.msgpack.core.annotations", - "org.msgpack.core.buffer", - "org.msgpack.value", - "org.msgpack.value.impl" - ), - libraryDependencies ++= Seq( - // msgpack-core should have no external dependencies - junitInterface, - "org.scalatest" %% "scalatest" % "3.0.3" % "test", - "org.scalacheck" %% "scalacheck" % "1.13.5" % "test", - "org.xerial" %% "xerial-core" % "3.6.0" % "test", - "org.msgpack" % "msgpack" % "0.6.12" % "test", - "commons-codec" % "commons-codec" % "1.10" % "test", - "com.typesafe.akka" %% "akka-actor" % "2.5.7" % "test" - ) - ) - -lazy val msgpackJackson = Project(id = "msgpack-jackson", base = file("msgpack-jackson")) - .enablePlugins(SbtOsgi) - .settings( - buildSettings, - name := "jackson-dataformat-msgpack", - description := "Jackson extension that adds support for MessagePack", - OsgiKeys.bundleSymbolicName := "org.msgpack.msgpack-jackson", - OsgiKeys.exportPackage := Seq( - "org.msgpack.jackson", - "org.msgpack.jackson.dataformat" - ), - libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.1", - junitInterface, - "org.apache.commons" % "commons-math3" % "3.6.1" % "test" - ), - testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") - ).dependsOn(msgpackCore) + .enablePlugins(SbtOsgi) + .settings( + buildSettings, + description := "Core library of the MessagePack for Java", + OsgiKeys.bundleSymbolicName := "org.msgpack.msgpack-core", + OsgiKeys.exportPackage := Seq( + // TODO enumerate used packages automatically + "org.msgpack.core", + "org.msgpack.core.annotations", + "org.msgpack.core.buffer", + "org.msgpack.value", + "org.msgpack.value.impl" + ), + libraryDependencies ++= Seq( + // msgpack-core should have no external dependencies + junitInterface, + "org.scalatest" %% "scalatest" % "3.0.3" % "test", + "org.scalacheck" %% "scalacheck" % "1.13.5" % "test", + "org.xerial" %% "xerial-core" % "3.6.0" % "test", + "org.msgpack" % "msgpack" % "0.6.12" % "test", + "commons-codec" % "commons-codec" % "1.10" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.5.7" % "test" + ) + ) +lazy val msgpackJackson = + Project(id = "msgpack-jackson", base = file("msgpack-jackson")) + .enablePlugins(SbtOsgi) + .settings( + buildSettings, + name := "jackson-dataformat-msgpack", + description := "Jackson extension that adds support for MessagePack", + OsgiKeys.bundleSymbolicName := "org.msgpack.msgpack-jackson", + OsgiKeys.exportPackage := Seq( + "org.msgpack.jackson", + "org.msgpack.jackson.dataformat" + ), + libraryDependencies ++= Seq( + "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.1", + junitInterface, + "org.apache.commons" % "commons-math3" % "3.6.1" % "test" + ), + testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") + ) + .dependsOn(msgpackCore) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala index 2f7639d61..b8d2bd691 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala @@ -23,15 +23,11 @@ class MessageBufferPackerTest extends MessagePackSpec { "MessageBufferPacker" should { "be equivalent to ByteArrayOutputStream" in { val packer1 = MessagePack.newDefaultBufferPacker - packer1.packValue(newMap( - newString("a"), newInteger(1), - newString("b"), newString("s"))) + packer1.packValue(newMap(newString("a"), newInteger(1), newString("b"), newString("s"))) - val stream = new ByteArrayOutputStream + val stream = new ByteArrayOutputStream val packer2 = MessagePack.newDefaultPacker(stream) - packer2.packValue(newMap( - newString("a"), newInteger(1), - newString("b"), newString("s"))) + packer2.packValue(newMap(newString("a"), newInteger(1), newString("b"), newString("s"))) packer2.flush packer1.toByteArray shouldBe stream.toByteArray diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala index be9d270cd..e7e9a4c36 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala @@ -22,15 +22,13 @@ import org.scalatest.exceptions.TestFailedException import scala.util.Random /** - * Created on 2014/05/07. - */ -class MessageFormatTest - extends MessagePackSpec { + * Created on 2014/05/07. + */ +class MessageFormatTest extends MessagePackSpec { "MessageFormat" should { "cover all byte codes" in { def checkV(b: Byte, tpe: ValueType) { - try - MessageFormat.valueOf(b).getValueType shouldBe tpe + try MessageFormat.valueOf(b).getValueType shouldBe tpe catch { case e: TestFailedException => error(f"Failure when looking at byte ${b}%02x") @@ -80,7 +78,6 @@ class MessageFormatTest check(Code.EXT16, ValueType.EXTENSION, MessageFormat.EXT16) check(Code.EXT32, ValueType.EXTENSION, MessageFormat.EXT32) - check(Code.INT8, ValueType.INTEGER, MessageFormat.INT8) check(Code.INT16, ValueType.INTEGER, MessageFormat.INT16) check(Code.INT32, ValueType.INTEGER, MessageFormat.INT32) @@ -94,7 +91,6 @@ class MessageFormatTest check(Code.STR16, ValueType.STRING, MessageFormat.STR16) check(Code.STR32, ValueType.STRING, MessageFormat.STR32) - check(Code.FLOAT32, ValueType.FLOAT, MessageFormat.FLOAT32) check(Code.FLOAT64, ValueType.FLOAT, MessageFormat.FLOAT64) @@ -107,7 +103,7 @@ class MessageFormatTest } "improve the valueOf performance" in { - val N = 1000000 + val N = 1000000 val idx = (0 until N).map(x => Random.nextInt(256).toByte).toArray[Byte] // Initialize diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala index b8be3bed0..468468c17 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala @@ -24,23 +24,14 @@ import xerial.core.util.{TimeReport, Timer} import scala.language.implicitConversions -trait MessagePackSpec - extends WordSpec - with Matchers - with GivenWhenThen - with OptionValues - with BeforeAndAfter - with PropertyChecks - with Benchmark - with Logger { +trait MessagePackSpec extends WordSpec with Matchers with GivenWhenThen with OptionValues with BeforeAndAfter with PropertyChecks with Benchmark with Logger { implicit def toTag(s: String): Tag = Tag(s) def toHex(arr: Array[Byte]) = arr.map(x => f"$x%02x").mkString(" ") def createMessagePackData(f: MessagePacker => Unit): Array[Byte] = { - val b = new - ByteArrayOutputStream() + val b = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(b) f(packer) packer.close() @@ -48,8 +39,7 @@ trait MessagePackSpec } } -trait Benchmark - extends Timer { +trait Benchmark extends Timer { val numWarmUpRuns = 10 @@ -66,4 +56,4 @@ trait Benchmark super.block(name, repeat)(f) } -} \ No newline at end of file +} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 1a6893157..f6b41bf34 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -27,8 +27,8 @@ import org.msgpack.value.{Value, Variable} import scala.util.Random /** - * Created on 2014/05/07. - */ + * Created on 2014/05/07. + */ class MessagePackTest extends MessagePackSpec { def isValidUTF8(s: String) = { @@ -37,10 +37,12 @@ class MessagePackTest extends MessagePackSpec { def containsUnmappableCharacter(s: String): Boolean = { try { - MessagePack.UTF8.newEncoder().onUnmappableCharacter(CodingErrorAction.REPORT).encode(CharBuffer.wrap(s)) + MessagePack.UTF8 + .newEncoder() + .onUnmappableCharacter(CodingErrorAction.REPORT) + .encode(CharBuffer.wrap(s)) false - } - catch { + } catch { case e: UnmappableCharacterException => true case _: Exception => false @@ -50,7 +52,10 @@ class MessagePackTest extends MessagePackSpec { "MessagePack" should { "clone packer config" in { - val config = new PackerConfig().withBufferSize(10).withBufferFlushThreshold(32 * 1024).withSmallStringOptimizationThreshold(142) + val config = new PackerConfig() + .withBufferSize(10) + .withBufferFlushThreshold(32 * 1024) + .withSmallStringOptimizationThreshold(142) val copy = config.clone() copy shouldBe config @@ -58,18 +63,17 @@ class MessagePackTest extends MessagePackSpec { "clone unpacker config" in { val config = new UnpackerConfig() - .withBufferSize(1) - .withActionOnMalformedString(CodingErrorAction.IGNORE) - .withActionOnUnmappableString(CodingErrorAction.REPORT) - .withAllowReadingBinaryAsString(false) - .withStringDecoderBufferSize(34) - .withStringSizeLimit(4324) + .withBufferSize(1) + .withActionOnMalformedString(CodingErrorAction.IGNORE) + .withActionOnUnmappableString(CodingErrorAction.REPORT) + .withAllowReadingBinaryAsString(false) + .withStringDecoderBufferSize(34) + .withStringSizeLimit(4324) val copy = config.clone() copy shouldBe config } - "detect fixint values" in { for (i <- 0 until 0x79) { @@ -90,8 +94,7 @@ class MessagePackTest extends MessagePackSpec { try { MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() fail("Shouldn't reach here") - } - catch { + } catch { case e: MessageTypeException => // OK } } @@ -105,21 +108,20 @@ class MessagePackTest extends MessagePackSpec { try { MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() fail("Shouldn't reach here") - } - catch { + } catch { case e: MessageTypeException => // OK } } "detect fixint quickly" in { - val N = 100000 + val N = 100000 val idx = (0 until N).map(x => Random.nextInt(256).toByte).toArray[Byte] time("check fixint", repeat = 100) { block("mask") { - var i = 0 + var i = 0 var count = 0 while (i < N) { if ((idx(i) & Code.POSFIXINT_MASK) == 0) { @@ -130,7 +132,7 @@ class MessagePackTest extends MessagePackSpec { } block("mask in func") { - var i = 0 + var i = 0 var count = 0 while (i < N) { if (Code.isPosFixInt(idx(i))) { @@ -141,7 +143,7 @@ class MessagePackTest extends MessagePackSpec { } block("shift cmp") { - var i = 0 + var i = 0 var count = 0 while (i < N) { if ((idx(i) >>> 7) == 0) { @@ -168,17 +170,16 @@ class MessagePackTest extends MessagePackSpec { } - def check[A]( - v: A, - pack: MessagePacker => Unit, - unpack: MessageUnpacker => A, - packerConfig: PackerConfig = new PackerConfig(), - unpackerConfig: UnpackerConfig = new UnpackerConfig() + v: A, + pack: MessagePacker => Unit, + unpack: MessageUnpacker => A, + packerConfig: PackerConfig = new PackerConfig(), + unpackerConfig: UnpackerConfig = new UnpackerConfig() ): Unit = { var b: Array[Byte] = null try { - val bs = new ByteArrayOutputStream() + val bs = new ByteArrayOutputStream() val packer = packerConfig.newPacker(bs) pack(packer) packer.close() @@ -186,10 +187,9 @@ class MessagePackTest extends MessagePackSpec { b = bs.toByteArray val unpacker = unpackerConfig.newUnpacker(b) - val ret = unpack(unpacker) + val ret = unpack(unpacker) ret shouldBe v - } - catch { + } catch { case e: Exception => warn(e.getMessage) if (b != null) { @@ -200,22 +200,22 @@ class MessagePackTest extends MessagePackSpec { } def checkException[A]( - v: A, - pack: MessagePacker => Unit, - unpack: MessageUnpacker => A, - packerConfig: PackerConfig = new PackerConfig(), - unpaackerConfig: UnpackerConfig = new UnpackerConfig() + v: A, + pack: MessagePacker => Unit, + unpack: MessageUnpacker => A, + packerConfig: PackerConfig = new PackerConfig(), + unpaackerConfig: UnpackerConfig = new UnpackerConfig() ): Unit = { var b: Array[Byte] = null - val bs = new ByteArrayOutputStream() - val packer = packerConfig.newPacker(bs) + val bs = new ByteArrayOutputStream() + val packer = packerConfig.newPacker(bs) pack(packer) packer.close() b = bs.toByteArray val unpacker = unpaackerConfig.newUnpacker(b) - val ret = unpack(unpacker) + val ret = unpack(unpacker) fail("cannot not reach here") } @@ -223,64 +223,111 @@ class MessagePackTest extends MessagePackSpec { def checkOverflow[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A) { try { checkException[A](v, pack, unpack) - } - catch { + } catch { case e: MessageIntegerOverflowException => // OK } } "pack/unpack primitive values" taggedAs ("prim") in { - forAll { (v: Boolean) => check(v, _.packBoolean(v), _.unpackBoolean) } - forAll { (v: Byte) => check(v, _.packByte(v), _.unpackByte) } - forAll { (v: Short) => check(v, _.packShort(v), _.unpackShort) } - forAll { (v: Int) => check(v, _.packInt(v), _.unpackInt) } - forAll { (v: Float) => check(v, _.packFloat(v), _.unpackFloat) } - forAll { (v: Long) => check(v, _.packLong(v), _.unpackLong) } - forAll { (v: Double) => check(v, _.packDouble(v), _.unpackDouble) } - check(null, _.packNil, { unpacker => unpacker.unpackNil(); null }) + forAll { (v: Boolean) => + check(v, _.packBoolean(v), _.unpackBoolean) + } + forAll { (v: Byte) => + check(v, _.packByte(v), _.unpackByte) + } + forAll { (v: Short) => + check(v, _.packShort(v), _.unpackShort) + } + forAll { (v: Int) => + check(v, _.packInt(v), _.unpackInt) + } + forAll { (v: Float) => + check(v, _.packFloat(v), _.unpackFloat) + } + forAll { (v: Long) => + check(v, _.packLong(v), _.unpackLong) + } + forAll { (v: Double) => + check(v, _.packDouble(v), _.unpackDouble) + } + check(null, _.packNil, { unpacker => + unpacker.unpackNil(); null + }) } "skipping a nil value" taggedAs ("try") in { check(true, _.packNil, _.tryUnpackNil) - check(false, { packer => packer.packString("val") }, { unpacker => unpacker.tryUnpackNil() }) - check("val", { packer => packer.packString("val") }, { unpacker => unpacker.tryUnpackNil(); unpacker.unpackString() }) - check("val", { packer => packer.packNil(); packer.packString("val") }, { unpacker => unpacker.tryUnpackNil(); unpacker.unpackString() }) + check(false, { packer => + packer.packString("val") + }, { unpacker => + unpacker.tryUnpackNil() + }) + check("val", { packer => + packer.packString("val") + }, { unpacker => + unpacker.tryUnpackNil(); unpacker.unpackString() + }) + check("val", { packer => + packer.packNil(); packer.packString("val") + }, { unpacker => + unpacker.tryUnpackNil(); unpacker.unpackString() + }) try { - checkException(null, { _ => }, _.tryUnpackNil) - } - catch { + checkException(null, { _ => + }, _.tryUnpackNil) + } catch { case e: MessageInsufficientBufferException => // OK } } "pack/unpack integer values" taggedAs ("int") in { val sampleData = Seq[Long](Int.MinValue.toLong - - 10, -65535, -8191, -1024, -255, -127, -63, -31, -15, -7, -3, -1, 0, 2, 4, 8, 16, 32, 64, 128, 256, 1024, 8192, 65536, - Int.MaxValue.toLong + 10) + 10, + -65535, + -8191, + -1024, + -255, + -127, + -63, + -31, + -15, + -7, + -3, + -1, + 0, + 2, + 4, + 8, + 16, + 32, + 64, + 128, + 256, + 1024, + 8192, + 65536, + Int.MaxValue.toLong + 10) for (v <- sampleData) { check(v, _.packLong(v), _.unpackLong) if (v.isValidInt) { val vi = v.toInt check(vi, _.packInt(vi), _.unpackInt) - } - else { + } else { checkOverflow(v, _.packLong(v), _.unpackInt) } if (v.isValidShort) { val vi = v.toShort check(vi, _.packShort(vi), _.unpackShort) - } - else { + } else { checkOverflow(v, _.packLong(v), _.unpackShort) } if (v.isValidByte) { val vi = v.toByte check(vi, _.packByte(vi), _.unpackByte) - } - else { + } else { checkOverflow(v, _.packLong(v), _.unpackByte) } @@ -302,8 +349,7 @@ class MessagePackTest extends MessagePackSpec { try { checkException(bi, _.packBigInteger(bi), _.unpackBigInteger()) fail("cannot reach here") - } - catch { + } catch { case e: IllegalArgumentException => // OK } } @@ -323,31 +369,32 @@ class MessagePackTest extends MessagePackSpec { // Large string val strLen = Seq(1000, 2000, 10000, 50000, 100000, 500000) for (l <- strLen) { - val v: String = Iterator.continually(Random.nextString(l * 10)).find(isValidUTF8).get + val v: String = + Iterator.continually(Random.nextString(l * 10)).find(isValidUTF8).get check(v, _.packString(v), _.unpackString) } } - "report errors when packing/unpacking malformed strings" taggedAs ("malformed") in { // TODO produce malformed utf-8 strings in Java8" pending // Create 100 malformed UTF8 Strings val r = new Random(0) - val malformedStrings = Iterator.continually { - val b = new Array[Byte](10) - r.nextBytes(b) - b - } - .filter(b => !isValidUTF8(new String(b))).take(100) + val malformedStrings = Iterator + .continually { + val b = new Array[Byte](10) + r.nextBytes(b) + b + } + .filter(b => !isValidUTF8(new String(b))) + .take(100) for (malformedBytes <- malformedStrings) { // Pack tests val malformed = new String(malformedBytes) try { checkException(malformed, _.packString(malformed), _.unpackString()) - } - catch { + } catch { case e: MessageStringCodingException => // OK } @@ -355,10 +402,8 @@ class MessagePackTest extends MessagePackSpec { checkException(malformed, { packer => packer.packRawStringHeader(malformedBytes.length) packer.writePayload(malformedBytes) - }, - _.unpackString()) - } - catch { + }, _.unpackString()) + } catch { case e: MessageStringCodingException => // OK } } @@ -371,8 +416,8 @@ class MessagePackTest extends MessagePackSpec { // Report error on unmappable character val unpackerConfig = new UnpackerConfig() - .withActionOnMalformedString(CodingErrorAction.REPORT) - .withActionOnUnmappableString(CodingErrorAction.REPORT) + .withActionOnMalformedString(CodingErrorAction.REPORT) + .withActionOnUnmappableString(CodingErrorAction.REPORT) for (bytes <- Seq(unmappable)) { When("unpacking") @@ -380,26 +425,24 @@ class MessagePackTest extends MessagePackSpec { checkException(bytes, { packer => packer.packRawStringHeader(bytes.length) packer.writePayload(bytes) - }, - _.unpackString(), - new PackerConfig(), - unpackerConfig) - } - catch { + }, _.unpackString(), new PackerConfig(), unpackerConfig) + } catch { case e: MessageStringCodingException => // OK } } } - "pack/unpack binary" taggedAs ("binary") in { forAll { (v: Array[Byte]) => - check(v, { packer => packer.packBinaryHeader(v.length); packer.writePayload(v) }, { unpacker => - val len = unpacker.unpackBinaryHeader() - val out = new Array[Byte](len) - unpacker.readPayload(out, 0, len) - out - } + check( + v, { packer => + packer.packBinaryHeader(v.length); packer.writePayload(v) + }, { unpacker => + val len = unpacker.unpackBinaryHeader() + val out = new Array[Byte](len) + unpacker.readPayload(out, 0, len) + out + } ) } @@ -407,32 +450,35 @@ class MessagePackTest extends MessagePackSpec { for (l <- len) { val v = new Array[Byte](l) Random.nextBytes(v) - check(v, { packer => packer.packBinaryHeader(v.length); packer.writePayload(v) }, { unpacker => - val len = unpacker.unpackBinaryHeader() - val out = new Array[Byte](len) - unpacker.readPayload(out, 0, len) - out - } + check( + v, { packer => + packer.packBinaryHeader(v.length); packer.writePayload(v) + }, { unpacker => + val len = unpacker.unpackBinaryHeader() + val out = new Array[Byte](len) + unpacker.readPayload(out, 0, len) + out + } ) } } val testHeaderLength = Seq(1, 2, 4, 8, 16, 17, 32, 64, 255, 256, 1000, 2000, 10000, 50000, 100000, 500000) - "pack/unpack arrays" taggedAs ("array") in { forAll { (v: Array[Int]) => - check(v, { packer => - packer.packArrayHeader(v.length) - v.map(packer.packInt(_)) - }, { unpacker => - val len = unpacker.unpackArrayHeader() - val out = new Array[Int](len) - for (i <- 0 until v.length) { - out(i) = unpacker.unpackInt + check( + v, { packer => + packer.packArrayHeader(v.length) + v.map(packer.packInt(_)) + }, { unpacker => + val len = unpacker.unpackArrayHeader() + val out = new Array[Int](len) + for (i <- 0 until v.length) { + out(i) = unpacker.unpackInt + } + out } - out - } ) } @@ -442,8 +488,7 @@ class MessagePackTest extends MessagePackSpec { try { checkException(0, _.packArrayHeader(-1), _.unpackArrayHeader) - } - catch { + } catch { case e: IllegalArgumentException => // OK } @@ -451,23 +496,24 @@ class MessagePackTest extends MessagePackSpec { "pack/unpack maps" taggedAs ("map") in { forAll { (v: Array[Int]) => - val m = v.map(i => (i, i.toString)) - check(m, { packer => - packer.packMapHeader(v.length) - m.map { case (k: Int, v: String) => - packer.packInt(k) - packer.packString(v) - } - }, { unpacker => - val len = unpacker.unpackMapHeader() - val b = Seq.newBuilder[(Int, String)] - for (i <- 0 until len) { - b += ((unpacker.unpackInt, unpacker.unpackString)) + check( + m, { packer => + packer.packMapHeader(v.length) + m.map { + case (k: Int, v: String) => + packer.packInt(k) + packer.packString(v) + } + }, { unpacker => + val len = unpacker.unpackMapHeader() + val b = Seq.newBuilder[(Int, String)] + for (i <- 0 until len) { + b += ((unpacker.unpackInt, unpacker.unpackString)) + } + b.result } - b.result - } ) } @@ -477,19 +523,18 @@ class MessagePackTest extends MessagePackSpec { try { checkException(0, _.packMapHeader(-1), _.unpackMapHeader) - } - catch { + } catch { case e: IllegalArgumentException => // OK } - } "pack/unpack extension types" taggedAs ("ext") in { forAll { (dataLen: Int, tpe: Byte) => val l = Math.abs(dataLen) whenever(l >= 0) { - val ext = new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(tpe), l) + val ext = + new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(tpe), l) check(ext, _.packExtensionTypeHeader(ext.getType, ext.getLength), _.unpackExtensionTypeHeader()) } } @@ -504,31 +549,38 @@ class MessagePackTest extends MessagePackSpec { "pack/unpack maps in lists" in { val aMap = List(Map("f" -> "x")) - check(aMap, { packer => - packer.packArrayHeader(aMap.size) - for (m <- aMap) { - packer.packMapHeader(m.size) - for ((k, v) <- m) { - packer.packString(k) - packer.packString(v) + check( + aMap, { packer => + packer.packArrayHeader(aMap.size) + for (m <- aMap) { + packer.packMapHeader(m.size) + for ((k, v) <- m) { + packer.packString(k) + packer.packString(v) + } } + }, { unpacker => + val v = new Variable() + unpacker.unpackValue(v) + import scala.collection.JavaConversions._ + v.asArrayValue() + .map { m => + val mv = m.asMapValue() + val kvs = mv.getKeyValueArray + + kvs + .grouped(2) + .map({ kvp: Array[Value] => + val k = kvp(0) + val v = kvp(1) + + (k.asStringValue().asString, v.asStringValue().asString) + }) + .toMap + } + .toList } - }, { unpacker => - val v = new Variable() - unpacker.unpackValue(v) - import scala.collection.JavaConversions._ - v.asArrayValue().map { m => - val mv = m.asMapValue() - val kvs = mv.getKeyValueArray - - kvs.grouped(2).map({ kvp: Array[Value] => - val k = kvp(0) - val v = kvp(1) - - (k.asStringValue().asString, v.asStringValue().asString) - }).toMap - }.toList - }) + ) } } @@ -536,7 +588,7 @@ class MessagePackTest extends MessagePackSpec { "MessagePack.PackerConfig" should { "be immutable" in { val a = new MessagePack.PackerConfig() - val b = a.withBufferSize(64*1024) + val b = a.withBufferSize(64 * 1024) a.equals(b) shouldBe false } @@ -544,16 +596,16 @@ class MessagePackTest extends MessagePackSpec { val a = new MessagePack.PackerConfig() val b = new MessagePack.PackerConfig() a.equals(b) shouldBe true - a.withBufferSize(64*1024).equals(b) shouldBe false + a.withBufferSize(64 * 1024).equals(b) shouldBe false a.withSmallStringOptimizationThreshold(64).equals(b) shouldBe false - a.withBufferFlushThreshold(64*1024).equals(b) shouldBe false + a.withBufferFlushThreshold(64 * 1024).equals(b) shouldBe false } } "MessagePack.UnpackerConfig" should { "be immutable" in { val a = new MessagePack.UnpackerConfig() - val b = a.withBufferSize(64*1024) + val b = a.withBufferSize(64 * 1024) a.equals(b) shouldBe false } @@ -561,11 +613,13 @@ class MessagePackTest extends MessagePackSpec { val a = new MessagePack.UnpackerConfig() val b = new MessagePack.UnpackerConfig() a.equals(b) shouldBe true - a.withBufferSize(64*1024).equals(b) shouldBe false + a.withBufferSize(64 * 1024).equals(b) shouldBe false a.withAllowReadingStringAsBinary(false).equals(b) shouldBe false a.withAllowReadingBinaryAsString(false).equals(b) shouldBe false - a.withActionOnMalformedString(CodingErrorAction.REPORT).equals(b) shouldBe false - a.withActionOnUnmappableString(CodingErrorAction.REPORT).equals(b) shouldBe false + a.withActionOnMalformedString(CodingErrorAction.REPORT) + .equals(b) shouldBe false + a.withActionOnUnmappableString(CodingErrorAction.REPORT) + .equals(b) shouldBe false a.withStringSizeLimit(32).equals(b) shouldBe false a.withStringDecoderBufferSize(32).equals(b) shouldBe false } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index c64f6f972..5024963fd 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -25,13 +25,13 @@ import xerial.core.io.IOUtil import scala.util.Random /** - * - */ + * + */ class MessagePackerTest extends MessagePackSpec { def verifyIntSeq(answer: Array[Int], packed: Array[Byte]) { val unpacker = MessagePack.newDefaultUnpacker(packed) - val b = Array.newBuilder[Int] + val b = Array.newBuilder[Int] while (unpacker.hasNext) { b += unpacker.unpackInt() } @@ -47,15 +47,14 @@ class MessagePackerTest extends MessagePackSpec { } def createTempFileWithOutputStream = { - val f = createTempFile - val out = new - FileOutputStream(f) + val f = createTempFile + val out = new FileOutputStream(f) (f, out) } def createTempFileWithChannel = { val (f, out) = createTempFileWithOutputStream - val ch = out.getChannel + val ch = out.getChannel (f, ch) } @@ -64,29 +63,24 @@ class MessagePackerTest extends MessagePackSpec { "reset the internal states" in { val intSeq = (0 until 100).map(i => Random.nextInt).toArray - val b = new - ByteArrayOutputStream + val b = new ByteArrayOutputStream val packer = MessagePack.newDefaultPacker(b) intSeq foreach packer.packInt packer.close verifyIntSeq(intSeq, b.toByteArray) val intSeq2 = intSeq.reverse - val b2 = new - ByteArrayOutputStream + val b2 = new ByteArrayOutputStream packer - .reset(new - OutputStreamBufferOutput(b2)) + .reset(new OutputStreamBufferOutput(b2)) intSeq2 foreach packer.packInt packer.close verifyIntSeq(intSeq2, b2.toByteArray) val intSeq3 = intSeq2.sorted - val b3 = new - ByteArrayOutputStream + val b3 = new ByteArrayOutputStream packer - .reset(new - OutputStreamBufferOutput(b3)) + .reset(new OutputStreamBufferOutput(b3)) intSeq3 foreach packer.packInt packer.close verifyIntSeq(intSeq3, b3.toByteArray) @@ -97,15 +91,12 @@ class MessagePackerTest extends MessagePackSpec { val N = 1000 val t = time("packer", repeat = 10) { block("no-buffer-reset") { - val out = new - ByteArrayOutputStream + val out = new ByteArrayOutputStream IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => for (i <- 0 until N) { - val outputStream = new - ByteArrayOutputStream() + val outputStream = new ByteArrayOutputStream() packer - .reset(new - OutputStreamBufferOutput(outputStream)) + .reset(new OutputStreamBufferOutput(outputStream)) packer.packInt(0) packer.flush() } @@ -113,15 +104,12 @@ class MessagePackerTest extends MessagePackSpec { } block("buffer-reset") { - val out = new - ByteArrayOutputStream + val out = new ByteArrayOutputStream IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => - val bufferOut = new - OutputStreamBufferOutput(new - ByteArrayOutputStream()) + val bufferOut = + new OutputStreamBufferOutput(new ByteArrayOutputStream()) for (i <- 0 until N) { - val outputStream = new - ByteArrayOutputStream() + val outputStream = new ByteArrayOutputStream() bufferOut.reset(outputStream) packer.reset(bufferOut) packer.packInt(0) @@ -138,11 +126,11 @@ class MessagePackerTest extends MessagePackSpec { // Based on https://github.com/msgpack/msgpack-java/issues/154 def test(bufferSize: Int, stringSize: Int): Boolean = { - val str = "a" * stringSize + val str = "a" * stringSize val rawString = ValueFactory.newString(str.getBytes("UTF-8")) - val array = ValueFactory.newArray(rawString) - val out = new ByteArrayOutputStream(bufferSize) - val packer = MessagePack.newDefaultPacker(out) + val array = ValueFactory.newArray(rawString) + val out = new ByteArrayOutputStream(bufferSize) + val packer = MessagePack.newDefaultPacker(out) packer.packValue(array) packer.close() out.toByteArray @@ -162,32 +150,28 @@ class MessagePackerTest extends MessagePackSpec { "reset OutputStreamBufferOutput" in { val (f0, out0) = createTempFileWithOutputStream - val packer = MessagePack.newDefaultPacker(out0) + val packer = MessagePack.newDefaultPacker(out0) packer.packInt(99) packer.close val up0 = MessagePack - .newDefaultUnpacker(new - FileInputStream(f0)) + .newDefaultUnpacker(new FileInputStream(f0)) up0.unpackInt shouldBe 99 up0.hasNext shouldBe false up0.close val (f1, out1) = createTempFileWithOutputStream packer - .reset(new - OutputStreamBufferOutput(out1)) + .reset(new OutputStreamBufferOutput(out1)) packer.packInt(99) packer.flush packer - .reset(new - OutputStreamBufferOutput(out1)) + .reset(new OutputStreamBufferOutput(out1)) packer.packString("hello") packer.close val up1 = MessagePack - .newDefaultUnpacker(new - FileInputStream(f1)) + .newDefaultUnpacker(new FileInputStream(f1)) up1.unpackInt shouldBe 99 up1.unpackString shouldBe "hello" up1.hasNext shouldBe false @@ -196,32 +180,28 @@ class MessagePackerTest extends MessagePackSpec { "reset ChannelBufferOutput" in { val (f0, out0) = createTempFileWithChannel - val packer = MessagePack.newDefaultPacker(out0) + val packer = MessagePack.newDefaultPacker(out0) packer.packInt(99) packer.close val up0 = MessagePack - .newDefaultUnpacker(new - FileInputStream(f0)) + .newDefaultUnpacker(new FileInputStream(f0)) up0.unpackInt shouldBe 99 up0.hasNext shouldBe false up0.close val (f1, out1) = createTempFileWithChannel packer - .reset(new - ChannelBufferOutput(out1)) + .reset(new ChannelBufferOutput(out1)) packer.packInt(99) packer.flush packer - .reset(new - ChannelBufferOutput(out1)) + .reset(new ChannelBufferOutput(out1)) packer.packString("hello") packer.close val up1 = MessagePack - .newDefaultUnpacker(new - FileInputStream(f1)) + .newDefaultUnpacker(new FileInputStream(f1)) up1.unpackInt shouldBe 99 up1.unpackString shouldBe "hello" up1.hasNext shouldBe false @@ -233,10 +213,10 @@ class MessagePackerTest extends MessagePackSpec { def measureDuration(outputStream: java.io.OutputStream) = { val packer = MessagePack.newDefaultPacker(outputStream) - var i = 0 + var i = 0 while (i < count) { packer.packString("0123456789ABCDEF") - i += 1 + i += 1 } packer.close } @@ -251,33 +231,34 @@ class MessagePackerTest extends MessagePackSpec { measureDuration(fileOutput) } } - t("file-output-stream").averageWithoutMinMax shouldBe < (t("byte-array-output-stream").averageWithoutMinMax * 5) + t("file-output-stream").averageWithoutMinMax shouldBe <(t("byte-array-output-stream").averageWithoutMinMax * 5) } } "compute totalWrittenBytes" in { - val out = new - ByteArrayOutputStream - val packerTotalWrittenBytes = IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => - packer.packByte(0) // 1 - .packBoolean(true) // 1 - .packShort(12) // 1 - .packInt(1024) // 3 - .packLong(Long.MaxValue) // 5 - .packString("foobar") // 7 - .flush() - - packer.getTotalWrittenBytes - } + val out = new ByteArrayOutputStream + val packerTotalWrittenBytes = + IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => + packer + .packByte(0) // 1 + .packBoolean(true) // 1 + .packShort(12) // 1 + .packInt(1024) // 3 + .packLong(Long.MaxValue) // 5 + .packString("foobar") // 7 + .flush() + + packer.getTotalWrittenBytes + } out.toByteArray.length shouldBe packerTotalWrittenBytes } "support read-only buffer" taggedAs ("read-only") in { val payload = Array[Byte](1) - val out = new - ByteArrayOutputStream() - val packer = MessagePack.newDefaultPacker(out) + val out = new ByteArrayOutputStream() + val packer = MessagePack + .newDefaultPacker(out) .packBinaryHeader(1) .writePayload(payload) .close() @@ -289,44 +270,46 @@ class MessagePackerTest extends MessagePackSpec { val b = packer.toByteArray val unpacker = MessagePack.newDefaultUnpacker(b) - val f = unpacker.getNextFormat + val f = unpacker.getNextFormat f shouldBe MessageFormat.STR8 } "be able to disable STR8 for backward compatibility" in { val config = new PackerConfig() - .withStr8FormatSupport(false) + .withStr8FormatSupport(false) val packer = config.newBufferPacker() packer.packString("Hello. This is a string longer than 32 characters!") val unpacker = MessagePack.newDefaultUnpacker(packer.toByteArray) - val f = unpacker.getNextFormat + val f = unpacker.getNextFormat f shouldBe MessageFormat.STR16 } "be able to disable STR8 when using CharsetEncoder" in { val config = new PackerConfig() - .withStr8FormatSupport(false) - .withSmallStringOptimizationThreshold(0) // Disable small string optimization + .withStr8FormatSupport(false) + .withSmallStringOptimizationThreshold(0) // Disable small string optimization val packer = config.newBufferPacker() packer.packString("small string") val unpacker = MessagePack.newDefaultUnpacker(packer.toByteArray) - val f = unpacker.getNextFormat - f shouldNot be (MessageFormat.STR8) + val f = unpacker.getNextFormat + f shouldNot be(MessageFormat.STR8) val s = unpacker.unpackString() s shouldBe "small string" } - "write raw binary" taggedAs("raw-binary") in { + "write raw binary" taggedAs ("raw-binary") in { val packer = new MessagePack.PackerConfig().newBufferPacker() - val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) + val msg = + Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) packer.writePayload(msg) } - "append raw binary" taggedAs("append-raw-binary") in { + "append raw binary" taggedAs ("append-raw-binary") in { val packer = new MessagePack.PackerConfig().newBufferPacker() - val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) + val msg = + Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) packer.addPayload(msg) } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index bd8e4e693..5b214970c 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -34,8 +34,7 @@ object MessageUnpackerTest { val a = array(cursor) cursor += 1 MessageBuffer.wrap(a) - } - else { + } else { null } } @@ -50,7 +49,7 @@ class MessageUnpackerTest extends MessagePackSpec { val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] def testData: Array[Byte] = { - val out = new ByteArrayOutputStream() + val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) packer @@ -72,7 +71,7 @@ class MessageUnpackerTest extends MessagePackSpec { val intSeq = (for (i <- 0 until 100) yield Random.nextInt()).toArray[Int] def testData2: Array[Byte] = { - val out = new ByteArrayOutputStream() + val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out); packer @@ -88,7 +87,10 @@ class MessageUnpackerTest extends MessagePackSpec { } def write(packer: MessagePacker, r: Random) { - val tpeIndex = Iterator.continually(r.nextInt(MessageFormat.values().length)).find(_ != MessageFormat.NEVER_USED.ordinal()).get + val tpeIndex = Iterator + .continually(r.nextInt(MessageFormat.values().length)) + .find(_ != MessageFormat.NEVER_USED.ordinal()) + .get val tpe = MessageFormat.values()(tpeIndex) tpe.getValueType match { @@ -110,7 +112,7 @@ class MessageUnpackerTest extends MessagePackSpec { packer.packString(v) case ValueType.BINARY => val len = r.nextInt(100) - val b = new Array[Byte](len) + val b = new Array[Byte](len) r.nextBytes(b) trace(s"binary: ${toHex(b)}") packer.packBinaryHeader(b.length) @@ -142,12 +144,14 @@ class MessageUnpackerTest extends MessagePackSpec { def testData3(N: Int): Array[Byte] = { - val out = new ByteArrayOutputStream() + val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) val r = new Random(0) - (0 until N).foreach { i => write(packer, r) } + (0 until N).foreach { i => + write(packer, r) + } packer.close() val arr = out.toByteArray @@ -156,7 +160,6 @@ class MessageUnpackerTest extends MessagePackSpec { arr } - def readValue(unpacker: MessageUnpacker) { val f = unpacker.getNextFormat() f.getValueType match { @@ -192,14 +195,14 @@ class MessageUnpackerTest extends MessagePackSpec { u.hasNext shouldBe false } - def unpackers(data: Array[Byte]) : Seq[MessageUnpacker] = { + def unpackers(data: Array[Byte]): Seq[MessageUnpacker] = { val bb = ByteBuffer.allocate(data.length) val db = ByteBuffer.allocateDirect(data.length) bb.put(data).flip() db.put(data).flip() val builder = Seq.newBuilder[MessageUnpacker] builder += MessagePack.newDefaultUnpacker(data) - builder += MessagePack.newDefaultUnpacker(bb) + builder += MessagePack.newDefaultUnpacker(bb) if (!universal) { builder += MessagePack.newDefaultUnpacker(db) } @@ -207,12 +210,12 @@ class MessageUnpackerTest extends MessagePackSpec { builder.result() } - def unpackerCollectionWithVariousBuffers(data: Array[Byte], chunkSize: Int) : Seq[MessageUnpacker] = { - val seqBytes = Seq.newBuilder[MessageBufferInput] - val seqByteBuffers = Seq.newBuilder[MessageBufferInput] + def unpackerCollectionWithVariousBuffers(data: Array[Byte], chunkSize: Int): Seq[MessageUnpacker] = { + val seqBytes = Seq.newBuilder[MessageBufferInput] + val seqByteBuffers = Seq.newBuilder[MessageBufferInput] val seqDirectBuffers = Seq.newBuilder[MessageBufferInput] - var left = data.length - var position = 0 + var left = data.length + var position = 0 while (left > 0) { val length = Math.min(chunkSize, left) seqBytes += new ArrayBufferInput(data, position, length) @@ -267,7 +270,7 @@ class MessageUnpackerTest extends MessagePackSpec { } "compare skip performance" taggedAs ("skip") in { - val N = 10000 + val N = 10000 val data = testData3(N) time("skip performance", repeat = 100) { @@ -322,7 +325,6 @@ class MessageUnpackerTest extends MessagePackSpec { } - "read data at the buffer boundary" taggedAs ("boundary") in { trait SplitTest { @@ -340,10 +342,10 @@ class MessageUnpackerTest extends MessagePackSpec { for (splitPoint <- 1 until data.length - 1) { debug(s"split at $splitPoint") - val (h, t) = data.splitAt(splitPoint) - val bin = new SplitMessageBufferInput(Array(h, t)) + val (h, t) = data.splitAt(splitPoint) + val bin = new SplitMessageBufferInput(Array(h, t)) val unpacker = MessagePack.newDefaultUnpacker(bin) - var count = 0 + var count = 0 while (unpacker.hasNext) { count += 1 val f = unpacker.getNextFormat @@ -356,13 +358,13 @@ class MessageUnpackerTest extends MessagePackSpec { } } - new SplitTest {val data = testData}.run - new SplitTest {val data = testData3(30)}.run + new SplitTest { val data = testData }.run + new SplitTest { val data = testData3(30) }.run } - "read integer at MessageBuffer boundaries" taggedAs("integer-buffer-boundary") in { + "read integer at MessageBuffer boundaries" taggedAs ("integer-buffer-boundary") in { val packer = MessagePack.newDefaultBufferPacker() - (0 until 1170).foreach{i => + (0 until 1170).foreach { i => packer.packLong(0x0011223344556677L) } packer.close @@ -383,9 +385,9 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "read string at MessageBuffer boundaries" taggedAs("string-buffer-boundary") in { + "read string at MessageBuffer boundaries" taggedAs ("string-buffer-boundary") in { val packer = MessagePack.newDefaultBufferPacker() - (0 until 1170).foreach{i => + (0 until 1170).foreach { i => packer.packString("hello world") } packer.close @@ -417,16 +419,15 @@ class MessageUnpackerTest extends MessagePackSpec { unpacker.skipValue() count += 1 } - } - finally { + } finally { unpacker.close() } } } val data = testData3(10000) - val N = 100 - val bb = ByteBuffer.allocate(data.length) + val N = 100 + val bb = ByteBuffer.allocate(data.length) bb.put(data).flip() val db = ByteBuffer.allocateDirect(data.length) db.put(data).flip() @@ -434,24 +435,23 @@ class MessageUnpackerTest extends MessagePackSpec { val t = time("skip performance", repeat = N) { block("v6") { import org.msgpack.`type`.{ValueType => ValueTypeV6} - val v6 = new org.msgpack.MessagePack() + val v6 = new org.msgpack.MessagePack() val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(data)) - var count = 0 + var count = 0 try { while (true) { unpacker.skip() count += 1 } - } - catch { + } catch { case e: EOFException => - } - finally - unpacker.close() + } finally unpacker.close() } block("v7-array") { - new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(data) }.run + new Fixture { + override val unpacker = MessagePack.newDefaultUnpacker(data) + }.run } block("v7-array-buffer") { @@ -468,7 +468,8 @@ class MessageUnpackerTest extends MessagePackSpec { t("v7-array").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax t("v7-array-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax - if (!universal) t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + if (!universal) + t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax } import org.msgpack.`type`.{ValueType => ValueTypeV6} @@ -480,13 +481,15 @@ class MessageUnpackerTest extends MessagePackSpec { vt match { case ValueTypeV6.ARRAY => val len = unpacker.readArrayBegin() - var i = 0 - while (i < len) {readValueV6(unpacker); i += 1} + var i = 0 + while (i < len) { readValueV6(unpacker); i += 1 } unpacker.readArrayEnd() case ValueTypeV6.MAP => val len = unpacker.readMapBegin() - var i = 0 - while (i < len) {readValueV6(unpacker); readValueV6(unpacker); i += 1} + var i = 0 + while (i < len) { + readValueV6(unpacker); readValueV6(unpacker); i += 1 + } unpacker.readMapEnd() case ValueTypeV6.NIL => unpacker.readNil() @@ -506,17 +509,17 @@ class MessageUnpackerTest extends MessagePackSpec { val buf = new Array[Byte](8192) def readValue(unpacker: MessageUnpacker) { - val f = unpacker.getNextFormat + val f = unpacker.getNextFormat val vt = f.getValueType vt match { case ValueType.ARRAY => val len = unpacker.unpackArrayHeader() - var i = 0 - while (i < len) {readValue(unpacker); i += 1} + var i = 0 + while (i < len) { readValue(unpacker); i += 1 } case ValueType.MAP => val len = unpacker.unpackMapHeader() - var i = 0 - while (i < len) {readValue(unpacker); readValue(unpacker); i += 1} + var i = 0 + while (i < len) { readValue(unpacker); readValue(unpacker); i += 1 } case ValueType.NIL => unpacker.unpackNil() case ValueType.INTEGER => @@ -536,7 +539,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } trait Fixture { - val unpacker : MessageUnpacker + val unpacker: MessageUnpacker def run { var count = 0 try { @@ -544,39 +547,36 @@ class MessageUnpackerTest extends MessagePackSpec { readValue(unpacker) count += 1 } - } - finally - unpacker.close() + } finally unpacker.close() } } val data = testData3(10000) - val N = 100 - val bb = ByteBuffer.allocate(data.length) + val N = 100 + val bb = ByteBuffer.allocate(data.length) bb.put(data).flip() val db = ByteBuffer.allocateDirect(data.length) db.put(data).flip() val t = time("unpack performance", repeat = N) { block("v6") { - val v6 = new org.msgpack.MessagePack() + val v6 = new org.msgpack.MessagePack() val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(data)) - var count = 0 + var count = 0 try { while (true) { readValueV6(unpacker) count += 1 } - } - catch { + } catch { case e: EOFException => - } - finally - unpacker.close() + } finally unpacker.close() } block("v7-array") { - new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(data) }.run + new Fixture { + override val unpacker = MessagePack.newDefaultUnpacker(data) + }.run } block("v7-array-buffer") { @@ -594,16 +594,17 @@ class MessageUnpackerTest extends MessagePackSpec { t("v7-array").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax t("v7-array-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax - if (!universal) t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + if (!universal) + t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax } "be faster for reading binary than v6" taggedAs ("cmp-binary") in { - val bos = new ByteArrayOutputStream() + val bos = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(bos) - val L = 10000 - val R = 100 + val L = 10000 + val R = 100 (0 until R).foreach { i => packer.packBinaryHeader(L) packer.writePayload(new Array[Byte](L)) @@ -611,8 +612,8 @@ class MessageUnpackerTest extends MessagePackSpec { packer.close() trait Fixture { - val unpacker : MessageUnpacker - val loop : Int + val unpacker: MessageUnpacker + val loop: Int def run { var i = 0 try { @@ -622,9 +623,7 @@ class MessageUnpackerTest extends MessagePackSpec { unpacker.readPayload(out, 0, len) i += 1 } - } - finally - unpacker.close() + } finally unpacker.close() } def runRef { var i = 0 @@ -634,12 +633,10 @@ class MessageUnpackerTest extends MessagePackSpec { val out = unpacker.readPayloadAsReference(len) i += 1 } - } - finally - unpacker.close() + } finally unpacker.close() } } - val b = bos.toByteArray + val b = bos.toByteArray val bb = ByteBuffer.allocate(b.length) bb.put(b).flip() val db = ByteBuffer.allocateDirect(b.length) @@ -647,9 +644,9 @@ class MessageUnpackerTest extends MessagePackSpec { time("unpackBinary", repeat = 100) { block("v6") { - val v6 = new org.msgpack.MessagePack() + val v6 = new org.msgpack.MessagePack() val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(b)) - var i = 0 + var i = 0 while (i < R) { val out = unpacker.readByteArray() i += 1 @@ -660,42 +657,42 @@ class MessageUnpackerTest extends MessagePackSpec { block("v7-array") { new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(b) - override val loop = R + override val loop = R }.run } block("v7-array-buffer") { new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(bb) - override val loop = R + override val loop = R }.run } if (!universal) block("v7-direct-buffer") { new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(db) - override val loop = R + override val loop = R }.run } block("v7-ref-array") { new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(b) - override val loop = R + override val loop = R }.runRef } block("v7-ref-array-buffer") { new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(bb) - override val loop = R + override val loop = R }.runRef } if (!universal) block("v7-ref-direct-buffer") { new Fixture { override val unpacker = MessagePack.newDefaultUnpacker(db) - override val loop = R + override val loop = R }.runRef } } @@ -703,13 +700,14 @@ class MessageUnpackerTest extends MessagePackSpec { "read payload as a reference" taggedAs ("ref") in { - val dataSizes = Seq(0, 1, 5, 8, 16, 32, 128, 256, 1024, 2000, 10000, 100000) + val dataSizes = + Seq(0, 1, 5, 8, 16, 32, 128, 256, 1024, 2000, 10000, 100000) for (s <- dataSizes) { When(f"data size is $s%,d") val data = new Array[Byte](s) Random.nextBytes(data) - val b = new ByteArrayOutputStream() + val b = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(b) packer.packBinaryHeader(s) packer.writePayload(data) @@ -730,11 +728,10 @@ class MessageUnpackerTest extends MessagePackSpec { } - "reset the internal states" taggedAs ("reset") in { val data = intSeq - val b = createMessagePackData(packer => data foreach packer.packInt) + val b = createMessagePackData(packer => data foreach packer.packInt) for (unpacker <- unpackers(b)) { val unpacked = Array.newBuilder[Int] @@ -745,8 +742,8 @@ class MessageUnpackerTest extends MessagePackSpec { unpacked.result shouldBe data val data2 = intSeq - val b2 = createMessagePackData(packer => data2 foreach packer.packInt) - val bi = new ArrayBufferInput(b2) + val b2 = createMessagePackData(packer => data2 foreach packer.packInt) + val bi = new ArrayBufferInput(b2) unpacker.reset(bi) val unpacked2 = Array.newBuilder[Int] while (unpacker.hasNext) { @@ -770,12 +767,12 @@ class MessageUnpackerTest extends MessagePackSpec { "improve the performance via reset method" taggedAs ("reset-arr") in { - val out = new ByteArrayOutputStream + val out = new ByteArrayOutputStream val packer = MessagePack.newDefaultPacker(out) packer.packInt(0) packer.flush val arr = out.toByteArray - val mb = MessageBuffer.wrap(arr) + val mb = MessageBuffer.wrap(arr) val N = 1000 val t = time("unpacker", repeat = 10) { @@ -822,7 +819,7 @@ class MessageUnpackerTest extends MessagePackSpec { "reset ChannelBufferInput" in { val f0 = createTempFile - val u = MessagePack.newDefaultUnpacker(new FileInputStream(f0).getChannel) + val u = MessagePack.newDefaultUnpacker(new FileInputStream(f0).getChannel) checkFile(u) val f1 = createTempFile @@ -834,7 +831,7 @@ class MessageUnpackerTest extends MessagePackSpec { "reset InputStreamBufferInput" in { val f0 = createTempFile - val u = MessagePack.newDefaultUnpacker(new FileInputStream(f0)) + val u = MessagePack.newDefaultUnpacker(new FileInputStream(f0)) checkFile(u) val f1 = createTempFile @@ -846,7 +843,7 @@ class MessageUnpackerTest extends MessagePackSpec { "unpack large string data" taggedAs ("large-string") in { def createLargeData(stringLength: Int): Array[Byte] = { - val out = new ByteArrayOutputStream() + val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) packer @@ -876,7 +873,7 @@ class MessageUnpackerTest extends MessagePackSpec { "unpack string crossing end of buffer" in { def check(expected: String, strLen: Int) = { val bytes = new Array[Byte](strLen) - val out = new ByteArrayOutputStream + val out = new ByteArrayOutputStream val packer = MessagePack.newDefaultPacker(out) packer.packBinaryHeader(bytes.length) @@ -885,7 +882,7 @@ class MessageUnpackerTest extends MessagePackSpec { packer.close val unpacker = MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(out.toByteArray))) - val len = unpacker.unpackBinaryHeader + val len = unpacker.unpackBinaryHeader unpacker.readPayload(len) val got = unpacker.unpackString unpacker.close @@ -893,12 +890,15 @@ class MessageUnpackerTest extends MessagePackSpec { got shouldBe expected } - Seq("\u3042", "a\u3042", "\u3042a", "\u3042\u3044\u3046\u3048\u304A\u304B\u304D\u304F\u3051\u3053\u3055\u3057\u3059\u305B\u305D").foreach { s => - Seq(8185, 8186, 8187, 8188, 16377, 16378, 16379, 16380).foreach { n => check(s, n)} - } + Seq("\u3042", "a\u3042", "\u3042a", "\u3042\u3044\u3046\u3048\u304A\u304B\u304D\u304F\u3051\u3053\u3055\u3057\u3059\u305B\u305D") + .foreach { s => + Seq(8185, 8186, 8187, 8188, 16377, 16378, 16379, 16380).foreach { n => + check(s, n) + } + } } - def readTest(input:MessageBufferInput): Unit = { + def readTest(input: MessageBufferInput): Unit = { withResource(MessagePack.newDefaultUnpacker(input)) { unpacker => while (unpacker.hasNext) { unpacker.unpackValue() @@ -906,22 +906,22 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "read value length at buffer boundary" taggedAs("number-boundary") in { - val input = new SplitMessageBufferInput(Array( - Array[Byte](MessagePack.Code.STR16), - Array[Byte](0x00), - Array[Byte](0x05), // STR16 length at the boundary - "hello".getBytes(MessagePack.UTF8)) - ) + "read value length at buffer boundary" taggedAs ("number-boundary") in { + val input = new SplitMessageBufferInput( + Array(Array[Byte](MessagePack.Code.STR16), + Array[Byte](0x00), + Array[Byte](0x05), // STR16 length at the boundary + "hello".getBytes(MessagePack.UTF8))) readTest(input) - val input2 = new SplitMessageBufferInput(Array( - Array[Byte](MessagePack.Code.STR32), - Array[Byte](0x00), - Array[Byte](0x00, 0x00), - Array[Byte](0x05), // STR32 length at the boundary - "hello".getBytes(MessagePack.UTF8)) - ) + val input2 = new SplitMessageBufferInput( + Array( + Array[Byte](MessagePack.Code.STR32), + Array[Byte](0x00), + Array[Byte](0x00, 0x00), + Array[Byte](0x05), // STR32 length at the boundary + "hello".getBytes(MessagePack.UTF8) + )) readTest(input2) } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala index 18876ddb8..ed79ef6ab 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala @@ -18,23 +18,20 @@ package org.msgpack.core.buffer import akka.util.ByteString import org.msgpack.core.{MessagePack, MessagePackSpec, MessageUnpacker} -class ByteStringTest - extends MessagePackSpec { +class ByteStringTest extends MessagePackSpec { val unpackedString = "foo" - val byteString = ByteString(createMessagePackData(_.packString(unpackedString))) + val byteString = ByteString(createMessagePackData(_.packString(unpackedString))) def unpackString(messageBuffer: MessageBuffer) = { - val input = new - MessageBufferInput { + val input = new MessageBufferInput { private var isRead = false override def next(): MessageBuffer = if (isRead) { null - } - else { + } else { isRead = true messageBuffer } @@ -49,8 +46,7 @@ class ByteStringTest // can't demonstrate with new ByteBufferInput(byteString.asByteBuffer) // as Travis tests run with JDK6 that picks up MessageBufferU - a[RuntimeException] shouldBe thrownBy(unpackString(new - MessageBuffer(byteString.asByteBuffer))) + a[RuntimeException] shouldBe thrownBy(unpackString(new MessageBuffer(byteString.asByteBuffer))) } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index a7653797e..060e436a1 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -27,15 +27,14 @@ import xerial.core.io.IOUtil._ import scala.util.Random -class MessageBufferInputTest - extends MessagePackSpec { +class MessageBufferInputTest extends MessagePackSpec { - val targetInputSize = Seq(0, 10, 500, 1000, 2000, 4000, 8000, 10000, 30000, 50000, 100000) + val targetInputSize = + Seq(0, 10, 500, 1000, 2000, 4000, 8000, 10000, 30000, 50000, 100000) def testData(size: Int) = { //debug(s"test data size: ${size}") - val b = new - Array[Byte](size) + val b = new Array[Byte](size) Random.nextBytes(b) b } @@ -52,10 +51,8 @@ class MessageBufferInputTest implicit class InputData(b: Array[Byte]) { def compress = { - val compressed = new - ByteArrayOutputStream() - val out = new - GZIPOutputStream(compressed) + val compressed = new ByteArrayOutputStream() + val out = new GZIPOutputStream(compressed) out.write(b) out.close() compressed.toByteArray @@ -67,14 +64,10 @@ class MessageBufferInputTest def saveToTmpFile: File = { val tmp = File - .createTempFile("testbuf", - ".dat", - new - File("target")) + .createTempFile("testbuf", ".dat", new File("target")) tmp.getParentFile.mkdirs() tmp.deleteOnExit() - withResource(new - FileOutputStream(tmp)) { out => + withResource(new FileOutputStream(tmp)) { out => out.write(b) } tmp @@ -93,23 +86,15 @@ class MessageBufferInputTest "MessageBufferInput" should { "support byte arrays" in { - runTest(new - ArrayBufferInput(_)) + runTest(new ArrayBufferInput(_)) } "support ByteBuffers" in { - runTest(b => new - ByteBufferInput(b.toByteBuffer)) + runTest(b => new ByteBufferInput(b.toByteBuffer)) } "support InputStreams" taggedAs ("is") in { - runTest(b => - new - InputStreamBufferInput( - new - GZIPInputStream(new - ByteArrayInputStream(b.compress))) - ) + runTest(b => new InputStreamBufferInput(new GZIPInputStream(new ByteArrayInputStream(b.compress)))) } "support file input channel" taggedAs ("fc") in { @@ -117,10 +102,8 @@ class MessageBufferInputTest val tmp = b.saveToTmpFile try { InputStreamBufferInput - .newBufferInput(new - FileInputStream(tmp)) - } - finally { + .newBufferInput(new FileInputStream(tmp)) + } finally { tmp.delete() } } @@ -134,17 +117,16 @@ class MessageBufferInputTest } def createTempFileWithInputStream = { - val f = createTempFile + val f = createTempFile val out = new FileOutputStream(f) MessagePack.newDefaultPacker(out).packInt(42).close - val in = new - FileInputStream(f) + val in = new FileInputStream(f) (f, in) } def createTempFileWithChannel = { val (f, in) = createTempFileWithInputStream - val ch = in.getChannel + val ch = in.getChannel (f, ch) } @@ -156,8 +138,7 @@ class MessageBufferInputTest "InputStreamBufferInput" should { "reset buffer" in { val (f0, in0) = createTempFileWithInputStream - val buf = new - InputStreamBufferInput(in0) + val buf = new InputStreamBufferInput(in0) readInt(buf) shouldBe 42 val (f1, in1) = createTempFileWithInputStream @@ -167,13 +148,12 @@ class MessageBufferInputTest "be non-blocking" taggedAs ("non-blocking") in { - withResource(new - PipedOutputStream()) { pipedOutputStream => - withResource(new - PipedInputStream()) { pipedInputStream => + withResource(new PipedOutputStream()) { pipedOutputStream => + withResource(new PipedInputStream()) { pipedInputStream => pipedInputStream.connect(pipedOutputStream) - val packer = MessagePack.newDefaultPacker(pipedOutputStream) + val packer = MessagePack + .newDefaultPacker(pipedOutputStream) .packArrayHeader(2) .packLong(42) .packString("hello world") @@ -196,8 +176,7 @@ class MessageBufferInputTest "ChannelBufferInput" should { "reset buffer" in { val (f0, in0) = createTempFileWithChannel - val buf = new - ChannelBufferInput(in0) + val buf = new ChannelBufferInput(in0) readInt(buf) shouldBe 42 val (f1, in1) = createTempFileWithChannel @@ -206,14 +185,15 @@ class MessageBufferInputTest } "unpack without blocking" in { - val server = ServerSocketChannel.open.bind(new InetSocketAddress("localhost", 0)) + val server = + ServerSocketChannel.open.bind(new InetSocketAddress("localhost", 0)) val executorService = Executors.newCachedThreadPool try { executorService.execute(new Runnable { override def run { val server_ch = server.accept - val packer = MessagePack.newDefaultPacker(server_ch) + val packer = MessagePack.newDefaultPacker(server_ch) packer.packString("0123456789") packer.flush // Keep the connection open @@ -226,17 +206,16 @@ class MessageBufferInputTest val future = executorService.submit(new Callable[String] { override def call: String = { - val conn_ch = SocketChannel.open(new InetSocketAddress("localhost", server.socket.getLocalPort)) + val conn_ch = SocketChannel.open(new InetSocketAddress("localhost", server.socket.getLocalPort)) val unpacker = MessagePack.newDefaultUnpacker(conn_ch) - val s = unpacker.unpackString + val s = unpacker.unpackString unpacker.close s } }) future.get(5, TimeUnit.SECONDS) shouldBe "0123456789" - } - finally { + } finally { executorService.shutdown if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { executorService.shutdownNow diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala index 1869f2aad..e048e1ba1 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala @@ -19,8 +19,7 @@ import java.io._ import org.msgpack.core.MessagePackSpec -class MessageBufferOutputTest - extends MessagePackSpec { +class MessageBufferOutputTest extends MessagePackSpec { def createTempFile = { val f = File.createTempFile("msgpackTest", "msgpack") @@ -29,15 +28,14 @@ class MessageBufferOutputTest } def createTempFileWithOutputStream = { - val f = createTempFile - val out = new - FileOutputStream(f) + val f = createTempFile + val out = new FileOutputStream(f) (f, out) } def createTempFileWithChannel = { val (f, out) = createTempFileWithOutputStream - val ch = out.getChannel + val ch = out.getChannel (f, ch) } @@ -51,8 +49,7 @@ class MessageBufferOutputTest "OutputStreamBufferOutput" should { "reset buffer" in { val (f0, out0) = createTempFileWithOutputStream - val buf = new - OutputStreamBufferOutput(out0) + val buf = new OutputStreamBufferOutput(out0) writeIntToBuf(buf) f0.length.toInt should be > 0 @@ -66,8 +63,7 @@ class MessageBufferOutputTest "ChannelBufferOutput" should { "reset buffer" in { val (f0, ch0) = createTempFileWithChannel - val buf = new - ChannelBufferOutput(ch0) + val buf = new ChannelBufferOutput(ch0) writeIntToBuf(buf) f0.length.toInt should be > 0 diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala index 40a185148..f0f66b4af 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala @@ -22,10 +22,9 @@ import org.msgpack.core.MessagePackSpec import scala.util.Random /** - * Created on 2014/05/01. - */ -class MessageBufferTest - extends MessagePackSpec { + * Created on 2014/05/01. + */ +class MessageBufferTest extends MessagePackSpec { "MessageBuffer" should { @@ -36,16 +35,16 @@ class MessageBufferTest } "wrap byte array considering position and remaining values" taggedAs ("wrap-ba") in { - val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) + val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) val mb = MessageBuffer.wrap(d, 2, 2) mb.getByte(0) shouldBe 12 mb.size() shouldBe 2 } "wrap ByteBuffer considering position and remaining values" taggedAs ("wrap-bb") in { - val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) + val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) val subset = ByteBuffer.wrap(d, 2, 2) - val mb = MessageBuffer.wrap(subset) + val mb = MessageBuffer.wrap(subset) mb.getByte(0) shouldBe 12 mb.size() shouldBe 2 } @@ -56,7 +55,9 @@ class MessageBufferTest val M = 64 * 1024 * 1024 val ub = MessageBuffer.allocate(M) - val ud = if (universal) MessageBuffer.wrap(ByteBuffer.allocate(M)) else MessageBuffer.wrap(ByteBuffer.allocateDirect(M)) + val ud = + if (universal) MessageBuffer.wrap(ByteBuffer.allocate(M)) + else MessageBuffer.wrap(ByteBuffer.allocateDirect(M)) val hb = ByteBuffer.allocate(M) val db = ByteBuffer.allocateDirect(M) @@ -68,10 +69,8 @@ class MessageBufferTest } } - val r = new - Random(0) - val rs = new - Array[Int](N) + val r = new Random(0) + val rs = new Array[Int](N) (0 until N).map(i => rs(i) = r.nextInt(N)) def randomBench(f: Int => Unit) { var i = 0 @@ -168,9 +167,9 @@ class MessageBufferTest "put ByteBuffer on itself" in { for (t <- buffers) { - val b = Array[Byte](0x02, 0x03) + val b = Array[Byte](0x02, 0x03) val srcArray = ByteBuffer.wrap(b) - val srcHeap = ByteBuffer.allocate(b.length) + val srcHeap = ByteBuffer.allocate(b.length) srcHeap.put(b).flip val srcOffHeap = ByteBuffer.allocateDirect(b.length) srcOffHeap.put(b).flip @@ -192,9 +191,9 @@ class MessageBufferTest "put MessageBuffer on itself" in { for (t <- buffers) { - val b = Array[Byte](0x02, 0x03) + val b = Array[Byte](0x02, 0x03) val srcArray = ByteBuffer.wrap(b) - val srcHeap = ByteBuffer.allocate(b.length) + val srcHeap = ByteBuffer.allocate(b.length) srcHeap.put(b).flip val srcOffHeap = ByteBuffer.allocateDirect(b.length) srcOffHeap.put(b).flip @@ -218,11 +217,11 @@ class MessageBufferTest } "copy sliced buffer" in { - def prepareBytes : Array[Byte] = { + def prepareBytes: Array[Byte] = { Array[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07) } - def prepareDirectBuffer : ByteBuffer = { + def prepareDirectBuffer: ByteBuffer = { val directBuffer = ByteBuffer.allocateDirect(prepareBytes.length) directBuffer.put(prepareBytes) directBuffer.flip @@ -259,5 +258,3 @@ class MessageBufferTest } } } - - diff --git a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala index bacf39ed4..cbbfd8751 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala @@ -18,10 +18,9 @@ package org.msgpack.core.example import org.msgpack.core.MessagePackSpec /** - * - */ -class MessagePackExampleTest - extends MessagePackSpec { + * + */ +class MessagePackExampleTest extends MessagePackSpec { "example" should { diff --git a/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala index e545d7d2a..7de9d6c6f 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala @@ -17,14 +17,13 @@ package org.msgpack.value import org.msgpack.core.MessagePackSpec -class RawStringValueImplTest - extends MessagePackSpec { +class RawStringValueImplTest extends MessagePackSpec { "StringValue" should { "return the same hash code if they are equal" in { val str = "a" - val a1 = ValueFactory.newString(str.getBytes("UTF-8")) - val a2 = ValueFactory.newString(str) + val a1 = ValueFactory.newString(str.getBytes("UTF-8")) + val a2 = ValueFactory.newString(str) a1.shouldEqual(a2) a1.hashCode.shouldEqual(a2.hashCode) diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala index 6b045f3ae..8b11e0ca0 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala @@ -18,10 +18,9 @@ package org.msgpack.value import org.msgpack.core.MessagePackSpec /** - * - */ -class ValueFactoryTest - extends MessagePackSpec { + * + */ +class ValueFactoryTest extends MessagePackSpec { def isValid(v: Value, expected: ValueType, @@ -35,8 +34,7 @@ class ValueFactoryTest isMap: Boolean = false, isExtension: Boolean = false, isRaw: Boolean = false, - isNumber: Boolean = false - ) { + isNumber: Boolean = false) { v.isNilValue shouldBe isNil v.isBooleanValue shouldBe isBoolean v.isIntegerValue shouldBe isInteger @@ -54,15 +52,25 @@ class ValueFactoryTest "create valid type values" in { isValid(ValueFactory.newNil(), expected = ValueType.NIL, isNil = true) - forAll { (v: Boolean) => isValid(ValueFactory.newBoolean(v), expected = ValueType.BOOLEAN, isBoolean = true) } - forAll { (v: Int) => isValid(ValueFactory.newInteger(v), expected = ValueType.INTEGER, isInteger = true, isNumber = true) } - forAll { (v: Float) => isValid(ValueFactory.newFloat(v), expected = ValueType.FLOAT, isFloat = true, isNumber = true) } - forAll { (v: String) => isValid(ValueFactory.newString(v), expected = ValueType.STRING, isString = true, isRaw = true) } - forAll { (v: Array[Byte]) => isValid(ValueFactory.newBinary(v), expected = ValueType.BINARY, isBinary = true, isRaw = true) } + forAll { (v: Boolean) => + isValid(ValueFactory.newBoolean(v), expected = ValueType.BOOLEAN, isBoolean = true) + } + forAll { (v: Int) => + isValid(ValueFactory.newInteger(v), expected = ValueType.INTEGER, isInteger = true, isNumber = true) + } + forAll { (v: Float) => + isValid(ValueFactory.newFloat(v), expected = ValueType.FLOAT, isFloat = true, isNumber = true) + } + forAll { (v: String) => + isValid(ValueFactory.newString(v), expected = ValueType.STRING, isString = true, isRaw = true) + } + forAll { (v: Array[Byte]) => + isValid(ValueFactory.newBinary(v), expected = ValueType.BINARY, isBinary = true, isRaw = true) + } isValid(ValueFactory.emptyArray(), expected = ValueType.ARRAY, isArray = true) isValid(ValueFactory.emptyMap(), expected = ValueType.MAP, isMap = true) - forAll { (v: Array[Byte]) => isValid(ValueFactory.newExtension(0, v), expected = ValueType - .EXTENSION, isExtension = true, isRaw = false) + forAll { (v: Array[Byte]) => + isValid(ValueFactory.newExtension(0, v), expected = ValueType.EXTENSION, isExtension = true, isRaw = false) } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala index 6cb7af603..0e1fb8c40 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala @@ -20,29 +20,38 @@ import org.msgpack.core._ import scala.util.parsing.json.JSON -class ValueTest extends MessagePackSpec -{ - def checkSuccinctType(pack:MessagePacker => Unit, expectedAtMost:MessageFormat) { - val b = createMessagePackData(pack) +class ValueTest extends MessagePackSpec { + def checkSuccinctType(pack: MessagePacker => Unit, expectedAtMost: MessageFormat) { + val b = createMessagePackData(pack) val v1 = MessagePack.newDefaultUnpacker(b).unpackValue() val mf = v1.asIntegerValue().mostSuccinctMessageFormat() mf.getValueType shouldBe ValueType.INTEGER - mf.ordinal() shouldBe <= (expectedAtMost.ordinal()) + mf.ordinal() shouldBe <=(expectedAtMost.ordinal()) val v2 = new Variable MessagePack.newDefaultUnpacker(b).unpackValue(v2) val mf2 = v2.asIntegerValue().mostSuccinctMessageFormat() mf2.getValueType shouldBe ValueType.INTEGER - mf2.ordinal() shouldBe <= (expectedAtMost.ordinal()) + mf2.ordinal() shouldBe <=(expectedAtMost.ordinal()) } "Value" should { "tell most succinct integer type" in { - forAll { (v: Byte) => checkSuccinctType(_.packByte(v), MessageFormat.INT8) } - forAll { (v: Short) => checkSuccinctType(_.packShort(v), MessageFormat.INT16) } - forAll { (v: Int) => checkSuccinctType(_.packInt(v), MessageFormat.INT32) } - forAll { (v: Long) => checkSuccinctType(_.packLong(v), MessageFormat.INT64) } - forAll { (v: Long) => checkSuccinctType(_.packBigInteger(BigInteger.valueOf(v)), MessageFormat.INT64) } + forAll { (v: Byte) => + checkSuccinctType(_.packByte(v), MessageFormat.INT8) + } + forAll { (v: Short) => + checkSuccinctType(_.packShort(v), MessageFormat.INT16) + } + forAll { (v: Int) => + checkSuccinctType(_.packInt(v), MessageFormat.INT32) + } + forAll { (v: Long) => + checkSuccinctType(_.packLong(v), MessageFormat.INT64) + } + forAll { (v: Long) => + checkSuccinctType(_.packBigInteger(BigInteger.valueOf(v)), MessageFormat.INT64) + } forAll { (v: Long) => whenever(v > 0) { // Create value between 2^63-1 < v <= 2^64-1 @@ -77,11 +86,11 @@ class ValueTest extends MessagePackSpec // Map value val m = newMapBuilder() - .put(newString("id"), newInteger(1001)) - .put(newString("name"), newString("leo")) - .put(newString("address"), newArray(newString("xxx-xxxx"), newString("yyy-yyyy"))) - .put(newString("name"), newString("mitsu")) - .build() + .put(newString("id"), newInteger(1001)) + .put(newString("name"), newString("leo")) + .put(newString("address"), newArray(newString("xxx-xxxx"), newString("yyy-yyyy"))) + .put(newString("name"), newString("mitsu")) + .build() val i1 = JSON.parseFull(m.toJson) val i2 = JSON.parseFull(m.toString) // expect json value val a1 = JSON.parseFull("""{"id":1001,"name":"mitsu","address":["xxx-xxxx","yyy-yyyy"]}""") @@ -108,22 +117,22 @@ class ValueTest extends MessagePackSpec newInteger(Integer.MAX_VALUE).asInt() shouldBe Integer.MAX_VALUE newInteger(Integer.MIN_VALUE).asInt() shouldBe Integer.MIN_VALUE intercept[MessageIntegerOverflowException] { - newInteger(Byte.MAX_VALUE+1).asByte() + newInteger(Byte.MAX_VALUE + 1).asByte() } intercept[MessageIntegerOverflowException] { - newInteger(Byte.MIN_VALUE-1).asByte() + newInteger(Byte.MIN_VALUE - 1).asByte() } intercept[MessageIntegerOverflowException] { - newInteger(Short.MAX_VALUE+1).asShort() + newInteger(Short.MAX_VALUE + 1).asShort() } intercept[MessageIntegerOverflowException] { - newInteger(Short.MIN_VALUE-1).asShort() + newInteger(Short.MIN_VALUE - 1).asShort() } intercept[MessageIntegerOverflowException] { - newInteger(Integer.MAX_VALUE+1.toLong).asInt() + newInteger(Integer.MAX_VALUE + 1.toLong).asInt() } intercept[MessageIntegerOverflowException] { - newInteger(Integer.MIN_VALUE-1.toLong).asInt() + newInteger(Integer.MIN_VALUE - 1.toLong).asInt() } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala index 979c33c9b..445eda32c 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala @@ -21,16 +21,13 @@ import org.msgpack.core.{MessageFormat, MessageFormatException, MessagePackSpec} /** * Created on 2014/05/06. */ -class ValueTypeTest - extends MessagePackSpec -{ +class ValueTypeTest extends MessagePackSpec { "ValueType" should { "lookup ValueType from a byte value" taggedAs ("code") in { - def check(b: Byte, tpe: ValueType) - { + def check(b: Byte, tpe: ValueType) { MessageFormat.valueOf(b).getValueType shouldBe tpe } @@ -51,8 +48,7 @@ class ValueTypeTest try { MessageFormat.valueOf(NEVER_USED).getValueType fail("NEVER_USED type should not have ValueType") - } - catch { + } catch { case e: MessageFormatException => // OK } diff --git a/project/plugins.sbt b/project/plugins.sbt index 85c54f812..4b0d461c7 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,12 +1,11 @@ -addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.6") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") -addSbtPlugin("com.github.sbt" % "sbt-findbugs" % "2.0.0") -addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.0.3") -addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.0") -addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.2") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC12") -addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.3.0") - +addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.6") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") +addSbtPlugin("com.github.sbt" % "sbt-findbugs" % "2.0.0") +addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.0.3") +addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.2") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC12") +addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.3.0") scalacOptions ++= Seq("-deprecation", "-feature") From d8330a036ac137e86430f06914ff0c6a26bb9a25 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Nov 2017 22:16:25 -0800 Subject: [PATCH 068/417] Use sbt 1.0.4 + java9 --- .travis.yml | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 267873cdd..6c49f5f9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ cache: - $HOME/.m2/repository/ - $HOME/.ivy2/cache/ - $HOME/.sbt/boot/ + - $HOME/.coursier sudo: false @@ -32,16 +33,5 @@ matrix: packages: - oracle-java9-installer script: - # https://github.com/sbt/sbt/pull/2951 - - git clone https://github.com/retronym/java9-rt-export - - cd java9-rt-export/ - - git checkout 1019a2873d057dd7214f4135e84283695728395d - - echo "sbt.version=1.0.2" > project/build.properties - - sbt package - - mkdir -p $HOME/.sbt/0.13/java9-rt-ext; java -jar target/java9-rt-export-*.jar $HOME/.sbt/0.13/java9-rt-ext/rt.jar - - jar tf $HOME/.sbt/0.13/java9-rt-ext/rt.jar | grep java/lang/Object - - cd .. - - rm sbt - - wget https://raw.githubusercontent.com/paulp/sbt-extras/3ba0e52f32d32c0454ec3a926caae2db0caaca12/sbt && chmod +x ./sbt - - ./sbt -Dscala.ext.dirs=$HOME/.sbt/0.13/java9-rt-ext test - - ./sbt -Dscala.ext.dirs=$HOME/.sbt/0.13/java9-rt-ext -Dmsgpack.universal-buffer=true test + - ./sbt test + - ./sbt -Dmsgpack.universal-buffer=true test From 9b2ee3dd755065d8080e58e20ccf1a48da296372 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Nov 2017 22:18:33 -0800 Subject: [PATCH 069/417] Upgrade sbt script --- sbt | 348 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 189 insertions(+), 159 deletions(-) diff --git a/sbt b/sbt index c475bc64b..ffd29c512 100755 --- a/sbt +++ b/sbt @@ -5,59 +5,60 @@ set -o pipefail -# todo - make this dynamic -declare -r sbt_release_version="0.13.9" -declare -r sbt_unreleased_version="0.13.9" +declare -r sbt_release_version="0.13.16" +declare -r sbt_unreleased_version="0.13.16" + +declare -r latest_213="2.13.0-M2" +declare -r latest_212="2.12.4" +declare -r latest_211="2.11.11" +declare -r latest_210="2.10.6" +declare -r latest_29="2.9.3" +declare -r latest_28="2.8.2" + declare -r buildProps="project/build.properties" -declare sbt_jar sbt_dir sbt_create sbt_version -declare scala_version sbt_explicit_version -declare verbose noshare batch trace_level log_level -declare sbt_saved_stty debugUs +declare -r sbt_launch_ivy_release_repo="http://repo.typesafe.com/typesafe/ivy-releases" +declare -r sbt_launch_ivy_snapshot_repo="https://repo.scala-sbt.org/scalasbt/ivy-snapshots" +declare -r sbt_launch_mvn_release_repo="http://repo.scala-sbt.org/scalasbt/maven-releases" +declare -r sbt_launch_mvn_snapshot_repo="http://repo.scala-sbt.org/scalasbt/maven-snapshots" -echoerr () { echo >&2 "$@"; } -vlog () { [[ -n "$verbose" ]] && echoerr "$@"; } +declare -r default_jvm_opts_common="-Xms512m -Xmx1536m -Xss2m" +declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" -# spaces are possible, e.g. sbt.version = 0.13.0 -build_props_sbt () { - [[ -r "$buildProps" ]] && \ - grep '^sbt\.version' "$buildProps" | tr '=\r' ' ' | awk '{ print $2; }' -} +declare sbt_jar sbt_dir sbt_create sbt_version sbt_script sbt_new +declare sbt_explicit_version +declare verbose noshare batch trace_level +declare debugUs -update_build_props_sbt () { - local ver="$1" - local old="$(build_props_sbt)" +declare java_cmd="java" +declare sbt_launch_dir="$HOME/.sbt/launchers" +declare sbt_launch_repo - [[ -r "$buildProps" ]] && [[ "$ver" != "$old" ]] && { - perl -pi -e "s/^sbt\.version\b.*\$/sbt.version=${ver}/" "$buildProps" - grep -q '^sbt.version[ =]' "$buildProps" || printf "\nsbt.version=%s\n" "$ver" >> "$buildProps" +# pull -J and -D options to give to java. +declare -a java_args scalac_args sbt_commands residual_args - vlog "!!!" - vlog "!!! Updated file $buildProps setting sbt.version to: $ver" - vlog "!!! Previous value was: $old" - vlog "!!!" - } -} +# args to jvm/sbt via files or environment variables +declare -a extra_jvm_opts extra_sbt_opts -set_sbt_version () { - sbt_version="${sbt_explicit_version:-$(build_props_sbt)}" - [[ -n "$sbt_version" ]] || sbt_version=$sbt_release_version - export sbt_version -} +echoerr () { echo >&2 "$@"; } +vlog () { [[ -n "$verbose" ]] && echoerr "$@"; } +die () { echo "Aborting: $@" ; exit 1; } -# restore stty settings (echo in particular) -onSbtRunnerExit() { - [[ -n "$sbt_saved_stty" ]] || return - vlog "" - vlog "restoring stty: $sbt_saved_stty" - stty "$sbt_saved_stty" - unset sbt_saved_stty -} +setTrapExit () { + # save stty and trap exit, to ensure echo is re-enabled if we are interrupted. + export SBT_STTY="$(stty -g 2>/dev/null)" + + # restore stty settings (echo in particular) + onSbtRunnerExit() { + [ -t 0 ] || return + vlog "" + vlog "restoring stty: $SBT_STTY" + stty "$SBT_STTY" + } -# save stty and trap exit, to ensure echo is reenabled if we are interrupted. -trap onSbtRunnerExit EXIT -sbt_saved_stty="$(stty -g 2>/dev/null)" -vlog "Saved stty: $sbt_saved_stty" + vlog "saving stty: $SBT_STTY" + trap onSbtRunnerExit EXIT +} # this seems to cover the bases on OSX, and someone will # have to tell me about the others. @@ -73,21 +74,8 @@ get_script_path () { fi } -die() { - echo "Aborting: $@" - exit 1 -} - -make_url () { - version="$1" - - case "$version" in - 0.7.*) echo "http://simple-build-tool.googlecode.com/files/sbt-launch-0.7.7.jar" ;; - 0.10.* ) echo "$sbt_launch_repo/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;; - 0.11.[12]) echo "$sbt_launch_repo/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;; - *) echo "$sbt_launch_repo/org.scala-sbt/sbt-launch/$version/sbt-launch.jar" ;; - esac -} +declare -r script_path="$(get_script_path "$BASH_SOURCE")" +declare -r script_name="${script_path##*/}" init_default_option_file () { local overriding_var="${!1}" @@ -101,98 +89,116 @@ init_default_option_file () { echo "$default_file" } -declare -r cms_opts="-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC" -declare -r jit_opts="-XX:ReservedCodeCacheSize=256m -XX:+TieredCompilation" -declare -r default_jvm_opts_common="-Xms512m -Xmx1536m -Xss2m $jit_opts $cms_opts" -declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" -declare -r latest_28="2.8.2" -declare -r latest_29="2.9.3" -declare -r latest_210="2.10.5" -declare -r latest_211="2.11.7" -declare -r latest_212="2.12.0-M3" - -declare -r script_path="$(get_script_path "$BASH_SOURCE")" -declare -r script_name="${script_path##*/}" - -# some non-read-onlies set with defaults -declare java_cmd="java" declare sbt_opts_file="$(init_default_option_file SBT_OPTS .sbtopts)" declare jvm_opts_file="$(init_default_option_file JVM_OPTS .jvmopts)" -declare sbt_launch_repo="http://repo.typesafe.com/typesafe/ivy-releases" -# pull -J and -D options to give to java. -declare -a residual_args -declare -a java_args -declare -a scalac_args -declare -a sbt_commands +build_props_sbt () { + [[ -r "$buildProps" ]] && \ + grep '^sbt\.version' "$buildProps" | tr '=\r' ' ' | awk '{ print $2; }' +} -# args to jvm/sbt via files or environment variables -declare -a extra_jvm_opts extra_sbt_opts +update_build_props_sbt () { + local ver="$1" + local old="$(build_props_sbt)" + + [[ -r "$buildProps" ]] && [[ "$ver" != "$old" ]] && { + perl -pi -e "s/^sbt\.version\b.*\$/sbt.version=${ver}/" "$buildProps" + grep -q '^sbt.version[ =]' "$buildProps" || printf "\nsbt.version=%s\n" "$ver" >> "$buildProps" + + vlog "!!!" + vlog "!!! Updated file $buildProps setting sbt.version to: $ver" + vlog "!!! Previous value was: $old" + vlog "!!!" + } +} + +set_sbt_version () { + sbt_version="${sbt_explicit_version:-$(build_props_sbt)}" + [[ -n "$sbt_version" ]] || sbt_version=$sbt_release_version + export sbt_version +} -addJava () { - vlog "[addJava] arg = '$1'" - java_args+=("$1") +url_base () { + local version="$1" + + case "$version" in + 0.7.*) echo "http://simple-build-tool.googlecode.com" ;; + 0.10.* ) echo "$sbt_launch_ivy_release_repo" ;; + 0.11.[12]) echo "$sbt_launch_ivy_release_repo" ;; + 0.*-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]) # ie "*-yyyymmdd-hhMMss" + echo "$sbt_launch_ivy_snapshot_repo" ;; + 0.*) echo "$sbt_launch_ivy_release_repo" ;; + *-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]) # ie "*-yyyymmdd-hhMMss" + echo "$sbt_launch_mvn_snapshot_repo" ;; + *) echo "$sbt_launch_mvn_release_repo" ;; + esac } -addSbt () { - vlog "[addSbt] arg = '$1'" - sbt_commands+=("$1") + +make_url () { + local version="$1" + + local base="${sbt_launch_repo:-$(url_base "$version")}" + + case "$version" in + 0.7.*) echo "$base/files/sbt-launch-0.7.7.jar" ;; + 0.10.* ) echo "$base/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;; + 0.11.[12]) echo "$base/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;; + 0.*) echo "$base/org.scala-sbt/sbt-launch/$version/sbt-launch.jar" ;; + *) echo "$base/org/scala-sbt/sbt-launch/$version/sbt-launch.jar" ;; + esac } + +addJava () { vlog "[addJava] arg = '$1'" ; java_args+=("$1"); } +addSbt () { vlog "[addSbt] arg = '$1'" ; sbt_commands+=("$1"); } +addScalac () { vlog "[addScalac] arg = '$1'" ; scalac_args+=("$1"); } +addResidual () { vlog "[residual] arg = '$1'" ; residual_args+=("$1"); } + +addResolver () { addSbt "set resolvers += $1"; } +addDebugger () { addJava "-Xdebug" ; addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1"; } setThisBuild () { vlog "[addBuild] args = '$@'" local key="$1" && shift addSbt "set $key in ThisBuild := $@" } -addScalac () { - vlog "[addScalac] arg = '$1'" - scalac_args+=("$1") -} -addResidual () { - vlog "[residual] arg = '$1'" - residual_args+=("$1") -} -addResolver () { - addSbt "set resolvers += $1" -} -addDebugger () { - addJava "-Xdebug" - addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1" -} setScalaVersion () { [[ "$1" == *"-SNAPSHOT" ]] && addResolver 'Resolver.sonatypeRepo("snapshots")' addSbt "++ $1" } setJavaHome () { java_cmd="$1/bin/java" - setThisBuild javaHome "Some(file(\"$1\"))" + setThisBuild javaHome "_root_.scala.Some(file(\"$1\"))" export JAVA_HOME="$1" export JDK_HOME="$1" export PATH="$JAVA_HOME/bin:$PATH" } -setJavaHomeQuietly () { - addSbt warn - setJavaHome "$1" - addSbt info -} -# if set, use JDK_HOME/JAVA_HOME over java found in path -if [[ -e "$JDK_HOME/lib/tools.jar" ]]; then - setJavaHomeQuietly "$JDK_HOME" -elif [[ -e "$JAVA_HOME/bin/java" ]]; then - setJavaHomeQuietly "$JAVA_HOME" -fi +getJavaVersion() { "$1" -version 2>&1 | grep -E -e '(java|openjdk) version' | awk '{ print $3 }' | tr -d \"; } -# directory to store sbt launchers -declare sbt_launch_dir="$HOME/.sbt/launchers" -[[ -d "$sbt_launch_dir" ]] || mkdir -p "$sbt_launch_dir" -[[ -w "$sbt_launch_dir" ]] || sbt_launch_dir="$(mktemp -d -t sbt_extras_launchers.XXXXXX)" +checkJava() { + # Warn if there is a Java version mismatch between PATH and JAVA_HOME/JDK_HOME + + [[ -n "$JAVA_HOME" && -e "$JAVA_HOME/bin/java" ]] && java="$JAVA_HOME/bin/java" + [[ -n "$JDK_HOME" && -e "$JDK_HOME/lib/tools.jar" ]] && java="$JDK_HOME/bin/java" + + if [[ -n "$java" ]]; then + pathJavaVersion=$(getJavaVersion java) + homeJavaVersion=$(getJavaVersion "$java") + if [[ "$pathJavaVersion" != "$homeJavaVersion" ]]; then + echoerr "Warning: Java version mismatch between PATH and JAVA_HOME/JDK_HOME, sbt will use the one in PATH" + echoerr " Either: fix your PATH, remove JAVA_HOME/JDK_HOME or use -java-home" + echoerr " java version from PATH: $pathJavaVersion" + echoerr " java version from JAVA_HOME/JDK_HOME: $homeJavaVersion" + fi + fi +} java_version () { - local version=$("$java_cmd" -version 2>&1 | grep -E -e '(java|openjdk) version' | awk '{ print $3 }' | tr -d \") + local version=$(getJavaVersion "$java_cmd") vlog "Detected Java version: $version" echo "${version:2:1}" } -# MaxPermSize critical on pre-8 jvms but incurs noisy warning on 8+ +# MaxPermSize critical on pre-8 JVMs but incurs noisy warning on 8+ default_jvm_opts () { local v="$(java_version)" if [[ $v -ge 8 ]]; then @@ -225,16 +231,23 @@ execRunner () { vlog "" } - [[ -n "$batch" ]] && exec /dev/null; then curl --fail --silent --location "$url" --output "$jar" elif which wget >/dev/null; then - wget --quiet -O "$jar" "$url" + wget -q -O "$jar" "$url" fi } && [[ -r "$jar" ]] } acquire_sbt_jar () { - sbt_url="$(jar_url "$sbt_version")" - sbt_jar="$(jar_file "$sbt_version")" - - [[ -r "$sbt_jar" ]] || download_url "$sbt_url" "$sbt_jar" + { + sbt_jar="$(jar_file "$sbt_version")" + [[ -r "$sbt_jar" ]] + } || { + sbt_jar="$HOME/.ivy2/local/org.scala-sbt/sbt-launch/$sbt_version/jars/sbt-launch.jar" + [[ -r "$sbt_jar" ]] + } || { + sbt_jar="$(jar_file "$sbt_version")" + download_url "$(make_url "$sbt_version")" "$sbt_jar" + } } usage () { + set_sbt_version cat < Turn on JVM debugging, open at the given port. -batch Disable interactive mode -prompt Set the sbt prompt; in expr, 's' is the State and 'e' is Extracted + -script Run the specified file as a scala script # sbt version (default: sbt.version from $buildProps if present, otherwise $sbt_release_version) -sbt-force-latest force the use of the latest release of sbt: $sbt_release_version -sbt-version use the specified version of sbt (default: $sbt_release_version) -sbt-dev use the latest pre-release version of sbt: $sbt_unreleased_version -sbt-jar use the specified jar as the sbt launcher - -sbt-launch-dir directory to hold sbt launchers (default: ~/.sbt/launchers) - -sbt-launch-repo repo url for downloading sbt launcher jar (default: $sbt_launch_repo) + -sbt-launch-dir directory to hold sbt launchers (default: $sbt_launch_dir) + -sbt-launch-repo repo url for downloading sbt launcher jar (default: $(url_base "$sbt_version")) # scala version (default: as chosen by sbt) -28 use $latest_28 @@ -307,6 +328,7 @@ runner with the -x option. -210 use $latest_210 -211 use $latest_211 -212 use $latest_212 + -213 use $latest_213 -scala-home use the scala build at the specified directory -scala-version use the specified version of scala -binary-version use the specified scala version when searching for dependencies @@ -333,8 +355,7 @@ runner with the -x option. EOM } -process_args () -{ +process_args () { require_arg () { local type="$1" local opt="$2" @@ -346,11 +367,11 @@ process_args () } while [[ $# -gt 0 ]]; do case "$1" in - -h|-help) usage; exit 1 ;; + -h|-help) usage; exit 0 ;; -v) verbose=true && shift ;; - -d) addSbt "--debug" && addSbt debug && shift ;; - -w) addSbt "--warn" && addSbt warn && shift ;; - -q) addSbt "--error" && addSbt error && shift ;; + -d) addSbt "--debug" && shift ;; + -w) addSbt "--warn" && shift ;; + -q) addSbt "--error" && shift ;; -x) debugUs=true && shift ;; -trace) require_arg integer "$1" "$2" && trace_level="$2" && shift 2 ;; -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; @@ -359,10 +380,11 @@ process_args () -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; -sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;; -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; - -offline) addSbt "set offline := true" && shift ;; + -offline) addSbt "set offline in Global := true" && shift ;; -jvm-debug) require_arg port "$1" "$2" && addDebugger "$2" && shift 2 ;; -batch) batch=true && shift ;; -prompt) require_arg "expr" "$1" "$2" && setThisBuild shellPrompt "(s => { val e = Project.extract(s) ; $2 })" && shift 2 ;; + -script) require_arg file "$1" "$2" && sbt_script="$2" && addJava "-Dsbt.main.class=sbt.ScriptMain" && shift 2 ;; -sbt-create) sbt_create=true && shift ;; -sbt-jar) require_arg path "$1" "$2" && sbt_jar="$2" && shift 2 ;; @@ -373,7 +395,7 @@ process_args () -sbt-launch-repo) require_arg path "$1" "$2" && sbt_launch_repo="$2" && shift 2 ;; -scala-version) require_arg version "$1" "$2" && setScalaVersion "$2" && shift 2 ;; -binary-version) require_arg version "$1" "$2" && setThisBuild scalaBinaryVersion "\"$2\"" && shift 2 ;; - -scala-home) require_arg path "$1" "$2" && setThisBuild scalaHome "Some(file(\"$2\"))" && shift 2 ;; + -scala-home) require_arg path "$1" "$2" && setThisBuild scalaHome "_root_.scala.Some(file(\"$2\"))" && shift 2 ;; -java-home) require_arg path "$1" "$2" && setJavaHome "$2" && shift 2 ;; -sbt-opts) require_arg path "$1" "$2" && sbt_opts_file="$2" && shift 2 ;; -jvm-opts) require_arg path "$1" "$2" && jvm_opts_file="$2" && shift 2 ;; @@ -386,10 +408,8 @@ process_args () -210) setScalaVersion "$latest_210" && shift ;; -211) setScalaVersion "$latest_211" && shift ;; -212) setScalaVersion "$latest_212" && shift ;; - - --debug) addSbt debug && addResidual "$1" && shift ;; - --warn) addSbt warn && addResidual "$1" && shift ;; - --error) addSbt error && addResidual "$1" && shift ;; + -213) setScalaVersion "$latest_213" && shift ;; + new) sbt_new=true && : ${sbt_explicit_version:=$sbt_release_version} && addResidual "$1" && shift ;; *) addResidual "$1" && shift ;; esac done @@ -400,8 +420,10 @@ process_args "$@" # skip #-styled comments and blank lines readConfigFile() { - while read line; do - [[ $line =~ ^# ]] || [[ -z $line ]] || echo "$line" + local end=false + until $end; do + read || end=true + [[ $REPLY =~ ^# ]] || [[ -z $REPLY ]] || echo "$REPLY" done < "$1" } @@ -426,6 +448,8 @@ argumentCount=$# # set sbt version set_sbt_version +checkJava + # only exists in 0.12+ setTraceLevel() { case "$sbt_version" in @@ -438,19 +462,21 @@ setTraceLevel() { [[ ${#scalac_args[@]} -eq 0 ]] || addSbt "set scalacOptions in ThisBuild += \"${scalac_args[@]}\"" # Update build.properties on disk to set explicit version - sbt gives us no choice -[[ -n "$sbt_explicit_version" ]] && update_build_props_sbt "$sbt_explicit_version" +[[ -n "$sbt_explicit_version" && -z "$sbt_new" ]] && update_build_props_sbt "$sbt_explicit_version" vlog "Detected sbt version $sbt_version" -[[ -n "$scala_version" ]] && vlog "Overriding scala version to $scala_version" - -# no args - alert them there's stuff in here -(( argumentCount > 0 )) || { - vlog "Starting $script_name: invoke with -help for other options" - residual_args=( shell ) -} +if [[ -n "$sbt_script" ]]; then + residual_args=( $sbt_script ${residual_args[@]} ) +else + # no args - alert them there's stuff in here + (( argumentCount > 0 )) || { + vlog "Starting $script_name: invoke with -help for other options" + residual_args=( shell ) + } +fi -# verify this is an sbt dir or -create was given -[[ -r ./build.sbt || -d ./project || -n "$sbt_create" ]] || { +# verify this is an sbt dir, -create was given or user attempts to run a scala script +[[ -r ./build.sbt || -d ./project || -n "$sbt_create" || -n "$sbt_script" || -n "$sbt_new" ]] || { cat < Date: Tue, 28 Nov 2017 22:23:28 -0800 Subject: [PATCH 070/417] Upgrade sbt-coursier to avoid IncompatibleClassChangeError in Java9 https://github.com/coursier/coursier/pull/678 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 4b0d461c7..4e683911c 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,7 +5,7 @@ addSbtPlugin("com.github.sbt" % "sbt-findbugs" % "2.0.0") addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.0.3") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.0") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.2") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC12") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC13") addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.3.0") scalacOptions ++= Seq("-deprecation", "-feature") From d379d0c32ba013ddb61b83c37575357471a005e1 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Nov 2017 22:33:06 -0800 Subject: [PATCH 071/417] Remove java7 test because sbt 1.0.x no longer works with Java7 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6c49f5f9d..edfa6458c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ cache: sudo: false jdk: - - openjdk7 - oraclejdk8 branches: From 3e3dfc9714525ff7c73f24aa6a51e98dab766e06 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Nov 2017 22:39:18 -0800 Subject: [PATCH 072/417] Split build into checkstyle, java8/9 build and test --- .travis.yml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index edfa6458c..6d24c3a95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,21 +9,23 @@ cache: sudo: false -jdk: - - oraclejdk8 - branches: only: - develop -script: - - ./sbt jcheckStyle - - ./sbt test - - ./sbt test -J-Dmsgpack.universal-buffer=true - matrix: include: - - dist: trusty + - env: PROJECT=checkstyle + jdk: oraclejdk8 + script: + - ./sbt jcheckStyle + - env: PROJECT=java8 + jdk: oraclejdk8 + script: + - ./sbt test + - ./sbt test -J-Dmsgpack.universal-buffer=true + - env: PROJECT=java9 + dist: trusty group: edge sudo: required jdk: oraclejdk9 @@ -33,4 +35,4 @@ matrix: - oracle-java9-installer script: - ./sbt test - - ./sbt -Dmsgpack.universal-buffer=true test + - ./sbt test -J-Dmsgpack.universal-buffer=true From 49ac4957f1b36c1e820407599d90dbfd7665c020 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Nov 2017 23:12:06 -0800 Subject: [PATCH 073/417] Add note on scalafmt usage --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 021c144a5..f46136f68 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Here is a list of sbt commands for daily development: > findbugs # Produce findbugs report in target/findbugs > jacoco:cover # Report the code coverage of tests to target/jacoco folder > jcheckStyle # Run check style +> scalafmt # Reformat Scala codes ``` ### Publishing From 84666b65b5859c3d1e5e53c9a6b3112e5c9b4a72 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Nov 2017 23:20:30 -0800 Subject: [PATCH 074/417] Do not force checking performance improvement against v6 for Travis --- .../test/scala/org/msgpack/core/MessageUnpackerTest.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 5b214970c..0ec54aff7 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -592,8 +592,12 @@ class MessageUnpackerTest extends MessagePackSpec { } } - t("v7-array").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax - t("v7-array-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + if (t("v7-array").averageWithoutMinMax > t("v6").averageWithoutMinMax) { + warn(s"v7-array ${t("v7-array").averageWithoutMinMax} is slower than v6 ${t("v6").averageWithoutMinMax}") + } + if (t("v7-array-buffer").averageWithoutMinMax > t("v6").averageWithoutMinMax) { + warn(s"v7-array-buffer ${t("v7-array-buffer").averageWithoutMinMax} is slower than v6 ${t("v6").averageWithoutMinMax}") + } if (!universal) t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax From a51b520de77b109fb676904762def476cf03007f Mon Sep 17 00:00:00 2001 From: Ivan Sopov Date: Sat, 17 Jun 2017 20:30:11 +0300 Subject: [PATCH 075/417] Add MessageBufferPacker#getSize() Rename to getBufferSize() --- .../main/java/org/msgpack/core/MessageBufferPacker.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java index 38962dbe2..eac9ba7ac 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java @@ -123,4 +123,12 @@ public List toBufferList() } return getArrayBufferOut().toBufferList(); } + + /** + * @return the size of the buffer in use + */ + public int getBufferSize() + { + return getArrayBufferOut().getSize(); + } } From be6fce9360d90351a992862280234e5cf3f18cd5 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 29 Nov 2017 10:50:12 -0800 Subject: [PATCH 076/417] Add 0.8.14 release notes --- RELEASE_NOTES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 31b3f0619..42148b152 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,13 @@ # Release Notes +## 0.8.14 + * Add MessageUnpacker.tryUnpackNil() for peeking whether the next value is nil or not. + * Add MessageBufferPacker.getBufferSize(). + * Improved MessageUnpacker.readPayload performance [#436](https://github.com/msgpack/msgpack-java/pull/436) + * Fixed a bug that ChannelBufferInput#next blocks until the buffer is filled. [#428](https://github.com/msgpack/msgpack-java/pull/428) + * (internal) Upgraded to sbt-1.0.4 for better Java9 support + * (internal) Dropped Java7 tests on TravisCI, but msgpack-java is still built for Java7 (1.7) target + ## 0.8.13 * Fix ambiguous overload in Java 9 [#415](https://github.com/msgpack/msgpack-java/pull/415) * Make MessagePackParser accept a string as a byte array field [#420](https://github.com/msgpack/msgpack-java/pull/420) From 3b5536e20650ea8ed4bc5190703ad5c4fd0fc145 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 29 Nov 2017 11:45:29 -0800 Subject: [PATCH 077/417] Setting version to 0.8.14 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 35fa32f46..dc6fa546b 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.14-SNAPSHOT" \ No newline at end of file +version in ThisBuild := "0.8.14" From 8a02b550973e700597d27a23dad45a173d420e58 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 29 Nov 2017 11:47:03 -0800 Subject: [PATCH 078/417] Add publishTo settings --- build.sbt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build.sbt b/build.sbt index bdeeef21a..13b3dfb8d 100644 --- a/build.sbt +++ b/build.sbt @@ -43,6 +43,13 @@ val buildSettings = Seq[Setting[_]]( releaseStepCommand("sonatypeReleaseAll"), pushChanges ), + // Add sonatype repository settings + publishTo := Some( + if (isSnapshot.value) + Opts.resolver.sonatypeSnapshots + else + Opts.resolver.sonatypeStaging + ), // Find bugs findbugsReportType := Some(FindbugsReport.FancyHtml), findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html"), From f0b87b28cd1dab2bb12f9928eff338386f8abc91 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 29 Nov 2017 11:50:04 -0800 Subject: [PATCH 079/417] Setting version to 0.8.15-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index dc6fa546b..ae9b6f3f6 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.14" +version in ThisBuild := "0.8.15-SNAPSHOT" From eecaf29d27e9f3f6da4e62d5bbff280f9ab2b3cb Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Thu, 30 Nov 2017 15:29:28 +0900 Subject: [PATCH 080/417] "test-only" does not work since sbt 1.0 https://github.com/sbt/sbt/blob/v1.0.4/notes/1.0.0.markdown > Drops sbt 0.12 style hyphen-separated key names --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f46136f68..65a9681a1 100644 --- a/README.md +++ b/README.md @@ -67,8 +67,8 @@ Here is a list of sbt commands for daily development: > ~compile # Compile source codes > ~test:compile # Compile both source and test codes > ~test # Run tests upon source code change -> ~test-only *MessagePackTest # Run tests in the specified class -> ~test-only *MessagePackTest -- -n prim # Run the test tagged as "prim" +> ~testOnly *MessagePackTest # Run tests in the specified class +> ~testOnly *MessagePackTest -- -n prim # Run the test tagged as "prim" > project msgpack-core # Focus on a specific project > package # Create a jar file in the target folder of each project > findbugs # Produce findbugs report in target/findbugs From 6f08e724b7955b976cfe12ea99180451a779528a Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Thu, 30 Nov 2017 15:43:24 +0900 Subject: [PATCH 081/417] use JavaConverters instead of JavaConversions JavaConversions is deprecated since Scala 2.12 https://github.com/scala/scala/blob/v2.12.4/src/library/scala/collection/JavaConversions.scala#L59 --- .../src/test/scala/org/msgpack/core/MessagePackTest.scala | 4 ++-- .../test/scala/org/msgpack/core/MessageUnpackerTest.scala | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index f6b41bf34..2d2f1d1f6 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -562,8 +562,8 @@ class MessagePackTest extends MessagePackSpec { }, { unpacker => val v = new Variable() unpacker.unpackValue(v) - import scala.collection.JavaConversions._ - v.asArrayValue() + import scala.collection.JavaConverters._ + v.asArrayValue().asScala .map { m => val mv = m.asMapValue() val kvs = mv.getKeyValueArray diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 0ec54aff7..c2c738515 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -23,7 +23,7 @@ import org.msgpack.core.buffer._ import org.msgpack.value.ValueType import xerial.core.io.IOUtil._ -import scala.collection.JavaConversions._ +import scala.collection.JavaConverters._ import scala.util.Random object MessageUnpackerTest { @@ -229,10 +229,10 @@ class MessageUnpackerTest extends MessagePackSpec { position += length } val builder = Seq.newBuilder[MessageUnpacker] - builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqBytes.result()))) - builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqByteBuffers.result()))) + builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqBytes.result().asJava))) + builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqByteBuffers.result().asJava))) if (!universal) { - builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqDirectBuffers.result()))) + builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqDirectBuffers.result().asJava))) } builder.result() From 04ddb33a29f0c148563293ac770dfa7e6c391c01 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Mon, 18 Dec 2017 00:35:23 +0900 Subject: [PATCH 082/417] Adding some advanced usages --- msgpack-jackson/README.md | 248 +++++++++++++++++++++++++++++++++++--- 1 file changed, 231 insertions(+), 17 deletions(-) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 2851df0c5..4e3b51c80 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -3,9 +3,12 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.msgpack/jackson-dataformat-msgpack/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.msgpack/jackson-dataformat-msgpack/) [![Javadoc](https://javadoc-emblem.rhcloud.com/doc/org.msgpack/jackson-dataformat-msgpack/badge.svg)](http://www.javadoc.io/doc/org.msgpack/jackson-dataformat-msgpack) -This Jackson extension library handles reading and writing of data encoded in [MessagePack](http://msgpack.org/) data format. +This Jackson extension library is a component to easily read and write [MessagePack](http://msgpack.org/) encoded data through jackson-databind API. + It extends standard Jackson streaming API (`JsonFactory`, `JsonParser`, `JsonGenerator`), and as such works seamlessly with all the higher level data abstractions (data binding, tree model, and pluggable extensions). For the details of Jackson-annotations, please see https://github.com/FasterXML/jackson-annotations. +This library, strictly speaking jackson-databind, isn't compatibile with msgpack-java v0.6 or earlier in serialization/deserialization of POJO. + ## Install ### Maven @@ -36,23 +39,66 @@ dependencies { ``` -## Usage +## Basic usage + +### Serialization/Deserialization of POJO -Only thing you need to do is to instantiate MessagePackFactory and pass it to the constructor of ObjectMapper. +Only thing you need to do is to instantiate `MessagePackFactory` and pass it to the constructor of `com.fasterxml.jackson.databind.ObjectMapper`. And then, you can use it for MessagePack format data in the same way as jackson-databind. +```java + // Instantiate ObjectMapper for MessagePack + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + + // Serialize a Java object to byte array + ExamplePojo pojo = new ExamplePojo("komamitsu"); + byte[] bytes = objectMapper.writeValueAsBytes(pojo); + + // Deserialize the byte array to a Java object + ExamplePojo deserialized = objectMapper.readValue(bytes, ExamplePojo.class); + System.out.println(deserialized.getName()); // => komamitsu ``` + +### Serialization/Deserialization of List + +```java + // Instantiate ObjectMapper for MessagePack ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - ExamplePojo orig = new ExamplePojo("komamitsu"); - byte[] bytes = objectMapper.writeValueAsBytes(orig); - ExamplePojo value = objectMapper.readValue(bytes, ExamplePojo.class); - System.out.println(value.getName()); // => komamitsu + + // Serialize a List to byte array + List list = new ArrayList<>(); + list.add("Foo"); + list.add("Bar"); + list.add(42); + byte[] bytes = objectMapper.writeValueAsBytes(list); + + // Deserialize the byte array to a List + List deserialized = objectMapper.readValue(bytes, new TypeReference>() {}); + System.out.println(deserialized); // => [Foo, Bar, 42] ``` -Also, you can exchange data among multiple languages. +### Serialization/Deserialization of Map + +```java + // Instantiate ObjectMapper for MessagePack + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + + // Serialize a Map to byte array + Map map = new HashMap<>(); + map.put("name", "komamitsu"); + map.put("age", 42); + byte[] bytes = objectMapper.writeValueAsBytes(map); + + // Deserialize the byte array to a Map + Map deserialized = objectMapper.readValue(bytes, new TypeReference>() {}); + System.out.println(deserialized); // => {name=komamitsu, age=42} + + ``` + +### Example of Serialization/Deserialization over multiple languages Java -``` +```java // Serialize Map obj = new HashMap(); obj.put("foo", "hello"); @@ -64,7 +110,7 @@ Java Ruby -``` +```ruby require 'msgpack' # Deserialize @@ -80,7 +126,7 @@ Ruby Java -``` +```java // Deserialize bs = new byte[] {(byte) 148, (byte) 164, 122, 101, 114, 111, 1, (byte) 203, 64, 0, 0, 0, 0, 0, 0, 0, (byte) 192}; @@ -89,15 +135,183 @@ Java // xs => [zero, 1, 2.0, null] ``` -### Serialization format +## Advanced usage -By default, the serialization format is object, which means it includes the schema of the serialized entity (POJO). -To serialize an entity without the schema, only as array, you can add the annotation `@JsonFormat(shape=JsonFormat.Shape.ARRAY)` to the entity definition. -Also, it's possible to set the serialization format for the object mapper instance to be array by changing the annotation inspector of object mapper to `JsonArrayFormat`: +### Serialize/Deserialize POJO as MessagePack array type to keep compatibility with msgpack-java:0.6 -``` +In msgpack-java:0.6 or earlier, a POJO was serliazed and deserialized as an array of values in MessagePack format. The order of values depended on an internal order of a Java class's variables and it was a naive way and caused some issues since Java class's variables order isn't guaranteed over Java implementations. + +On the other hand, jackson-databind serializes and deserializes a POJO as a key-value object. So this `jackson-dataformat-msgpack` also handles POJOs in the same way. As a result, it isn't compatible with msgpack-java:0.6 or earlier in serialization and deserialization of POJOs. + +But if you want to make this library handle POJOs in the same way as msgpack-java:0.6 or earlier, you can use `JsonArrayFormat` like this: + +```java ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); ``` -This format provides compatibility with msgpack-java 0.6.x serialization api. +### Serialize multiple values without closing an output stream + +`com.fasterxml.jackson.databind.ObjectMapper` closes an output stream by default after it writes a value. If you want to serialize multiple values in a row without closing an output stream, set `JsonGenerator.Feature.AUTO_CLOSE_TARGET` to false. + +```java + OutputStream out = new FileOutputStream(tempFile); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + + objectMapper.writeValue(out, 1); + objectMapper.writeValue(out, "two"); + objectMapper.writeValue(out, 3.14); + out.close(); + + MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(new FileInputStream(tempFile)); + System.out.println(unpacker.unpackInt()); // => 1 + System.out.println(unpacker.unpackString()); // => two + System.out.println(unpacker.unpackFloat()); // => 3.14 +``` + +### Deserialize multiple values without closing an input stream + +`com.fasterxml.jackson.databind.ObjectMapper` closes an input stream by default after it reads a value. If you want to deserialize multiple values in a row witout closing an output stream, set `JsonParser.Feature.AUTO_CLOSE_SOURCE` to false. + +```java + MessagePacker packer = MessagePack.newDefaultPacker(new FileOutputStream(tempFile)); + packer.packInt(42); + packer.packString("Hello"); + packer.close(); + + FileInputStream in = new FileInputStream(tempFile); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); + System.out.println(objectMapper.readValue(in, Integer.class)); + System.out.println(objectMapper.readValue(in, String.class)); + in.close(); +``` + +### Serialize not using str8 type + +Old msgpack-java (e.g 0.6.7) doesn't support MessagePack str8 type. When your application needs to comunicate with such an old MessagePack library, you can disable the data type like this: + +```java + MessagePack.PackerConfig config = new MessagePack.PackerConfig().withStr8FormatSupport(false); + ObjectMapper mapperWithConfig = new ObjectMapper(new MessagePackFactory(config)); + // This string is serialized as bin8 type + byte[] resultWithoutStr8Format = mapperWithConfig.writeValueAsBytes(str8LengthString); +``` + +### Serialize using non-String as a key of Map + +When you want to use non-String value as a key of Map, use `MessagePackKeySerializer` for key serialization. + +```java + @JsonSerialize(keyUsing = MessagePackKeySerializer.class) + private Map intMap = new HashMap<>(); + + : + { + intMap.put(42, "Hello"); + + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + byte[] bytes = objectMapper.writeValueAsBytes(intMap); + + Map deserialized = objectMapper.readValue(bytes, new TypeReference>() {}); + System.out.println(deserialized); // => {42=Hello} + } +``` + +### Deserialize extension types with ExtensionTypeCustomDeserializers + +`ExtensionTypeCustomDeserializers` helps you to deserialize extension types. + +#### With target Java class + +```java + NestedListComplexPojo parent = new NestedListComplexPojo(); + parent.children = Arrays.asList(new TinyPojo("Foo"), new TinyPojo("Bar")); + + // In this application, extension type 17 is used for NestedListComplexPojo + byte[] bytes; + { + // This ObjectMapper is just for temporary serialization + ObjectMapper tempObjectMapper = new ObjectMapper(new MessagePackFactory()); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + MessagePacker packer = MessagePack.newDefaultPacker(outputStream); + + byte[] extBytes = tempObjectMapper.writeValueAsBytes(parent); + packer.packExtensionTypeHeader((byte) 17, extBytes.length); + packer.addPayload(extBytes); + packer.close(); + + bytes = outputStream.toByteArray(); + } + + // Register the type and the class to ExtensionTypeCustomDeserializers + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addTargetClass((byte) 17, NestedListComplexPojo.class); + ObjectMapper objectMapper = new ObjectMapper( + new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); + + System.out.println(objectMapper.readValue(bytes, Object.class)); + // => NestedListComplexPojo{children=[TinyPojo{name='Foo'}, TinyPojo{name='Bar'}]} +``` + +#### With type reference + +```java + Map map = new HashMap<>(); + map.put("one", 1); + map.put("two", 2); + + // In this application, extension type 31 is used for Map + byte[] bytes; + { + // Same as above + : + packer.packExtensionTypeHeader((byte) 31, extBytes.length); + : + } + + // Register the type and the type reference to ExtensionTypeCustomDeserializers + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addTargetTypeReference((byte) 31, + new TypeReference>() {}); + ObjectMapper objectMapper = new ObjectMapper( + new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); + + System.out.println(objectMapper.readValue(bytes, Object.class)); + // => {one=1, two=2} +``` + +#### With custom deserializer + +```java + // In this application, extension type 59 is used for byte[] + byte[] bytes; + { + // This ObjectMapper is just for temporary serialization + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + MessagePacker packer = MessagePack.newDefaultPacker(outputStream); + + packer.packExtensionTypeHeader((byte) 59, hexspeak.length); + packer.addPayload(hexspeak); + packer.close(); + + bytes = outputStream.toByteArray(); + } + + // Register the type and a deserializer to ExtensionTypeCustomDeserializers + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addCustomDeser((byte) 59, data -> { + if (Arrays.equals(data, + new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE})) { + return "Java"; + } + return "Not Java"; + } + ); + ObjectMapper objectMapper = new ObjectMapper( + new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); + + System.out.println(objectMapper.readValue(bytes, Object.class)); + // => Java +``` From 6389f8da0db75bc20452ccbce65d128b3c01d4b2 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 21 Dec 2017 00:49:45 +0900 Subject: [PATCH 083/417] Update README.md --- msgpack-jackson/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 4e3b51c80..e65bd8789 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -7,7 +7,7 @@ This Jackson extension library is a component to easily read and write [MessageP It extends standard Jackson streaming API (`JsonFactory`, `JsonParser`, `JsonGenerator`), and as such works seamlessly with all the higher level data abstractions (data binding, tree model, and pluggable extensions). For the details of Jackson-annotations, please see https://github.com/FasterXML/jackson-annotations. -This library, strictly speaking jackson-databind, isn't compatibile with msgpack-java v0.6 or earlier in serialization/deserialization of POJO. +This library, strictly speaking jackson-databind, isn't compatibile with msgpack-java v0.6 or earlier in serialization/deserialization of POJO. See **Advanced usage** below for details. ## Install From cece5d26209144a341cffb18a8a7814cc35ed0aa Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 21 Dec 2017 11:37:51 +0900 Subject: [PATCH 084/417] Update README.md --- msgpack-jackson/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index e65bd8789..8a24178a4 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -7,7 +7,7 @@ This Jackson extension library is a component to easily read and write [MessageP It extends standard Jackson streaming API (`JsonFactory`, `JsonParser`, `JsonGenerator`), and as such works seamlessly with all the higher level data abstractions (data binding, tree model, and pluggable extensions). For the details of Jackson-annotations, please see https://github.com/FasterXML/jackson-annotations. -This library, strictly speaking jackson-databind, isn't compatibile with msgpack-java v0.6 or earlier in serialization/deserialization of POJO. See **Advanced usage** below for details. +This library isn't compatibile with msgpack-java v0.6 or earlier by default in serialization/deserialization of POJO. See **Advanced usage** below for details. ## Install From 40ac58a3488f7fa503b9d16a2483da07a49a424e Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 21 Dec 2017 11:42:34 +0900 Subject: [PATCH 085/417] Update README.md Minor change and fix typo --- msgpack-jackson/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 8a24178a4..33f58b68c 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -139,7 +139,7 @@ Java ### Serialize/Deserialize POJO as MessagePack array type to keep compatibility with msgpack-java:0.6 -In msgpack-java:0.6 or earlier, a POJO was serliazed and deserialized as an array of values in MessagePack format. The order of values depended on an internal order of a Java class's variables and it was a naive way and caused some issues since Java class's variables order isn't guaranteed over Java implementations. +In msgpack-java:0.6 or earlier, a POJO was serliazed and deserialized as an array of values in MessagePack format. The order of values depended on an internal order of Java class's variables and it was a naive way and caused some issues since Java class's variables order isn't guaranteed over Java implementations. On the other hand, jackson-databind serializes and deserializes a POJO as a key-value object. So this `jackson-dataformat-msgpack` also handles POJOs in the same way. As a result, it isn't compatible with msgpack-java:0.6 or earlier in serialization and deserialization of POJOs. @@ -172,7 +172,7 @@ But if you want to make this library handle POJOs in the same way as msgpack-jav ### Deserialize multiple values without closing an input stream -`com.fasterxml.jackson.databind.ObjectMapper` closes an input stream by default after it reads a value. If you want to deserialize multiple values in a row witout closing an output stream, set `JsonParser.Feature.AUTO_CLOSE_SOURCE` to false. +`com.fasterxml.jackson.databind.ObjectMapper` closes an input stream by default after it reads a value. If you want to deserialize multiple values in a row without closing an output stream, set `JsonParser.Feature.AUTO_CLOSE_SOURCE` to false. ```java MessagePacker packer = MessagePack.newDefaultPacker(new FileOutputStream(tempFile)); @@ -221,7 +221,7 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial ### Deserialize extension types with ExtensionTypeCustomDeserializers -`ExtensionTypeCustomDeserializers` helps you to deserialize extension types. +`ExtensionTypeCustomDeserializers` helps you to deserialize extension types easily. #### With target Java class From 382113ec1cde81193966617c593196ee1e5abb43 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Wed, 10 Jan 2018 11:43:47 +0900 Subject: [PATCH 086/417] update sbt plugins scalafmt plugin commands changed. see - https://github.com/scalameta/scalafmt/pull/1085 - https://github.com/scalameta/scalafmt/blob/v1.4.0/scalafmt-sbt/src/main/scala/org/scalafmt/sbt/ScalafmtPlugin.scala#L18-L32 --- README.md | 2 +- project/plugins.sbt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 65a9681a1..ea4cb1b1e 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Here is a list of sbt commands for daily development: > findbugs # Produce findbugs report in target/findbugs > jacoco:cover # Report the code coverage of tests to target/jacoco folder > jcheckStyle # Run check style -> scalafmt # Reformat Scala codes +> ;scalafmt;test:scalafmt;scalafmtSbt # Reformat Scala codes ``` ### Publishing diff --git a/project/plugins.sbt b/project/plugins.sbt index 4e683911c..a4fc6f318 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,11 +1,11 @@ -addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.6") +addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.7") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") addSbtPlugin("com.github.sbt" % "sbt-findbugs" % "2.0.0") addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.0.3") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.0") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.2") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC13") -addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.3.0") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0") +addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.4.0") scalacOptions ++= Seq("-deprecation", "-feature") From b82e4d37cd1895975e05ebd432364619f1d4434d Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 4 Feb 2018 23:48:20 +0900 Subject: [PATCH 087/417] Support ObjectMapper#copy with MessagePackFactory --- .../ExtensionTypeCustomDeserializers.java | 6 ++ .../dataformat/MessagePackFactory.java | 40 +++++++++++++ .../dataformat/MessagePackFactoryTest.java | 57 +++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java index 6d61ce53b..ef86ebbb8 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java @@ -32,6 +32,12 @@ public ExtensionTypeCustomDeserializers() objectMapper = new ObjectMapper(new MessagePackFactory().setReuseResourceInParser(false)); } + public ExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers src) + { + this(); + this.deserTable.putAll(src.deserTable); + } + public void addTargetClass(byte type, final Class klass) { deserTable.put(type, new Deser() diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index 11b5ee88f..a624b6b9d 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.io.IOContext; import org.msgpack.core.MessagePack; +import org.msgpack.core.annotations.VisibleForTesting; import java.io.File; import java.io.FileOutputStream; @@ -51,6 +52,15 @@ public MessagePackFactory(MessagePack.PackerConfig packerConfig) this.packerConfig = packerConfig; } + public MessagePackFactory(MessagePackFactory src) + { + super(src, null); + this.packerConfig = src.packerConfig.clone(); + this.reuseResourceInGenerator = src.reuseResourceInGenerator; + this.reuseResourceInParser = src.reuseResourceInParser; + this.extTypeCustomDesers = new ExtensionTypeCustomDeserializers(src.extTypeCustomDesers); + } + public MessagePackFactory setReuseResourceInGenerator(boolean reuseResourceInGenerator) { this.reuseResourceInGenerator = reuseResourceInGenerator; @@ -130,4 +140,34 @@ protected JsonParser _createParser(byte[] data, int offset, int len, IOContext c } return parser; } + + @Override + public JsonFactory copy() + { + return new MessagePackFactory(this); + } + + @VisibleForTesting + MessagePack.PackerConfig getPackerConfig() + { + return packerConfig; + } + + @VisibleForTesting + boolean isReuseResourceInGenerator() + { + return reuseResourceInGenerator; + } + + @VisibleForTesting + boolean isReuseResourceInParser() + { + return reuseResourceInParser; + } + + @VisibleForTesting + ExtensionTypeCustomDeserializers getExtTypeCustomDesers() + { + return extTypeCustomDesers; + } } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java index 25180f784..f9ce8629c 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java @@ -16,13 +16,26 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.core.JsonEncoding; +import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.AnnotationIntrospector; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; +import org.msgpack.core.MessagePack; import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; public class MessagePackFactoryTest extends MessagePackDataformatTestBase @@ -43,4 +56,48 @@ public void testCreateParser() JsonParser parser = factory.createParser(in); assertEquals(MessagePackParser.class, parser.getClass()); } + + @Test + public void copy() + throws IOException + { + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addTargetClass((byte) 42, TinyPojo.class); + + MessagePack.PackerConfig msgpackPackerConfig = new MessagePack.PackerConfig().withStr8FormatSupport(false); + + MessagePackFactory messagePackFactory = new MessagePackFactory(msgpackPackerConfig); + messagePackFactory.setExtTypeCustomDesers(extTypeCustomDesers); + + ObjectMapper objectMapper = new ObjectMapper(messagePackFactory); + + objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); + + objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); + + ObjectMapper copiedObjectMapper = objectMapper.copy(); + JsonFactory copiedFactory = copiedObjectMapper.getFactory(); + assertThat(copiedFactory, is(instanceOf(MessagePackFactory.class))); + MessagePackFactory copiedMessagePackFactory = (MessagePackFactory) copiedFactory; + + assertThat(copiedMessagePackFactory.getPackerConfig().isStr8FormatSupport(), is(false)); + + assertThat(copiedMessagePackFactory.getExtTypeCustomDesers().getDeser((byte) 42), is(notNullValue())); + assertThat(copiedMessagePackFactory.getExtTypeCustomDesers().getDeser((byte) 43), is(nullValue())); + + assertThat(copiedMessagePackFactory.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET), is(false)); + assertThat(copiedMessagePackFactory.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE), is(false)); + + Collection annotationIntrospectors = copiedObjectMapper.getSerializationConfig().getAnnotationIntrospector().allIntrospectors(); + assertThat(annotationIntrospectors.size(), is(1)); + assertThat(annotationIntrospectors.stream().findFirst().get(), is(instanceOf(JsonArrayFormat.class))); + + HashMap map = new HashMap<>(); + map.put("one", 1); + Map deserialized = copiedObjectMapper + .readValue(objectMapper.writeValueAsBytes(map), new TypeReference>() {}); + assertThat(deserialized.size(), is(1)); + assertThat(deserialized.get("one"), is(1)); + } } From c1f6a79d6c2936ba00109725a21604458b7d1ff1 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Wed, 7 Feb 2018 11:37:24 +0900 Subject: [PATCH 088/417] remove unnecessary settings in java 9 test --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6d24c3a95..19f8914ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,9 +25,6 @@ matrix: - ./sbt test - ./sbt test -J-Dmsgpack.universal-buffer=true - env: PROJECT=java9 - dist: trusty - group: edge - sudo: required jdk: oraclejdk9 addons: apt: From 9500d21363ed62c66ebf93c407b10a8e076e0c1f Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Wed, 7 Feb 2018 11:46:48 +0900 Subject: [PATCH 089/417] remove "-target:jvm-1.7" from scalacOptions Scala 2.12 does not support "-target:jvm-1.7" --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 13b3dfb8d..5cb1efaf6 100644 --- a/build.sbt +++ b/build.sbt @@ -15,7 +15,7 @@ val buildSettings = Seq[Setting[_]]( Tags.limit(Tags.Test, 1) ), // JVM options for building - scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-target:jvm-1.7", "-feature"), + scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-feature"), javaOptions in Test ++= Seq("-ea"), javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation", "-source", "1.7", "-target", "1.7"), // Use lenient validation mode when generating Javadoc (for Java8) From 6da87168d6ca6850d584a093caf0d188ffa154d5 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Wed, 7 Feb 2018 12:00:53 +0900 Subject: [PATCH 090/417] add SafeVarargs annotation suppress following warning https://travis-ci.org/msgpack/msgpack-java/jobs/337228566#L522 ``` [warn] /home/travis/build/msgpack/msgpack-java/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java:231:1: Possible heap pollution from parameterized vararg type java.util.Map.Entry [warn] public static MapValue newMap(Map.Entry... pairs) ``` --- msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java b/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java index 912dc55fb..5fc8f81fe 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java @@ -228,6 +228,7 @@ public static ImmutableMapValue emptyMap() return ImmutableMapValueImpl.empty(); } + @SafeVarargs public static MapValue newMap(Map.Entry... pairs) { Value[] kvs = new Value[pairs.length * 2]; From 41e7fe7b80823dead74133063dd5959a1347b126 Mon Sep 17 00:00:00 2001 From: Ivan Sopov Date: Mon, 12 Feb 2018 17:41:57 +0300 Subject: [PATCH 091/417] add MessagePacker.clear() method to clear position --- .../org/msgpack/core/MessageBufferPacker.java | 5 ++--- .../main/java/org/msgpack/core/MessagePacker.java | 8 ++++++++ .../msgpack/core/buffer/ArrayBufferOutput.java | 4 ++-- .../msgpack/core/MessageBufferPackerTest.scala | 15 +++++++++++++++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java index eac9ba7ac..71edc21d2 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java @@ -56,11 +56,10 @@ private ArrayBufferOutput getArrayBufferOut() return (ArrayBufferOutput) out; } - /** - * Clears the written data. - */ + @Override public void clear() { + super.clear(); getArrayBufferOut().clear(); } diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 7c6700bd3..ed7d90e92 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -260,6 +260,14 @@ public long getTotalWrittenBytes() return totalFlushBytes + position; } + /** + * Clears the written data. + */ + public void clear() + { + position = 0; + } + /** * Flushes internal buffer to the underlying output. *

      diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java index 955d48ad4..88fc0c92b 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java @@ -28,9 +28,9 @@ public class ArrayBufferOutput implements MessageBufferOutput { - private List list; + private final List list; + private final int bufferSize; private MessageBuffer lastBuffer; - private int bufferSize; public ArrayBufferOutput() { diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala index b8d2bd691..2194e42ea 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala @@ -16,6 +16,7 @@ package org.msgpack.core import java.io.ByteArrayOutputStream +import java.util.Arrays import org.msgpack.value.ValueFactory._ @@ -32,5 +33,19 @@ class MessageBufferPackerTest extends MessagePackSpec { packer1.toByteArray shouldBe stream.toByteArray } + + "clear unflushed" in { + val packer = MessagePack.newDefaultBufferPacker + packer.packInt(1); + packer.clear(); + packer.packInt(2); + + packer.toByteArray shouldBe Array(2) + val buffer = packer.toBufferList().get(0) + buffer.toByteArray() shouldBe Array(2) + val array = Arrays.copyOf(buffer.sliceAsByteBuffer().array(), buffer.size()) + array shouldBe Array(2) + } + } } From 6effc8cc516940be1d66f63f748af5d210248d81 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Tue, 20 Feb 2018 23:15:29 +0900 Subject: [PATCH 092/417] Update jackson-databind 2.7.9.1 to address https://github.com/FasterXML/jackson-databind/issues/1599 With 2.8.10, it degrades the serialization performance of jackson-dataformat-msgpack down to 62%. --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 5cb1efaf6..7eb70a456 100644 --- a/build.sbt +++ b/build.sbt @@ -115,7 +115,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.1", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.9.1", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 43a6e261cba50476c98e7e4bb3706816e8dda94d Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 22 Feb 2018 00:01:08 +0900 Subject: [PATCH 093/417] Use jackson-databind 2.8.11.1 for security vulnerability --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 7eb70a456..073cd4020 100644 --- a/build.sbt +++ b/build.sbt @@ -115,7 +115,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.9.1", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.1", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From e14deb2f15fa94687465a78b60d5842e85a29edb Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 16 Mar 2018 22:37:55 +0900 Subject: [PATCH 094/417] Add 0.8.15 release notes --- RELEASE_NOTES.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 42148b152..564fefcba 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,15 @@ # Release Notes +## 0.8.15 + * Suppress a warning in ValueFactory + * Add MessagePacker.clear() method to clear position + * Support ObjectMapper#copy with MessagePackFactory + * Use jackson-databind 2.8.11.1 for security vulnerability + * (internal) Remove "-target:jvm-1.7" from scalacOptions + * (internal) Replace sbt `test-only` command with `testOnly` + * (internal) Use JavaConverters instead of JavaConversions in unit tests + * (internal) Remove unnecessary settings for Java 9 test in .travis.yml + ## 0.8.14 * Add MessageUnpacker.tryUnpackNil() for peeking whether the next value is nil or not. * Add MessageBufferPacker.getBufferSize(). From 013d2c03b99c4fe44e7f0667983a993de80486a3 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 16 Mar 2018 22:50:43 +0900 Subject: [PATCH 095/417] Minor fixes --- RELEASE_NOTES.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 564fefcba..f69db7fc3 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,14 +1,13 @@ # Release Notes ## 0.8.15 - * Suppress a warning in ValueFactory - * Add MessagePacker.clear() method to clear position - * Support ObjectMapper#copy with MessagePackFactory - * Use jackson-databind 2.8.11.1 for security vulnerability - * (internal) Remove "-target:jvm-1.7" from scalacOptions - * (internal) Replace sbt `test-only` command with `testOnly` - * (internal) Use JavaConverters instead of JavaConversions in unit tests - * (internal) Remove unnecessary settings for Java 9 test in .travis.yml + * Suppress a warning in ValueFactory [#457](https://github.com/msgpack/msgpack-java/pull/457) + * Add MessagePacker#clear() method to clear position [#459](https://github.com/msgpack/msgpack-java/pull/459) + * Support ObjectMapper#copy with MessagePackFactory [#454](https://github.com/msgpack/msgpack-java/pull/454) + * Use jackson-databind 2.8.11.1 for security vulnerability [#467](https://github.com/msgpack/msgpack-java/pull/467) + * (internal) Remove "-target:jvm-1.7" from scalacOptions [#456](https://github.com/msgpack/msgpack-java/pull/456) + * (internal) Replace sbt `test-only` command with `testOnly` [#445](https://github.com/msgpack/msgpack-java/pull/445) + * (internal) Use JavaConverters instead of JavaConversions in unit tests [#446](https://github.com/msgpack/msgpack-java/pull/446) ## 0.8.14 * Add MessageUnpacker.tryUnpackNil() for peeking whether the next value is nil or not. From 0345ea1ed17756b27a3b5756192c34172450a1f3 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 16 Mar 2018 23:37:06 +0900 Subject: [PATCH 096/417] Setting version to 0.8.15 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index ae9b6f3f6..56ed83db7 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.15-SNAPSHOT" +version in ThisBuild := "0.8.15" From 1447f8fb2f720697ef0dab4371c52f75a64d51cc Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 16 Mar 2018 23:39:00 +0900 Subject: [PATCH 097/417] Setting version to 0.8.16-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 56ed83db7..77d6943c6 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.15" +version in ThisBuild := "0.8.16-SNAPSHOT" From 906a5fdb3b3f4c8496dd2c695c065e4844c0dc46 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 14 Apr 2018 15:37:40 +0900 Subject: [PATCH 098/417] Fix NPE at ObjectMapper#copy with MessagePackFactory --- .../dataformat/MessagePackFactory.java | 4 ++- .../dataformat/MessagePackFactoryTest.java | 32 ++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index a624b6b9d..225a33628 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -58,7 +58,9 @@ public MessagePackFactory(MessagePackFactory src) this.packerConfig = src.packerConfig.clone(); this.reuseResourceInGenerator = src.reuseResourceInGenerator; this.reuseResourceInParser = src.reuseResourceInParser; - this.extTypeCustomDesers = new ExtensionTypeCustomDeserializers(src.extTypeCustomDesers); + if (src.extTypeCustomDesers != null) { + this.extTypeCustomDesers = new ExtensionTypeCustomDeserializers(src.extTypeCustomDesers); + } } public MessagePackFactory setReuseResourceInGenerator(boolean reuseResourceInGenerator) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java index f9ce8629c..478b73a76 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import org.junit.Test; import org.msgpack.core.MessagePack; @@ -58,7 +59,36 @@ public void testCreateParser() } @Test - public void copy() + public void copyWithDefaultConfig() + throws IOException + { + MessagePackFactory messagePackFactory = new MessagePackFactory(); + ObjectMapper copiedObjectMapper = new ObjectMapper(messagePackFactory).copy(); + JsonFactory copiedFactory = copiedObjectMapper.getFactory(); + assertThat(copiedFactory, is(instanceOf(MessagePackFactory.class))); + MessagePackFactory copiedMessagePackFactory = (MessagePackFactory) copiedFactory; + + assertThat(copiedMessagePackFactory.getPackerConfig().isStr8FormatSupport(), is(true)); + + assertThat(copiedMessagePackFactory.getExtTypeCustomDesers(), is(nullValue())); + + assertThat(copiedMessagePackFactory.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET), is(true)); + assertThat(copiedMessagePackFactory.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE), is(true)); + + Collection annotationIntrospectors = copiedObjectMapper.getSerializationConfig().getAnnotationIntrospector().allIntrospectors(); + assertThat(annotationIntrospectors.size(), is(1)); + assertThat(annotationIntrospectors.stream().findFirst().get(), is(instanceOf(JacksonAnnotationIntrospector.class))); + + HashMap map = new HashMap<>(); + map.put("one", 1); + Map deserialized = copiedObjectMapper + .readValue(objectMapper.writeValueAsBytes(map), new TypeReference>() {}); + assertThat(deserialized.size(), is(1)); + assertThat(deserialized.get("one"), is(1)); + } + + @Test + public void copyWithAdvancedConfig() throws IOException { ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); From 5505124e618e4079daff17a32190ab595918d7f1 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 14 Apr 2018 22:26:47 +0900 Subject: [PATCH 099/417] Refactor the test --- .../dataformat/MessagePackFactoryTest.java | 112 ++++++++++-------- 1 file changed, 65 insertions(+), 47 deletions(-) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java index 478b73a76..c36360c52 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.ObjectMapper; @@ -58,76 +59,93 @@ public void testCreateParser() assertEquals(MessagePackParser.class, parser.getClass()); } - @Test - public void copyWithDefaultConfig() + private void assertCopy(boolean advancedConfig) throws IOException { - MessagePackFactory messagePackFactory = new MessagePackFactory(); - ObjectMapper copiedObjectMapper = new ObjectMapper(messagePackFactory).copy(); - JsonFactory copiedFactory = copiedObjectMapper.getFactory(); - assertThat(copiedFactory, is(instanceOf(MessagePackFactory.class))); - MessagePackFactory copiedMessagePackFactory = (MessagePackFactory) copiedFactory; + // Build base ObjectMapper + ObjectMapper objectMapper; + if (advancedConfig) { + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addTargetClass((byte) 42, TinyPojo.class); - assertThat(copiedMessagePackFactory.getPackerConfig().isStr8FormatSupport(), is(true)); + MessagePack.PackerConfig msgpackPackerConfig = new MessagePack.PackerConfig().withStr8FormatSupport(false); - assertThat(copiedMessagePackFactory.getExtTypeCustomDesers(), is(nullValue())); + MessagePackFactory messagePackFactory = new MessagePackFactory(msgpackPackerConfig); + messagePackFactory.setExtTypeCustomDesers(extTypeCustomDesers); - assertThat(copiedMessagePackFactory.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET), is(true)); - assertThat(copiedMessagePackFactory.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE), is(true)); + objectMapper = new ObjectMapper(messagePackFactory); - Collection annotationIntrospectors = copiedObjectMapper.getSerializationConfig().getAnnotationIntrospector().allIntrospectors(); - assertThat(annotationIntrospectors.size(), is(1)); - assertThat(annotationIntrospectors.stream().findFirst().get(), is(instanceOf(JacksonAnnotationIntrospector.class))); + objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); - HashMap map = new HashMap<>(); - map.put("one", 1); - Map deserialized = copiedObjectMapper - .readValue(objectMapper.writeValueAsBytes(map), new TypeReference>() {}); - assertThat(deserialized.size(), is(1)); - assertThat(deserialized.get("one"), is(1)); - } + objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); + } + else { + MessagePackFactory messagePackFactory = new MessagePackFactory(); + objectMapper = new ObjectMapper(messagePackFactory); + } - @Test - public void copyWithAdvancedConfig() - throws IOException - { - ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); - extTypeCustomDesers.addTargetClass((byte) 42, TinyPojo.class); + // Use the original ObjectMapper in advance + { + byte[] bytes = objectMapper.writeValueAsBytes(1234); + assertThat(objectMapper.readValue(bytes, Integer.class), is(1234)); + } - MessagePack.PackerConfig msgpackPackerConfig = new MessagePack.PackerConfig().withStr8FormatSupport(false); + // Copy the ObjectMapper + ObjectMapper copiedObjectMapper = objectMapper.copy(); - MessagePackFactory messagePackFactory = new MessagePackFactory(msgpackPackerConfig); - messagePackFactory.setExtTypeCustomDesers(extTypeCustomDesers); + // Assert the copied ObjectMapper + JsonFactory copiedFactory = copiedObjectMapper.getFactory(); + assertThat(copiedFactory, is(instanceOf(MessagePackFactory.class))); + MessagePackFactory copiedMessagePackFactory = (MessagePackFactory) copiedFactory; - ObjectMapper objectMapper = new ObjectMapper(messagePackFactory); + Collection annotationIntrospectors = + copiedObjectMapper.getSerializationConfig().getAnnotationIntrospector().allIntrospectors(); + assertThat(annotationIntrospectors.size(), is(1)); - objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); - objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); + if (advancedConfig) { + assertThat(copiedMessagePackFactory.getPackerConfig().isStr8FormatSupport(), is(false)); - objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); + assertThat(copiedMessagePackFactory.getExtTypeCustomDesers().getDeser((byte) 42), is(notNullValue())); + assertThat(copiedMessagePackFactory.getExtTypeCustomDesers().getDeser((byte) 43), is(nullValue())); - ObjectMapper copiedObjectMapper = objectMapper.copy(); - JsonFactory copiedFactory = copiedObjectMapper.getFactory(); - assertThat(copiedFactory, is(instanceOf(MessagePackFactory.class))); - MessagePackFactory copiedMessagePackFactory = (MessagePackFactory) copiedFactory; + assertThat(copiedMessagePackFactory.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET), is(false)); + assertThat(copiedMessagePackFactory.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE), is(false)); - assertThat(copiedMessagePackFactory.getPackerConfig().isStr8FormatSupport(), is(false)); + assertThat(annotationIntrospectors.stream().findFirst().get(), is(instanceOf(JsonArrayFormat.class))); + } + else { + assertThat(copiedMessagePackFactory.getPackerConfig().isStr8FormatSupport(), is(true)); - assertThat(copiedMessagePackFactory.getExtTypeCustomDesers().getDeser((byte) 42), is(notNullValue())); - assertThat(copiedMessagePackFactory.getExtTypeCustomDesers().getDeser((byte) 43), is(nullValue())); + assertThat(copiedMessagePackFactory.getExtTypeCustomDesers(), is(nullValue())); - assertThat(copiedMessagePackFactory.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET), is(false)); - assertThat(copiedMessagePackFactory.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE), is(false)); + assertThat(copiedMessagePackFactory.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET), is(true)); + assertThat(copiedMessagePackFactory.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE), is(true)); - Collection annotationIntrospectors = copiedObjectMapper.getSerializationConfig().getAnnotationIntrospector().allIntrospectors(); - assertThat(annotationIntrospectors.size(), is(1)); - assertThat(annotationIntrospectors.stream().findFirst().get(), is(instanceOf(JsonArrayFormat.class))); + assertThat(annotationIntrospectors.stream().findFirst().get(), + is(instanceOf(JacksonAnnotationIntrospector.class))); + } - HashMap map = new HashMap<>(); + // Check the copied ObjectMapper works fine + Map map = new HashMap<>(); map.put("one", 1); Map deserialized = copiedObjectMapper .readValue(objectMapper.writeValueAsBytes(map), new TypeReference>() {}); assertThat(deserialized.size(), is(1)); assertThat(deserialized.get("one"), is(1)); } + + @Test + public void copyWithDefaultConfig() + throws IOException + { + assertCopy(false); + } + + @Test + public void copyWithAdvancedConfig() + throws IOException + { + assertCopy(true); + } } From 2b6487f912dffe6cd04b253c6aee9c962e007bec Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 14 Apr 2018 22:46:37 +0900 Subject: [PATCH 100/417] Remove unused import --- .../org/msgpack/jackson/dataformat/MessagePackFactoryTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java index c36360c52..c3379c3df 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.ObjectMapper; From d209ac210d4eaef394ecad5121799a9479bae3e0 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 15 Apr 2018 21:16:14 +0900 Subject: [PATCH 101/417] Add 0.8.16 release notes --- RELEASE_NOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f69db7fc3..72a462d8d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,8 @@ # Release Notes +## 0.8.16 + * Fix NPE at ObjectMapper#copy with MessagePackFactory when ExtensionTypeCustomDeserializers isn't set [#471](https://github.com/msgpack/msgpack-java/pull/471) + ## 0.8.15 * Suppress a warning in ValueFactory [#457](https://github.com/msgpack/msgpack-java/pull/457) * Add MessagePacker#clear() method to clear position [#459](https://github.com/msgpack/msgpack-java/pull/459) From 84db39d4c38bb12fde8b6dc4415df6efe8573323 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 15 Apr 2018 21:49:53 +0900 Subject: [PATCH 102/417] Setting version to 0.8.16 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 77d6943c6..5750684b5 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.16-SNAPSHOT" +version in ThisBuild := "0.8.16" From 0f29cc32c6f3325598b19de2a5fd180234a53979 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 15 Apr 2018 21:50:41 +0900 Subject: [PATCH 103/417] Setting version to 0.8.17-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 5750684b5..f8e5d35bc 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.16" +version in ThisBuild := "0.8.17-SNAPSHOT" From c2133553c3bef6c4edb2a0e0ff6ed5fe7ddb2a87 Mon Sep 17 00:00:00 2001 From: Atsushi Nakagawa Date: Mon, 16 Apr 2018 11:03:47 +0900 Subject: [PATCH 104/417] MessagePacker: Improve and clarify use in documentation for addPayload() --- .../java/org/msgpack/core/MessagePacker.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index ed7d90e92..668b2dac0 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -1025,13 +1025,17 @@ public MessagePacker writePayload(byte[] src, int off, int len) /** * Writes a byte array to the output. *

      - * Unlike {@link #writePayload(byte[])} method, this method doesn't copy the byte array even when given byte - * array is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is faster than - * {@link #writePayload(byte[])} method but caller must not modify the byte array after calling this method. + * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. + *

      + * Unlike {@link #writePayload(byte[])} method, this method does not make a defensive copy of the given byte + * array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. This is + * faster than {@link #writePayload(byte[])} method but caller must not modify the byte array after calling + * this method. * * @param src the data to add * @return this * @throws IOException when underlying output throws IOException + * @see #writePayload(byte[]) */ public MessagePacker addPayload(byte[] src) throws IOException @@ -1042,16 +1046,19 @@ public MessagePacker addPayload(byte[] src) /** * Writes a byte array to the output. *

      - * Unlike {@link #writePayload(byte[], int, int)} method, this method doesn't copy the byte array even when - * given byte array is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. - * This is faster than {@link #writePayload(byte[], int, int)} method but caller must not modify the byte array - * after calling this method. + * This method is used with {@link #packRawStringHeader(int)} or {@link #packBinaryHeader(int)} methods. + *

      + * Unlike {@link #writePayload(byte[], int, int)} method, this method does not make a defensive copy of the + * given byte array, even if it is shorter than {@link MessagePack.PackerConfig#withBufferFlushThreshold(int)}. + * This is faster than {@link #writePayload(byte[])} method but caller must not modify the byte array after + * calling this method. * * @param src the data to add * @param off the start offset in the data * @param len the number of bytes to add * @return this * @throws IOException when underlying output throws IOException + * @see #writePayload(byte[], int, int) */ public MessagePacker addPayload(byte[] src, int off, int len) throws IOException From dad0ade8894f50385f49971c01247286bd38f76e Mon Sep 17 00:00:00 2001 From: Joel Nelson Date: Fri, 25 May 2018 15:20:21 -0400 Subject: [PATCH 105/417] use MessageBuffer constructor reflection only when required --- .../msgpack/core/buffer/MessageBuffer.java | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 246e678a7..c85680905 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -144,26 +144,33 @@ public class MessageBuffer bufferClsName = isLittleEndian ? DEFAULT_MESSAGE_BUFFER : BIGENDIAN_MESSAGE_BUFFER; } - try { - // We need to use reflection here to find MessageBuffer implementation classes because - // importing these classes creates TypeProfile and adds some overhead to method calls. + if (DEFAULT_MESSAGE_BUFFER.equals(bufferClsName)) { + // No need to use reflection here, we're not using a MessageBuffer subclass. + mbArrConstructor = null; + mbBBConstructor = null; + } + else { + try { + // We need to use reflection here to find MessageBuffer implementation classes because + // importing these classes creates TypeProfile and adds some overhead to method calls. - // MessageBufferX (default, BE or U) class - Class bufferCls = Class.forName(bufferClsName); + // MessageBufferX (default, BE or U) class + Class bufferCls = Class.forName(bufferClsName); - // MessageBufferX(byte[]) constructor - Constructor mbArrCstr = bufferCls.getDeclaredConstructor(byte[].class, int.class, int.class); - mbArrCstr.setAccessible(true); - mbArrConstructor = mbArrCstr; + // MessageBufferX(byte[]) constructor + Constructor mbArrCstr = bufferCls.getDeclaredConstructor(byte[].class, int.class, int.class); + mbArrCstr.setAccessible(true); + mbArrConstructor = mbArrCstr; - // MessageBufferX(ByteBuffer) constructor - Constructor mbBBCstr = bufferCls.getDeclaredConstructor(ByteBuffer.class); - mbBBCstr.setAccessible(true); - mbBBConstructor = mbBBCstr; - } - catch (Exception e) { - e.printStackTrace(System.err); - throw new RuntimeException(e); // No more fallback exists if MessageBuffer constructors are inaccessible + // MessageBufferX(ByteBuffer) constructor + Constructor mbBBCstr = bufferCls.getDeclaredConstructor(ByteBuffer.class); + mbBBCstr.setAccessible(true); + mbBBConstructor = mbBBCstr; + } + catch (Exception e) { + e.printStackTrace(System.err); + throw new RuntimeException(e); // No more fallback exists if MessageBuffer constructors are inaccessible + } } } } @@ -266,7 +273,10 @@ public static MessageBuffer wrap(ByteBuffer bb) private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len) { checkNotNull(arr); - return newInstance(mbArrConstructor, arr, off, len); + if (mbArrConstructor != null) { + return newInstance(mbArrConstructor, arr, off, len); + } + return new MessageBuffer(arr, off, len); } /** @@ -278,7 +288,10 @@ private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len) private static MessageBuffer newMessageBuffer(ByteBuffer bb) { checkNotNull(bb); - return newInstance(mbBBConstructor, bb); + if (mbBBConstructor != null) { + return newInstance(mbBBConstructor, bb); + } + return new MessageBuffer(bb); } /** From 4a291fded69611f83d6de175c9bd20ccf32c1994 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Sat, 11 Aug 2018 11:21:04 +0900 Subject: [PATCH 106/417] Fix typo --- RELEASE_NOTES.md | 2 +- msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java | 2 +- .../src/main/java/org/msgpack/core/MessageUnpacker.java | 2 +- msgpack-jackson/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 72a462d8d..1bd70b33e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -59,7 +59,7 @@ * Small performance optimization of packString when the String size is larger than 512 bytes. ## 0.8.4 - * Embed bundle paramters for OSGi + * Embed bundle parameters for OSGi ## 0.8.3 * Fix a bug (#348), which wrongly overwrites the buffer before reading numeric data at the buffer boundary diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 668b2dac0..6837f9f72 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -200,7 +200,7 @@ public class MessagePacker /** * Create an MessagePacker that outputs the packed data to the given {@link org.msgpack.core.buffer.MessageBufferOutput}. - * This method is available for subclasses to override. Use MessagePack.PackerConfig.newPacker method to instanciate this implementation. + * This method is available for subclasses to override. Use MessagePack.PackerConfig.newPacker method to instantiate this implementation. * * @param out MessageBufferOutput. Use {@link org.msgpack.core.buffer.OutputStreamBufferOutput}, {@link org.msgpack.core.buffer.ChannelBufferOutput} or * your own implementation of {@link org.msgpack.core.buffer.MessageBufferOutput} interface. diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 0edd874d9..30da411ea 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -204,7 +204,7 @@ public class MessageUnpacker /** * Create an MessageUnpacker that reads data from the given MessageBufferInput. - * This method is available for subclasses to override. Use MessagePack.UnpackerConfig.newUnpacker method to instanciate this implementation. + * This method is available for subclasses to override. Use MessagePack.UnpackerConfig.newUnpacker method to instantiate this implementation. * * @param in */ diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 33f58b68c..02f07c4dc 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -7,7 +7,7 @@ This Jackson extension library is a component to easily read and write [MessageP It extends standard Jackson streaming API (`JsonFactory`, `JsonParser`, `JsonGenerator`), and as such works seamlessly with all the higher level data abstractions (data binding, tree model, and pluggable extensions). For the details of Jackson-annotations, please see https://github.com/FasterXML/jackson-annotations. -This library isn't compatibile with msgpack-java v0.6 or earlier by default in serialization/deserialization of POJO. See **Advanced usage** below for details. +This library isn't compatible with msgpack-java v0.6 or earlier by default in serialization/deserialization of POJO. See **Advanced usage** below for details. ## Install From 0db1c139e9950e3c753c10fea9e50d492ab53fab Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sat, 6 Oct 2018 09:28:30 +0900 Subject: [PATCH 107/417] add jdk11 test --- .travis.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 19f8914ff..a5e5f71b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,12 +24,8 @@ matrix: script: - ./sbt test - ./sbt test -J-Dmsgpack.universal-buffer=true - - env: PROJECT=java9 - jdk: oraclejdk9 - addons: - apt: - packages: - - oracle-java9-installer + - env: PROJECT=java11 + jdk: openjdk11 script: - ./sbt test - ./sbt test -J-Dmsgpack.universal-buffer=true From 290d3d805794d08c501799a2bcb76467d7aab8d4 Mon Sep 17 00:00:00 2001 From: Joel Nelson Date: Tue, 29 May 2018 16:45:27 -0400 Subject: [PATCH 108/417] avoid creating MessageBuffer needlessly --- .../java/org/msgpack/core/MessageUnpacker.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 30da411ea..bbceefea3 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -1597,7 +1597,20 @@ public byte[] readPayload(int length) public void readPayload(byte[] dst, int off, int len) throws IOException { - readPayload(MessageBuffer.wrap(dst), off, len); + while (true) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= len) { + buffer.getBytes(position, dst, off, len); + position += len; + return; + } + buffer.getBytes(position, dst, off, bufferRemaining); + off += bufferRemaining; + len -= bufferRemaining; + position += bufferRemaining; + + nextBuffer(); + } } /** From e1108098ddfaa1457461dd066de1d447561d0e86 Mon Sep 17 00:00:00 2001 From: Joel Nelson Date: Tue, 29 May 2018 16:46:24 -0400 Subject: [PATCH 109/417] convert degenerate switch to if --- .../main/java/org/msgpack/core/MessageUnpacker.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index bbceefea3..cd0c44dec 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -607,11 +607,11 @@ public ImmutableValue unpackValue() case BOOLEAN: return ValueFactory.newBoolean(unpackBoolean()); case INTEGER: - switch (mf) { - case UINT64: - return ValueFactory.newInteger(unpackBigInteger()); - default: - return ValueFactory.newInteger(unpackLong()); + if (mf == MessageFormat.UINT64) { + return ValueFactory.newInteger(unpackBigInteger()); + } + else { + return ValueFactory.newInteger(unpackLong()); } case FLOAT: return ValueFactory.newFloat(unpackDouble()); From 2f520b5a57f3c7346ddba4152d08cac2d7386255 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Wed, 7 Nov 2018 13:08:16 +0900 Subject: [PATCH 110/417] fix javadoc badge --- README.md | 2 +- msgpack-jackson/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ea4cb1b1e..527667454 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ supports all of the message pack types, including [extension format](https://git ## Quick Start [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.msgpack/msgpack-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.msgpack/msgpack-core/) -[![Javadoc](https://javadoc-emblem.rhcloud.com/doc/org.msgpack/msgpack-core/badge.svg)](http://www.javadoc.io/doc/org.msgpack/msgpack-core) +[![Javadoc](https://javadoc.io/badge/org.msgpack/msgpack-core.svg)](https://www.javadoc.io/doc/org.msgpack/msgpack-core) For Maven users: ``` diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 02f07c4dc..52149f047 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -1,7 +1,7 @@ # jackson-dataformat-msgpack [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.msgpack/jackson-dataformat-msgpack/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.msgpack/jackson-dataformat-msgpack/) -[![Javadoc](https://javadoc-emblem.rhcloud.com/doc/org.msgpack/jackson-dataformat-msgpack/badge.svg)](http://www.javadoc.io/doc/org.msgpack/jackson-dataformat-msgpack) +[![Javadoc](https://www.javadoc.io/badge/org.msgpack/jackson-dataformat-msgpack.svg)](https://www.javadoc.io/doc/org.msgpack/jackson-dataformat-msgpack) This Jackson extension library is a component to easily read and write [MessagePack](http://msgpack.org/) encoded data through jackson-databind API. From 16e370e348215a72a14c210b42d448d513aee015 Mon Sep 17 00:00:00 2001 From: alterdego <45322074+alterdego@users.noreply.github.com> Date: Mon, 21 Jan 2019 22:23:58 -0500 Subject: [PATCH 111/417] Fixed typos in README.md (#493) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 527667454..08cb6caca 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ MessagePack for Java === -[MessagePack](http://msgpack.org) is a binary serialization format. If you need a fast and compact alternative of JSON, MessagePack is your friend. For example, a small integer can be encoded in a single byte, and short strings only need a single byte prefix + the original byte array. MessagePack implementation is already available in various lanaguages (See also the list in http://msgpack.org) and works as a universal data format. +[MessagePack](http://msgpack.org) is a binary serialization format. If you need a fast and compact alternative of JSON, MessagePack is your friend. For example, a small integer can be encoded in a single byte, and short strings only need a single byte prefix + the original byte array. MessagePack implementation is already available in various languages (See also the list in http://msgpack.org) and works as a universal data format. * Message Pack specification: From 39dc8a7d3bcd5b02be209396d5cd50fa6fef8d05 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Mon, 13 May 2019 22:41:42 +0900 Subject: [PATCH 112/417] Handle unexpected EOF --- .../jackson/dataformat/MessagePackParser.java | 3 +- .../dataformat/MessagePackParserTest.java | 102 ++++++++++++++---- 2 files changed, 84 insertions(+), 21 deletions(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 5df9632ab..d6de1ce06 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -26,6 +26,7 @@ import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.base.ParserMinimalBase; import com.fasterxml.jackson.core.io.IOContext; +import com.fasterxml.jackson.core.io.JsonEOFException; import com.fasterxml.jackson.core.json.DupDetector; import com.fasterxml.jackson.core.json.JsonReadContext; import org.msgpack.core.ExtensionTypeHeader; @@ -233,7 +234,7 @@ public JsonToken nextToken() } if (!messageUnpacker.hasNext()) { - return null; + throw new JsonEOFException(this, null, "Unexpected EOF"); } MessageFormat format = messageUnpacker.getNextFormat(); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 088cd2bcb..2258f2f82 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -18,9 +18,11 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.io.JsonEOFException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -48,8 +50,8 @@ import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; public class MessagePackParserTest extends MessagePackDataformatTestBase @@ -348,8 +350,6 @@ public void testMessagePackParserDirectly() assertEquals(-1, parser.getCurrentLocation().getLineNr()); assertEquals(16, parser.getCurrentLocation().getColumnNr()); - assertNull(parser.nextToken()); - parser.close(); parser.close(); // Intentional } @@ -555,8 +555,8 @@ public void testByteArrayKey() MessagePacker messagePacker = MessagePack.newDefaultPacker(out).packMapHeader(2); byte[] k0 = new byte[] {0}; byte[] k1 = new byte[] {1}; - messagePacker.packBinaryHeader(1).writePayload(k0).packInt(2); - messagePacker.packBinaryHeader(1).writePayload(k1).packInt(3); + messagePacker.packBinaryHeader(1).writePayload(k0).packInt(10); + messagePacker.packBinaryHeader(1).writePayload(k1).packInt(11); messagePacker.close(); ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); @@ -577,10 +577,10 @@ public Object deserializeKey(String key, DeserializationContext ctxt) assertEquals(2, map.size()); for (Map.Entry entry : map.entrySet()) { if (Arrays.equals(entry.getKey(), k0)) { - assertEquals((Integer) 2, entry.getValue()); + assertEquals((Integer) 10, entry.getValue()); } else if (Arrays.equals(entry.getKey(), k1)) { - assertEquals((Integer) 3, entry.getValue()); + assertEquals((Integer) 11, entry.getValue()); } } } @@ -590,9 +590,9 @@ public void testIntegerKey() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - MessagePacker messagePacker = MessagePack.newDefaultPacker(out).packMapHeader(3); + MessagePacker messagePacker = MessagePack.newDefaultPacker(out).packMapHeader(2); for (int i = 0; i < 2; i++) { - messagePacker.packInt(i).packInt(i + 2); + messagePacker.packInt(i).packInt(i + 10); } messagePacker.close(); @@ -612,8 +612,8 @@ public Object deserializeKey(String key, DeserializationContext ctxt) Map map = objectMapper.readValue( out.toByteArray(), new TypeReference>() {}); assertEquals(2, map.size()); - assertEquals((Integer) 2, map.get(0)); - assertEquals((Integer) 3, map.get(1)); + assertEquals((Integer) 10, map.get(0)); + assertEquals((Integer) 11, map.get(1)); } @Test @@ -621,9 +621,9 @@ public void testFloatKey() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - MessagePacker messagePacker = MessagePack.newDefaultPacker(out).packMapHeader(3); + MessagePacker messagePacker = MessagePack.newDefaultPacker(out).packMapHeader(2); for (int i = 0; i < 2; i++) { - messagePacker.packFloat(i).packInt(i + 2); + messagePacker.packFloat(i).packInt(i + 10); } messagePacker.close(); @@ -643,8 +643,8 @@ public Object deserializeKey(String key, DeserializationContext ctxt) Map map = objectMapper.readValue( out.toByteArray(), new TypeReference>() {}); assertEquals(2, map.size()); - assertEquals((Integer) 2, map.get(0f)); - assertEquals((Integer) 3, map.get(1f)); + assertEquals((Integer) 10, map.get(0f)); + assertEquals((Integer) 11, map.get(1f)); } @Test @@ -652,9 +652,9 @@ public void testBooleanKey() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - MessagePacker messagePacker = MessagePack.newDefaultPacker(out).packMapHeader(3); - messagePacker.packBoolean(true).packInt(2); - messagePacker.packBoolean(false).packInt(3); + MessagePacker messagePacker = MessagePack.newDefaultPacker(out).packMapHeader(2); + messagePacker.packBoolean(true).packInt(10); + messagePacker.packBoolean(false).packInt(11); messagePacker.close(); ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); @@ -673,8 +673,8 @@ public Object deserializeKey(String key, DeserializationContext ctxt) Map map = objectMapper.readValue( out.toByteArray(), new TypeReference>() {}); assertEquals(2, map.size()); - assertEquals((Integer) 2, map.get(true)); - assertEquals((Integer) 3, map.get(false)); + assertEquals((Integer) 10, map.get(true)); + assertEquals((Integer) 11, map.get(false)); } @Test @@ -851,4 +851,66 @@ public void deserializeStringAsBigDecimal() BigDecimal v = objectMapper.readValue(out.toByteArray(), BigDecimal.class); assertThat(v, is(bd)); } + + @Test + public void handleMissingItemInArray() + throws IOException + { + MessagePacker packer = MessagePack.newDefaultPacker(out); + packer.packArrayHeader(3); + packer.packString("one"); + packer.packString("two"); + packer.close(); + + try { + objectMapper.readValue(out.toByteArray(), new TypeReference>() {}); + fail(); + } + catch (JsonMappingException e) { + assertTrue(e.getCause() instanceof JsonEOFException); + } + } + + @Test + public void handleMissingKeyValueInMap() + throws IOException + { + MessagePacker packer = MessagePack.newDefaultPacker(out); + packer.packMapHeader(3); + packer.packString("one"); + packer.packInt(1); + packer.packString("two"); + packer.packInt(2); + packer.close(); + + try { + objectMapper.readValue(out.toByteArray(), new TypeReference>() {}); + fail(); + } + catch (JsonEOFException e) { + assertTrue(true); + } + } + + @Test + public void handleMissingValueInMap() + throws IOException + { + MessagePacker packer = MessagePack.newDefaultPacker(out); + packer.packMapHeader(3); + packer.packString("one"); + packer.packInt(1); + packer.packString("two"); + packer.packInt(2); + packer.packString("three"); + packer.close(); + + try { + objectMapper.readValue(out.toByteArray(), new TypeReference>() {}); + fail(); + } + catch (JsonEOFException e) { + assertTrue(true); + } + } } From c1695e4a5cff40804e7821ba0ca44480dd09301e Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 16 Jun 2019 13:50:06 +0900 Subject: [PATCH 113/417] Update jackson-databind to 2.9.9 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 073cd4020..2645fb126 100644 --- a/build.sbt +++ b/build.sbt @@ -115,7 +115,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.1", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 22272c497e810eff888bc94baafc2825b009c2a0 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 19 Jun 2019 13:49:48 +0900 Subject: [PATCH 114/417] Setting version to 0.8.17 --- RELEASE_NOTES.md | 4 ++++ version.sbt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 1bd70b33e..f91988767 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Release Notes +## 0.8.17 + * Fix OOM exception for invalid msgpack messages [#500](https://github.com/msgpack/msgpack-java/pull/500) + * Use jackson-databind 2.9.9 for security vulnerability [#505](https://github.com/msgpack/msgpack-java/pull/505) + ## 0.8.16 * Fix NPE at ObjectMapper#copy with MessagePackFactory when ExtensionTypeCustomDeserializers isn't set [#471](https://github.com/msgpack/msgpack-java/pull/471) diff --git a/version.sbt b/version.sbt index f8e5d35bc..959f99c3a 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.17-SNAPSHOT" +version in ThisBuild := "0.8.17" From 9087df9ebda0f976a23ebd8f841f0682b2aeb66c Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 19 Jun 2019 14:07:41 +0900 Subject: [PATCH 115/417] Setting version to 0.8.18-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 959f99c3a..4ae9fc5bd 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.17" +version in ThisBuild := "0.8.18-SNAPSHOT" From 8060e0f5e956ccd1a217e23bae0046dd24e72ace Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Tue, 9 Jul 2019 23:13:34 +0900 Subject: [PATCH 116/417] Add a header to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 08cb6caca..c1dbc2461 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ dependencies { - [Usage examples](msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java) +### Integration with Jackson ObjectMapper (jackson-databind) + msgpack-java supports serialization and deserialization of Java objects through [jackson-databind](https://github.com/FasterXML/jackson-databind). For details, see [msgpack-jackson/README.md](msgpack-jackson/README.md). The template-based serialization mechanism used in v06 is deprecated. From 76fdd872cd2538b81515a9e396450f22ecbba203 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Fri, 19 Jul 2019 15:08:05 +0900 Subject: [PATCH 117/417] Update dependencies (#507) --- build.sbt | 12 ++++++------ project/build.properties | 2 +- project/plugins.sbt | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build.sbt b/build.sbt index 2645fb126..1821bf09c 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ val buildSettings = Seq[Setting[_]]( organizationName := "MessagePack", organizationHomepage := Some(new URL("http://msgpack.org/")), description := "MessagePack for Java", - scalaVersion := "2.12.4", + scalaVersion := "2.12.8", logBuffered in Test := false, // msgpack-java should be a pure-java library, so remove Scala specific configurations autoScalaLibrary := false, @@ -93,12 +93,12 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) libraryDependencies ++= Seq( // msgpack-core should have no external dependencies junitInterface, - "org.scalatest" %% "scalatest" % "3.0.3" % "test", - "org.scalacheck" %% "scalacheck" % "1.13.5" % "test", + "org.scalatest" %% "scalatest" % "3.0.8" % "test", + "org.scalacheck" %% "scalacheck" % "1.14.0" % "test", "org.xerial" %% "xerial-core" % "3.6.0" % "test", "org.msgpack" % "msgpack" % "0.6.12" % "test", - "commons-codec" % "commons-codec" % "1.10" % "test", - "com.typesafe.akka" %% "akka-actor" % "2.5.7" % "test" + "commons-codec" % "commons-codec" % "1.12" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.5.23" % "test" ) ) @@ -115,7 +115,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9.1", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), diff --git a/project/build.properties b/project/build.properties index cd928eac3..e2820dd8c 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.0.4 +sbt.version=1.2.8 diff --git a/project/plugins.sbt b/project/plugins.sbt index a4fc6f318..647c13328 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,11 +1,11 @@ -addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.7") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.0") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") +addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.11") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.5") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.2") addSbtPlugin("com.github.sbt" % "sbt-findbugs" % "2.0.0") addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.0.3") -addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.0") -addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.2") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0") -addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.4.0") +addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") +addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.5") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.3") +addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.5.1") scalacOptions ++= Seq("-deprecation", "-feature") From 8612b028a95445bae2b9b4591124beba69d70401 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Mon, 26 Aug 2019 22:47:10 +0900 Subject: [PATCH 118/417] Use jackson-databind-2.9.9.3 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 1821bf09c..2ea074f17 100644 --- a/build.sbt +++ b/build.sbt @@ -115,7 +115,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9.1", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9.3", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From f7aaab8f4c88fdcc990146befee37b1e1525369e Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Mon, 26 Aug 2019 22:58:47 +0900 Subject: [PATCH 119/417] Add a workaround for Travis CI error --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index a5e5f71b2..d1c82a096 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,8 @@ language: scala +# With xenial, `Installing oraclejdk8` fails due to "Expected feature release number in range of 9 to 14, but got: 8" +dist: trusty + cache: directories: - $HOME/.m2/repository/ From 961fd266f9d853e5ee07d9bc1ae031d2b1d54e78 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 28 Aug 2019 00:10:06 +0900 Subject: [PATCH 120/417] Add test code and write tips for issue 508 --- msgpack-jackson/README.md | 38 ++++++++++++++ .../dataformat/MessagePackGeneratorTest.java | 51 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 52149f047..fe76f0e2b 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -315,3 +315,41 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial System.out.println(objectMapper.readValue(bytes, Object.class)); // => Java ``` + +### Serialize a nested object that also serializes + +When you serialize an object that has a nested object also serializing with ObjectMapper and MessagePackFactory like the following code + +```java + @Test + public void testNestedSerialization() throws Exception + { + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.writeValueAsBytes(new OuterClass()); + } + + public class OuterClass + { + public String getInner() throws JsonProcessingException + { + ObjectMapper m = new ObjectMapper(new MessagePackFactory()); + m.writeValueAsBytes(new InnerClass()); + return "EFG"; + } + } + + public class InnerClass + { + public String getName() + { + return "ABC"; + } + } +``` + +This code throws NullPointerException since the nested MessagePackFactory modifies a shared state stored in ThreadLocal. There are a few options to fix this issue, but they introduce performance degredations while this usage is a corner case. A workaround that doesn't affect performance is to call `MessagePackFactory#setReuseResourceInGenerator(false)`. I think it might be inconvenient to call the API for users, but it's a reasonable tradeoff with performance for now. + +```java + ObjectMapper objectMapper = new ObjectMapper( + new MessagePackFactory().setReuseResourceInGenerator(false)); +``` \ No newline at end of file diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index 7a8db2805..549f2f90a 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -15,6 +15,7 @@ // package org.msgpack.jackson.dataformat; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonEncoding; import com.fasterxml.jackson.core.JsonProcessingException; @@ -884,4 +885,54 @@ public void serializeStringAsBigInteger() MessagePack.newDefaultUnpacker(objectMapper.writeValueAsBytes(bi)).unpackDouble(), is(bi.doubleValue())); } + + @Test + public void testNestedSerialization() throws Exception + { + // The purpose of this test is to confirm if MessagePackFactory.setReuseResourceInGenerator(false) + // works as a workaround for https://github.com/msgpack/msgpack-java/issues/508 + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory().setReuseResourceInGenerator(false)); + OuterClass outerClass = objectMapper.readValue( + objectMapper.writeValueAsBytes(new OuterClass("Foo")), + OuterClass.class); + assertEquals("Foo", outerClass.getName()); + } + + static class OuterClass + { + private final String name; + + public OuterClass(@JsonProperty("name") String name) + { + this.name = name; + } + + public String getName() + throws IOException + { + // Serialize nested class object + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + InnerClass innerClass = objectMapper.readValue( + objectMapper.writeValueAsBytes(new InnerClass("Bar")), + InnerClass.class); + assertEquals("Bar", innerClass.getName()); + + return name; + } + } + + static class InnerClass + { + private final String name; + + public InnerClass(@JsonProperty("name") String name) + { + this.name = name; + } + + public String getName() + { + return name; + } + } } From b67c13b91232fd15870d04f4ade689b8ec957427 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 30 Aug 2019 22:07:18 +0900 Subject: [PATCH 121/417] Minor change --- msgpack-jackson/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index fe76f0e2b..d53ecfefb 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -347,9 +347,10 @@ When you serialize an object that has a nested object also serializing with Obje } ``` -This code throws NullPointerException since the nested MessagePackFactory modifies a shared state stored in ThreadLocal. There are a few options to fix this issue, but they introduce performance degredations while this usage is a corner case. A workaround that doesn't affect performance is to call `MessagePackFactory#setReuseResourceInGenerator(false)`. I think it might be inconvenient to call the API for users, but it's a reasonable tradeoff with performance for now. +This code throws NullPointerException since the nested MessagePackFactory modifies a shared state stored in ThreadLocal. There are a few options to fix this issue, but they introduce performance degredations while this usage is a corner case. A workaround that doesn't affect performance is to call `MessagePackFactory#setReuseResourceInGenerator(false)`. It might be inconvenient to call the API for users, but it's a reasonable tradeoff with performance for now. ```java ObjectMapper objectMapper = new ObjectMapper( new MessagePackFactory().setReuseResourceInGenerator(false)); -``` \ No newline at end of file +``` + From d7f32ca9381980ddbc225e4065059db0c544e003 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 30 Aug 2019 22:22:45 +0900 Subject: [PATCH 122/417] Minor update --- msgpack-jackson/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index d53ecfefb..00be68c67 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -318,7 +318,7 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial ### Serialize a nested object that also serializes -When you serialize an object that has a nested object also serializing with ObjectMapper and MessagePackFactory like the following code +When you serialize an object that has a nested object also serializing with ObjectMapper and MessagePackFactory like the following code, it throws NullPointerException since the nested MessagePackFactory modifies a shared state stored in ThreadLocal. ```java @Test @@ -347,7 +347,7 @@ When you serialize an object that has a nested object also serializing with Obje } ``` -This code throws NullPointerException since the nested MessagePackFactory modifies a shared state stored in ThreadLocal. There are a few options to fix this issue, but they introduce performance degredations while this usage is a corner case. A workaround that doesn't affect performance is to call `MessagePackFactory#setReuseResourceInGenerator(false)`. It might be inconvenient to call the API for users, but it's a reasonable tradeoff with performance for now. +There are a few options to fix this issue, but they introduce performance degredations while this usage is a corner case. A workaround that doesn't affect performance is to call `MessagePackFactory#setReuseResourceInGenerator(false)`. It might be inconvenient to call the API for users, but it's a reasonable tradeoff with performance for now. ```java ObjectMapper objectMapper = new ObjectMapper( From 65dc3220ca6d560257cd2c6618551a0be04db3df Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 30 Aug 2019 22:59:55 +0900 Subject: [PATCH 123/417] Add 0.8.18 release note --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f91988767..a9cd048c3 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Release Notes +## 0.8.18 + * (internal) Update sbt related dependencies [#507](https://github.com/msgpack/msgpack-java/pull/507) + * Use jackson-databind 2.9.9.3 for security vulnerability [#511](https://github.com/msgpack/msgpack-java/pull/511) + ## 0.8.17 * Fix OOM exception for invalid msgpack messages [#500](https://github.com/msgpack/msgpack-java/pull/500) * Use jackson-databind 2.9.9 for security vulnerability [#505](https://github.com/msgpack/msgpack-java/pull/505) From e414ebfe24718d49b957f050cdd7b2754fa81c18 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 30 Aug 2019 23:05:52 +0900 Subject: [PATCH 124/417] Setting version to 0.8.18 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 4ae9fc5bd..977a2dca2 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.18-SNAPSHOT" +version in ThisBuild := "0.8.18" From 7088d20763ddf6384320bb2c0d40f9664a816deb Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 30 Aug 2019 23:16:44 +0900 Subject: [PATCH 125/417] Setting version to 0.8.19-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 977a2dca2..92280a1a3 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.18" +version in ThisBuild := "0.8.19-SNAPSHOT" From c1eb4259bba41e90dbd85aedca468d6159ec4a3f Mon Sep 17 00:00:00 2001 From: qxo <49526356@qq.com> Date: Sun, 3 Nov 2019 23:27:27 +0800 Subject: [PATCH 126/417] MessagePackFactory should add getFormatName for naming the factory --- .../org/msgpack/jackson/dataformat/MessagePackFactory.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index 225a33628..1e7acc5e2 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -172,4 +172,10 @@ ExtensionTypeCustomDeserializers getExtTypeCustomDesers() { return extTypeCustomDesers; } + + @Override + public String getFormatName() + { + return "msgpack"; + } } From bef0ccdb9b1be70c533f81e0c459fdef6f578cd2 Mon Sep 17 00:00:00 2001 From: ppkarwasz Date: Mon, 18 Nov 2019 19:47:30 +0100 Subject: [PATCH 127/417] Improves MessageBuffer support for Java 11 (#514) * Improves MessageBuffer support of Java 11 Switches the MessageBuffer implementation to MessageBufferU for Java versions at least 9. Since this implementation overrides almost all MessageBuffer's method it is safe to allow direct buffers as argument to MessageBuffer.wrap(ByteBuffer) * Corrects code style * Do not switch to MessageBufferU on Java 9+ Disables the automatic switch to MessageBufferU on Java 9+, falling back to a manual switch through Java properties. * Run Java 11 tests on universal buffer only Java 11 tests without the "msgpack.universal-buffer" property set where using the universal buffer anyway: Java 11's "java.specification.version" does not contain a dot, so MessageBuffer misidentified it as Java less than 7 and switched to MessageBufferU. * Fixes DirectBufferAccess#clean on Java 11 For Java 9+ we switch from a DirectByteBuffer.cleaner().clean() call to Unsafe.invokeCleaner(buffer). * Corrects style * Corrects whitespace * Restores Java8 tests. * Fixes IllegalAccessExceptions Adds missing setAccessible calls. --- .../core/buffer/DirectBufferAccess.java | 155 ++++++++++++++++-- .../msgpack/core/buffer/MessageBuffer.java | 52 ++++-- .../msgpack/core/buffer/MessageBufferU.java | 12 ++ 3 files changed, 191 insertions(+), 28 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java index ab86061d3..cde2e6eca 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java @@ -19,6 +19,10 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.ByteBuffer; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import sun.misc.Unsafe; /** * Wraps the difference of access methods to DirectBuffers between Android and others. @@ -37,20 +41,24 @@ enum DirectBufferConstructorType } static Method mGetAddress; + // For Java <=8, gets a sun.misc.Cleaner static Method mCleaner; static Method mClean; + // For Java >=9, invokes a jdk.internal.ref.Cleaner + static Method mInvokeCleaner; // TODO We should use MethodHandle for efficiency, but it is not available in JDK6 - static Constructor byteBufferConstructor; + static Constructor byteBufferConstructor; static Class directByteBufferClass; static DirectBufferConstructorType directBufferConstructorType; static Method memoryBlockWrapFromJni; static { try { + final ByteBuffer direct = ByteBuffer.allocateDirect(1); // Find the hidden constructor for DirectByteBuffer - directByteBufferClass = ClassLoader.getSystemClassLoader().loadClass("java.nio.DirectByteBuffer"); - Constructor directByteBufferConstructor = null; + directByteBufferClass = direct.getClass(); + Constructor directByteBufferConstructor = null; DirectBufferConstructorType constructorType = null; Method mbWrap = null; try { @@ -92,17 +100,139 @@ enum DirectBufferConstructorType mGetAddress = directByteBufferClass.getDeclaredMethod("address"); mGetAddress.setAccessible(true); - mCleaner = directByteBufferClass.getDeclaredMethod("cleaner"); - mCleaner.setAccessible(true); - - mClean = mCleaner.getReturnType().getDeclaredMethod("clean"); - mClean.setAccessible(true); + if (MessageBuffer.javaVersion <= 8) { + setupCleanerJava6(direct); + } + else { + setupCleanerJava9(direct); + } } catch (Exception e) { throw new RuntimeException(e); } } + private static void setupCleanerJava6(final ByteBuffer direct) + { + Object obj; + obj = AccessController.doPrivileged(new PrivilegedAction() + { + @Override + public Object run() + { + return getCleanerMethod(direct); + } + }); + if (obj instanceof Throwable) { + throw new RuntimeException((Throwable) obj); + } + mCleaner = (Method) obj; + + obj = AccessController.doPrivileged(new PrivilegedAction() + { + @Override + public Object run() + { + return getCleanMethod(direct, mCleaner); + } + }); + if (obj instanceof Throwable) { + throw new RuntimeException((Throwable) obj); + } + mClean = (Method) obj; + } + + private static void setupCleanerJava9(final ByteBuffer direct) + { + Object obj = AccessController.doPrivileged(new PrivilegedAction() + { + @Override + public Object run() + { + return getInvokeCleanerMethod(direct); + } + }); + if (obj instanceof Throwable) { + throw new RuntimeException((Throwable) obj); + } + mInvokeCleaner = (Method) obj; + } + + /** + * Checks if we have a usable {@link DirectByteBuffer#cleaner}. + * @param direct a direct buffer + * @return the method or an error + */ + private static Object getCleanerMethod(ByteBuffer direct) + { + try { + Method m = direct.getClass().getDeclaredMethod("cleaner"); + m.setAccessible(true); + m.invoke(direct); + return m; + } + catch (NoSuchMethodException e) { + return e; + } + catch (InvocationTargetException e) { + return e; + } + catch (IllegalAccessException e) { + return e; + } + } + + /** + * Checks if we have a usable {@link sun.misc.Cleaner#clean}. + * @param direct a direct buffer + * @param mCleaner the {@link DirectByteBuffer#cleaner} method + * @return the method or null + */ + private static Object getCleanMethod(ByteBuffer direct, Method mCleaner) + { + try { + Method m = mCleaner.getReturnType().getDeclaredMethod("clean"); + Object c = mCleaner.invoke(direct); + m.setAccessible(true); + m.invoke(c); + return m; + } + catch (NoSuchMethodException e) { + return e; + } + catch (InvocationTargetException e) { + return e; + } + catch (IllegalAccessException e) { + return e; + } + } + + /** + * Checks if we have a usable {@link Unsafe#invokeCleaner}. + * @param direct a direct buffer + * @return the method or an error + */ + private static Object getInvokeCleanerMethod(ByteBuffer direct) + { + try { + // See https://bugs.openjdk.java.net/browse/JDK-8171377 + Method m = MessageBuffer.unsafe.getClass().getDeclaredMethod( + "invokeCleaner", ByteBuffer.class); + m.invoke(MessageBuffer.unsafe, direct); + return m; + } + catch (NoSuchMethodException e) { + return e; + } + catch (InvocationTargetException e) { + return e; + } + catch (IllegalAccessException e) { + return e; + } + } + static long getAddress(Object base) { try { @@ -119,8 +249,13 @@ static long getAddress(Object base) static void clean(Object base) { try { - Object cleaner = mCleaner.invoke(base); - mClean.invoke(cleaner); + if (MessageBuffer.javaVersion <= 8) { + Object cleaner = mCleaner.invoke(base); + mClean.invoke(cleaner); + } + else { + mInvokeCleaner.invoke(MessageBuffer.unsafe, base); + } } catch (Throwable e) { throw new RuntimeException(e); diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index c85680905..8628ae785 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -47,6 +47,7 @@ public class MessageBuffer { static final boolean isUniversalBuffer; static final Unsafe unsafe; + static final int javaVersion = getJavaVersion(); /** * Reference to MessageBuffer Constructors @@ -69,21 +70,6 @@ public class MessageBuffer int arrayByteBaseOffset = 16; try { - // Check java version - String javaVersion = System.getProperty("java.specification.version", ""); - int dotPos = javaVersion.indexOf('.'); - boolean isJavaAtLeast7 = false; - if (dotPos != -1) { - try { - int major = Integer.parseInt(javaVersion.substring(0, dotPos)); - int minor = Integer.parseInt(javaVersion.substring(dotPos + 1)); - isJavaAtLeast7 = major > 1 || (major == 1 && minor >= 7); - } - catch (NumberFormatException e) { - e.printStackTrace(System.err); - } - } - boolean hasUnsafe = false; try { hasUnsafe = Class.forName("sun.misc.Unsafe") != null; @@ -97,12 +83,12 @@ public class MessageBuffer // Is Google App Engine? boolean isGAE = System.getProperty("com.google.appengine.runtime.version") != null; - // For Java6, android and JVM that has no Unsafe class, use Universal MessageBuffer + // For Java6, android and JVM that has no Unsafe class, use Universal MessageBuffer (based on ByteBuffer). useUniversalBuffer = Boolean.parseBoolean(System.getProperty("msgpack.universal-buffer", "false")) || isAndroid || isGAE - || !isJavaAtLeast7 + || javaVersion < 7 || !hasUnsafe; if (!useUniversalBuffer) { @@ -175,6 +161,31 @@ public class MessageBuffer } } + private static int getJavaVersion() + { + String javaVersion = System.getProperty("java.specification.version", ""); + int dotPos = javaVersion.indexOf('.'); + if (dotPos != -1) { + try { + int major = Integer.parseInt(javaVersion.substring(0, dotPos)); + int minor = Integer.parseInt(javaVersion.substring(dotPos + 1)); + return major > 1 ? major : minor; + } + catch (NumberFormatException e) { + e.printStackTrace(System.err); + } + } + else { + try { + return Integer.parseInt(javaVersion); + } + catch (NumberFormatException e) { + e.printStackTrace(System.err); + } + } + return 6; + } + /** * Base object for resolving the relative address of the raw byte array. * If base == null, the address value is a raw memory address @@ -366,7 +377,12 @@ else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.reference)) { { if (bb.isDirect()) { if (isUniversalBuffer) { - throw new UnsupportedOperationException("Cannot create MessageBuffer from a DirectBuffer on this platform"); + // MessageBufferU overrides almost all methods, only field 'size' is used. + this.base = null; + this.address = 0; + this.size = bb.remaining(); + this.reference = null; + return; } // Direct buffer or off-heap memory this.base = null; diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java index 4369bdf3c..a185a67b9 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java @@ -258,4 +258,16 @@ public byte[] toByteArray() getBytes(0, b, 0, b.length); return b; } + + @Override + public boolean hasArray() + { + return !wrap.isDirect(); + } + + @Override + public byte[] array() + { + return hasArray() ? wrap.array() : null; + } } From 657d1c154eb73176c31de3112d1255f4adbc4ce9 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 18 Nov 2019 16:28:37 -0800 Subject: [PATCH 128/417] Setting version to 0.8.19 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 92280a1a3..1845e6fa6 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.19-SNAPSHOT" +version in ThisBuild := "0.8.19" From 3bd4b1889f503e9c72736487e80acb8918855bd4 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 18 Nov 2019 16:30:13 -0800 Subject: [PATCH 129/417] Setting version to 0.8.20-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 1845e6fa6..76bbb0cea 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.19" +version in ThisBuild := "0.8.20-SNAPSHOT" From 85730331feb64f09491918bd4fddf6845e9ce573 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 18 Nov 2019 16:38:59 -0800 Subject: [PATCH 130/417] Add 0.8.19 release note --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index a9cd048c3..6a434fcf0 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Release Notes +## 0.8.19 + * Support JDK11 + * msgpack-jackson: Fixes [#515](https://github.com/msgpack/msgpack-java/pull/515) + ## 0.8.18 * (internal) Update sbt related dependencies [#507](https://github.com/msgpack/msgpack-java/pull/507) * Use jackson-databind 2.9.9.3 for security vulnerability [#511](https://github.com/msgpack/msgpack-java/pull/511) From 196bcf323504dab45c9decd9aae31a77ba1c7e7c Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 27 Nov 2019 11:56:34 -0800 Subject: [PATCH 131/417] Setting version to 0.8.20 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 76bbb0cea..3718ff65e 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.20-SNAPSHOT" +version in ThisBuild := "0.8.20" From 12f25007008d961c85bc0bb1ca5ce6bb1e5e6f5c Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 27 Nov 2019 11:57:25 -0800 Subject: [PATCH 132/417] Setting version to 0.8.21-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 3718ff65e..9e4cb15e6 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.20" +version in ThisBuild := "0.8.21-SNAPSHOT" From f20ffe3d8d1a8f78d2cb1bb9bdc1bb9d0f0e922b Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Wed, 27 Nov 2019 11:59:59 -0800 Subject: [PATCH 133/417] 0.8.20 release notes --- RELEASE_NOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6a434fcf0..dd241f178 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,8 @@ # Release Notes +## 0.8.20 + * Rebuild 0.8.19 with JDK8 + ## 0.8.19 * Support JDK11 * msgpack-jackson: Fixes [#515](https://github.com/msgpack/msgpack-java/pull/515) From 72066f35b1148154bae9022b4776cf6e4be2d44f Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 22 May 2020 09:38:45 -0700 Subject: [PATCH 134/417] Delete msgpack.org.md As mentioned here #521, msgpack.org site shows an obsolete documentation by having this file. I'll remove this (@komamitsu ) --- msgpack.org.md | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) delete mode 100644 msgpack.org.md diff --git a/msgpack.org.md b/msgpack.org.md deleted file mode 100644 index 580febac6..000000000 --- a/msgpack.org.md +++ /dev/null @@ -1,46 +0,0 @@ -# MessagePack for Java - -[JavaDoc is available at javadoc.io](https://www.javadoc.io/doc/org.msgpack/msgpack-core). - -## How to install - -You can install msgpack via maven: - - - ... - - org.msgpack - msgpack - ${msgpack.version} - - ... - - -## Simple Serialization/Deserialization/Duck Typing using Value - - // Create serialize objects. - List src = new ArrayList(); - src.add("msgpack"); - src.add("kumofs"); - src.add("viver"); - - MessagePack msgpack = new MessagePack(); - // Serialize - byte[] raw = msgpack.write(src); - - // Deserialize directly using a template - List dst1 = msgpack.read(raw, Templates.tList(Templates.TString)); - System.out.println(dst1.get(0)); - System.out.println(dst1.get(1)); - System.out.println(dst1.get(2)); - - // Or, Deserialze to Value then convert type. - Value dynamic = msgpack.read(raw); - List dst2 = new Converter(dynamic) - .read(Templates.tList(Templates.TString)); - System.out.println(dst2.get(0)); - System.out.println(dst2.get(1)); - System.out.println(dst2.get(2)); - - - From 3cf8a52fe0224aa112fef7b10f349b510af7f77c Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 2 Jun 2020 17:25:24 -0700 Subject: [PATCH 135/417] #522: Ensure building msgpack-java for Java 7 target (#523) --- build.sbt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 2ea074f17..3329fbfd6 100644 --- a/build.sbt +++ b/build.sbt @@ -17,7 +17,8 @@ val buildSettings = Seq[Setting[_]]( // JVM options for building scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-feature"), javaOptions in Test ++= Seq("-ea"), - javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation", "-source", "1.7", "-target", "1.7"), + javacOptions ++= Seq("-source", "1.7", "-target", "1.7"), + javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation"), // Use lenient validation mode when generating Javadoc (for Java8) javacOptions in doc := { val opts = Seq("-source", "1.7") From 981c9c7788261aea56570e9db89adc84f3d98777 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 16 Jun 2020 02:00:26 -0700 Subject: [PATCH 136/417] Add GitHub Action workflow (x64) and Travis (arm64) build (#524) * Add GitHub Action workflow * Use Travis for arm64 build --- .github/workflows/CI.yml | 60 ++++++++++++++++++++++++++++++++++++++++ .travis.yml | 15 ++-------- 2 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/CI.yml diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 000000000..53b8c7090 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,60 @@ +name: CI + +on: + pull_request: + paths: + - '**.scala' + - '**.java' + - '**.sbt' + - '.github/workflows/**.yml' + push: + branches: + - master + paths: + - '**.scala' + - '**.java' + - '**.sbt' + - '.github/workflows/**.yml' + +jobs: + code_format: + name: Code Format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: jcheckstyle + run: ./sbt jcheckStyle + test_jdk11: + name: Test JDK11 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: olafurpg/setup-scala@v7 + with: + java-version: adopt@1.11 + - uses: actions/cache@v2 + with: + path: ~/.cache + key: ${{ runner.os }}-jdk11-${{ hashFiles('**/*.sbt') }} + restore-keys: ${{ runner.os }}-jdk11- + - name: Test + run: ./sbt test + - name: Universal Buffer Test + run: ./sbt test -J-Dmsgpack.universal-buffer=true + test_jdk8: + name: Test JDK8 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: olafurpg/setup-scala@v7 + with: + java-version: adopt@1.8 + - uses: actions/cache@v2 + with: + path: ~/.cache + key: ${{ runner.os }}-jdk8-${{ hashFiles('**/*.sbt') }} + restore-keys: ${{ runner.os }}-jdk8- + - name: Test + run: ./sbt test + - name: Universal Buffer Test + run: ./sbt test -J-Dmsgpack.universal-buffer=true diff --git a/.travis.yml b/.travis.yml index d1c82a096..f198f64fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: scala -# With xenial, `Installing oraclejdk8` fails due to "Expected feature release number in range of 9 to 14, but got: 8" -dist: trusty +arch: arm64 +os: linux cache: directories: @@ -10,23 +10,12 @@ cache: - $HOME/.sbt/boot/ - $HOME/.coursier -sudo: false - branches: only: - develop matrix: include: - - env: PROJECT=checkstyle - jdk: oraclejdk8 - script: - - ./sbt jcheckStyle - - env: PROJECT=java8 - jdk: oraclejdk8 - script: - - ./sbt test - - ./sbt test -J-Dmsgpack.universal-buffer=true - env: PROJECT=java11 jdk: openjdk11 script: From 793cfcdbb26324d06b91994174fdf1b70515979a Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 26 Aug 2020 20:23:19 +0900 Subject: [PATCH 137/417] Support numeric types in MessagePackParser.getText() --- .../jackson/dataformat/MessagePackParser.java | 8 ++++++++ .../dataformat/MessagePackParserTest.java | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index d6de1ce06..9974c2743 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -383,6 +383,14 @@ public String getText() return stringValue; case BYTES: return new String(bytesValue, MessagePack.UTF8); + case INT: + return String.valueOf(intValue); + case LONG: + return String.valueOf(longValue); + case DOUBLE: + return String.valueOf(doubleValue); + case BIG_INT: + return String.valueOf(biValue); default: throw new IllegalStateException("Invalid type=" + type); } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 2258f2f82..1041a7599 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -365,7 +365,9 @@ public void testReadPrimitives() MessagePacker packer = MessagePack.newDefaultPacker(out); packer.packString("foo"); packer.packDouble(3.14); + packer.packInt(Integer.MIN_VALUE); packer.packLong(Long.MAX_VALUE); + packer.packBigInteger(BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE)); byte[] bytes = {0x00, 0x11, 0x22}; packer.packBinaryHeader(bytes.length); packer.writePayload(bytes); @@ -374,10 +376,24 @@ public void testReadPrimitives() JsonParser parser = factory.createParser(new FileInputStream(tempFile)); assertEquals(JsonToken.VALUE_STRING, parser.nextToken()); assertEquals("foo", parser.getText()); + assertEquals(JsonToken.VALUE_NUMBER_FLOAT, parser.nextToken()); assertEquals(3.14, parser.getDoubleValue(), 0.0001); + assertEquals("3.14", parser.getText()); + + assertEquals(JsonToken.VALUE_NUMBER_INT, parser.nextToken()); + assertEquals(Integer.MIN_VALUE, parser.getIntValue()); + assertEquals(Integer.MIN_VALUE, parser.getLongValue()); + assertEquals("-2147483648", parser.getText()); + assertEquals(JsonToken.VALUE_NUMBER_INT, parser.nextToken()); assertEquals(Long.MAX_VALUE, parser.getLongValue()); + assertEquals("9223372036854775807", parser.getText()); + + assertEquals(JsonToken.VALUE_NUMBER_INT, parser.nextToken()); + assertEquals(BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE), parser.getBigIntegerValue()); + assertEquals("9223372036854775808", parser.getText()); + assertEquals(JsonToken.VALUE_EMBEDDED_OBJECT, parser.nextToken()); assertEquals(bytes.length, parser.getBinaryValue().length); assertEquals(bytes[0], parser.getBinaryValue()[0]); From bd0ebe1516626d93767a45a40dfb09c02bee5f27 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 30 Aug 2020 23:26:11 +0900 Subject: [PATCH 138/417] Update sbt to avoid download failures --- sbt | 560 ++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 318 insertions(+), 242 deletions(-) diff --git a/sbt b/sbt index ffd29c512..11a73fbcf 100755 --- a/sbt +++ b/sbt @@ -2,33 +2,61 @@ # # A more capable sbt runner, coincidentally also called sbt. # Author: Paul Phillips +# https://github.com/paulp/sbt-extras +# +# Generated from http://www.opensource.org/licenses/bsd-license.php +# Copyright (c) 2011, Paul Phillips. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -o pipefail -declare -r sbt_release_version="0.13.16" -declare -r sbt_unreleased_version="0.13.16" +declare -r sbt_release_version="1.3.13" +declare -r sbt_unreleased_version="1.4.0-M1" -declare -r latest_213="2.13.0-M2" -declare -r latest_212="2.12.4" -declare -r latest_211="2.11.11" -declare -r latest_210="2.10.6" +declare -r latest_213="2.13.3" +declare -r latest_212="2.12.12" +declare -r latest_211="2.11.12" +declare -r latest_210="2.10.7" declare -r latest_29="2.9.3" declare -r latest_28="2.8.2" declare -r buildProps="project/build.properties" -declare -r sbt_launch_ivy_release_repo="http://repo.typesafe.com/typesafe/ivy-releases" +declare -r sbt_launch_ivy_release_repo="https://repo.typesafe.com/typesafe/ivy-releases" declare -r sbt_launch_ivy_snapshot_repo="https://repo.scala-sbt.org/scalasbt/ivy-snapshots" -declare -r sbt_launch_mvn_release_repo="http://repo.scala-sbt.org/scalasbt/maven-releases" -declare -r sbt_launch_mvn_snapshot_repo="http://repo.scala-sbt.org/scalasbt/maven-snapshots" +declare -r sbt_launch_mvn_release_repo="https://repo.scala-sbt.org/scalasbt/maven-releases" +declare -r sbt_launch_mvn_snapshot_repo="https://repo.scala-sbt.org/scalasbt/maven-snapshots" -declare -r default_jvm_opts_common="-Xms512m -Xmx1536m -Xss2m" -declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" +declare -r default_jvm_opts_common="-Xms512m -Xss2m -XX:MaxInlineLevel=18" +declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy -Dsbt.coursier.home=project/.coursier" declare sbt_jar sbt_dir sbt_create sbt_version sbt_script sbt_new declare sbt_explicit_version declare verbose noshare batch trace_level -declare debugUs declare java_cmd="java" declare sbt_launch_dir="$HOME/.sbt/launchers" @@ -40,13 +68,17 @@ declare -a java_args scalac_args sbt_commands residual_args # args to jvm/sbt via files or environment variables declare -a extra_jvm_opts extra_sbt_opts -echoerr () { echo >&2 "$@"; } -vlog () { [[ -n "$verbose" ]] && echoerr "$@"; } -die () { echo "Aborting: $@" ; exit 1; } +echoerr() { echo >&2 "$@"; } +vlog() { [[ -n "$verbose" ]] && echoerr "$@"; } +die() { + echo "Aborting: $*" + exit 1 +} -setTrapExit () { +setTrapExit() { # save stty and trap exit, to ensure echo is re-enabled if we are interrupted. - export SBT_STTY="$(stty -g 2>/dev/null)" + SBT_STTY="$(stty -g 2>/dev/null)" + export SBT_STTY # restore stty settings (echo in particular) onSbtRunnerExit() { @@ -62,11 +94,14 @@ setTrapExit () { # this seems to cover the bases on OSX, and someone will # have to tell me about the others. -get_script_path () { +get_script_path() { local path="$1" - [[ -L "$path" ]] || { echo "$path" ; return; } + [[ -L "$path" ]] || { + echo "$path" + return + } - local target="$(readlink "$path")" + local -r target="$(readlink "$path")" if [[ "${target:0:1}" == "/" ]]; then echo "$target" else @@ -74,10 +109,12 @@ get_script_path () { fi } -declare -r script_path="$(get_script_path "$BASH_SOURCE")" -declare -r script_name="${script_path##*/}" +script_path="$(get_script_path "${BASH_SOURCE[0]}")" +declare -r script_path +script_name="${script_path##*/}" +declare -r script_name -init_default_option_file () { +init_default_option_file() { local overriding_var="${!1}" local default_file="$2" if [[ ! -r "$default_file" && "$overriding_var" =~ ^@(.*)$ ]]; then @@ -89,82 +126,82 @@ init_default_option_file () { echo "$default_file" } -declare sbt_opts_file="$(init_default_option_file SBT_OPTS .sbtopts)" -declare jvm_opts_file="$(init_default_option_file JVM_OPTS .jvmopts)" +sbt_opts_file="$(init_default_option_file SBT_OPTS .sbtopts)" +sbtx_opts_file="$(init_default_option_file SBTX_OPTS .sbtxopts)" +jvm_opts_file="$(init_default_option_file JVM_OPTS .jvmopts)" -build_props_sbt () { - [[ -r "$buildProps" ]] && \ +build_props_sbt() { + [[ -r "$buildProps" ]] && grep '^sbt\.version' "$buildProps" | tr '=\r' ' ' | awk '{ print $2; }' } -update_build_props_sbt () { - local ver="$1" - local old="$(build_props_sbt)" - - [[ -r "$buildProps" ]] && [[ "$ver" != "$old" ]] && { - perl -pi -e "s/^sbt\.version\b.*\$/sbt.version=${ver}/" "$buildProps" - grep -q '^sbt.version[ =]' "$buildProps" || printf "\nsbt.version=%s\n" "$ver" >> "$buildProps" - - vlog "!!!" - vlog "!!! Updated file $buildProps setting sbt.version to: $ver" - vlog "!!! Previous value was: $old" - vlog "!!!" - } -} - -set_sbt_version () { +set_sbt_version() { sbt_version="${sbt_explicit_version:-$(build_props_sbt)}" [[ -n "$sbt_version" ]] || sbt_version=$sbt_release_version export sbt_version } -url_base () { +url_base() { local version="$1" case "$version" in - 0.7.*) echo "http://simple-build-tool.googlecode.com" ;; - 0.10.* ) echo "$sbt_launch_ivy_release_repo" ;; + 0.7.*) echo "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/simple-build-tool" ;; + 0.10.*) echo "$sbt_launch_ivy_release_repo" ;; 0.11.[12]) echo "$sbt_launch_ivy_release_repo" ;; 0.*-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]) # ie "*-yyyymmdd-hhMMss" - echo "$sbt_launch_ivy_snapshot_repo" ;; - 0.*) echo "$sbt_launch_ivy_release_repo" ;; - *-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]) # ie "*-yyyymmdd-hhMMss" - echo "$sbt_launch_mvn_snapshot_repo" ;; - *) echo "$sbt_launch_mvn_release_repo" ;; + echo "$sbt_launch_ivy_snapshot_repo" ;; + 0.*) echo "$sbt_launch_ivy_release_repo" ;; + *-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9]) # ie "*-yyyymmddThhMMss" + echo "$sbt_launch_mvn_snapshot_repo" ;; + *) echo "$sbt_launch_mvn_release_repo" ;; esac } -make_url () { +make_url() { local version="$1" local base="${sbt_launch_repo:-$(url_base "$version")}" case "$version" in - 0.7.*) echo "$base/files/sbt-launch-0.7.7.jar" ;; - 0.10.* ) echo "$base/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;; + 0.7.*) echo "$base/sbt-launch-0.7.7.jar" ;; + 0.10.*) echo "$base/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;; 0.11.[12]) echo "$base/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;; - 0.*) echo "$base/org.scala-sbt/sbt-launch/$version/sbt-launch.jar" ;; - *) echo "$base/org/scala-sbt/sbt-launch/$version/sbt-launch.jar" ;; + 0.*) echo "$base/org.scala-sbt/sbt-launch/$version/sbt-launch.jar" ;; + *) echo "$base/org/scala-sbt/sbt-launch/$version/sbt-launch-${version}.jar" ;; esac } -addJava () { vlog "[addJava] arg = '$1'" ; java_args+=("$1"); } -addSbt () { vlog "[addSbt] arg = '$1'" ; sbt_commands+=("$1"); } -addScalac () { vlog "[addScalac] arg = '$1'" ; scalac_args+=("$1"); } -addResidual () { vlog "[residual] arg = '$1'" ; residual_args+=("$1"); } +addJava() { + vlog "[addJava] arg = '$1'" + java_args+=("$1") +} +addSbt() { + vlog "[addSbt] arg = '$1'" + sbt_commands+=("$1") +} +addScalac() { + vlog "[addScalac] arg = '$1'" + scalac_args+=("$1") +} +addResidual() { + vlog "[residual] arg = '$1'" + residual_args+=("$1") +} + +addResolver() { addSbt "set resolvers += $1"; } -addResolver () { addSbt "set resolvers += $1"; } -addDebugger () { addJava "-Xdebug" ; addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1"; } -setThisBuild () { - vlog "[addBuild] args = '$@'" +addDebugger() { addJava "-Xdebug" && addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1"; } + +setThisBuild() { + vlog "[addBuild] args = '$*'" local key="$1" && shift - addSbt "set $key in ThisBuild := $@" + addSbt "set $key in ThisBuild := $*" } -setScalaVersion () { +setScalaVersion() { [[ "$1" == *"-SNAPSHOT" ]] && addResolver 'Resolver.sonatypeRepo("snapshots")' addSbt "++ $1" } -setJavaHome () { +setJavaHome() { java_cmd="$1/bin/java" setThisBuild javaHome "_root_.scala.Some(file(\"$1\"))" export JAVA_HOME="$1" @@ -172,13 +209,25 @@ setJavaHome () { export PATH="$JAVA_HOME/bin:$PATH" } -getJavaVersion() { "$1" -version 2>&1 | grep -E -e '(java|openjdk) version' | awk '{ print $3 }' | tr -d \"; } +getJavaVersion() { + local -r str=$("$1" -version 2>&1 | grep -E -e '(java|openjdk) version' | awk '{ print $3 }' | tr -d '"') + + # java -version on java8 says 1.8.x + # but on 9 and 10 it's 9.x.y and 10.x.y. + if [[ "$str" =~ ^1\.([0-9]+)(\..*)?$ ]]; then + echo "${BASH_REMATCH[1]}" + elif [[ "$str" =~ ^([0-9]+)(\..*)?$ ]]; then + echo "${BASH_REMATCH[1]}" + elif [[ -n "$str" ]]; then + echoerr "Can't parse java version from: $str" + fi +} checkJava() { # Warn if there is a Java version mismatch between PATH and JAVA_HOME/JDK_HOME - [[ -n "$JAVA_HOME" && -e "$JAVA_HOME/bin/java" ]] && java="$JAVA_HOME/bin/java" - [[ -n "$JDK_HOME" && -e "$JDK_HOME/lib/tools.jar" ]] && java="$JDK_HOME/bin/java" + [[ -n "$JAVA_HOME" && -e "$JAVA_HOME/bin/java" ]] && java="$JAVA_HOME/bin/java" + [[ -n "$JDK_HOME" && -e "$JDK_HOME/lib/tools.jar" ]] && java="$JDK_HOME/bin/java" if [[ -n "$java" ]]; then pathJavaVersion=$(getJavaVersion java) @@ -192,31 +241,25 @@ checkJava() { fi } -java_version () { - local version=$(getJavaVersion "$java_cmd") +java_version() { + local -r version=$(getJavaVersion "$java_cmd") vlog "Detected Java version: $version" - echo "${version:2:1}" + echo "$version" } # MaxPermSize critical on pre-8 JVMs but incurs noisy warning on 8+ -default_jvm_opts () { - local v="$(java_version)" - if [[ $v -ge 8 ]]; then +default_jvm_opts() { + local -r v="$(java_version)" + if [[ $v -ge 10 ]]; then + echo "$default_jvm_opts_common -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler" + elif [[ $v -ge 8 ]]; then echo "$default_jvm_opts_common" else echo "-XX:MaxPermSize=384m $default_jvm_opts_common" fi } -build_props_scala () { - if [[ -r "$buildProps" ]]; then - versionLine="$(grep '^build.scala.versions' "$buildProps")" - versionString="${versionLine##build.scala.versions=}" - echo "${versionString%% .*}" - fi -} - -execRunner () { +execRunner() { # print the arguments one to a line, quoting any containing spaces vlog "# Executing command line:" && { for arg; do @@ -234,40 +277,36 @@ execRunner () { setTrapExit if [[ -n "$batch" ]]; then - "$@" < /dev/null + "$@" /dev/null; then + if command -v curl >/dev/null 2>&1; then curl --fail --silent --location "$url" --output "$jar" - elif which wget >/dev/null; then + elif command -v wget >/dev/null 2>&1; then wget -q -O "$jar" "$url" fi } && [[ -r "$jar" ]] } -acquire_sbt_jar () { +acquire_sbt_jar() { { sbt_jar="$(jar_file "$sbt_version")" [[ -r "$sbt_jar" ]] @@ -276,11 +315,66 @@ acquire_sbt_jar () { [[ -r "$sbt_jar" ]] } || { sbt_jar="$(jar_file "$sbt_version")" - download_url "$(make_url "$sbt_version")" "$sbt_jar" + jar_url="$(make_url "$sbt_version")" + + echoerr "Downloading sbt launcher for ${sbt_version}:" + echoerr " From ${jar_url}" + echoerr " To ${sbt_jar}" + + download_url "${jar_url}" "${sbt_jar}" + + case "${sbt_version}" in + 0.*) + vlog "SBT versions < 1.0 do not have published MD5 checksums, skipping check" + echo "" + ;; + *) verify_sbt_jar "${sbt_jar}" ;; + esac } } -usage () { +verify_sbt_jar() { + local jar="${1}" + local md5="${jar}.md5" + md5url="$(make_url "${sbt_version}").md5" + + echoerr "Downloading sbt launcher ${sbt_version} md5 hash:" + echoerr " From ${md5url}" + echoerr " To ${md5}" + + download_url "${md5url}" "${md5}" >/dev/null 2>&1 + + if command -v md5sum >/dev/null 2>&1; then + if echo "$(cat "${md5}") ${jar}" | md5sum -c -; then + rm -rf "${md5}" + return 0 + else + echoerr "Checksum does not match" + return 1 + fi + elif command -v md5 >/dev/null 2>&1; then + if [ "$(md5 -q "${jar}")" == "$(cat "${md5}")" ]; then + rm -rf "${md5}" + return 0 + else + echoerr "Checksum does not match" + return 1 + fi + elif command -v openssl >/dev/null 2>&1; then + if [ "$(openssl md5 -r "${jar}" | awk '{print $1}')" == "$(cat "${md5}")" ]; then + rm -rf "${md5}" + return 0 + else + echoerr "Checksum does not match" + return 1 + fi + else + echoerr "Could not find an MD5 command" + return 1 + fi +} + +usage() { set_sbt_version cat < Run the specified file as a scala script # sbt version (default: sbt.version from $buildProps if present, otherwise $sbt_release_version) - -sbt-force-latest force the use of the latest release of sbt: $sbt_release_version - -sbt-version use the specified version of sbt (default: $sbt_release_version) - -sbt-dev use the latest pre-release version of sbt: $sbt_unreleased_version - -sbt-jar use the specified jar as the sbt launcher - -sbt-launch-dir directory to hold sbt launchers (default: $sbt_launch_dir) - -sbt-launch-repo repo url for downloading sbt launcher jar (default: $(url_base "$sbt_version")) + -sbt-version use the specified version of sbt (default: $sbt_release_version) + -sbt-force-latest force the use of the latest release of sbt: $sbt_release_version + -sbt-dev use the latest pre-release version of sbt: $sbt_unreleased_version + -sbt-jar use the specified jar as the sbt launcher + -sbt-launch-dir directory to hold sbt launchers (default: $sbt_launch_dir) + -sbt-launch-repo repo url for downloading sbt launcher jar (default: $(url_base "$sbt_version")) # scala version (default: as chosen by sbt) - -28 use $latest_28 - -29 use $latest_29 - -210 use $latest_210 - -211 use $latest_211 - -212 use $latest_212 - -213 use $latest_213 - -scala-home use the scala build at the specified directory - -scala-version use the specified version of scala - -binary-version use the specified scala version when searching for dependencies + -28 use $latest_28 + -29 use $latest_29 + -210 use $latest_210 + -211 use $latest_211 + -212 use $latest_212 + -213 use $latest_213 + -scala-home use the scala build at the specified directory + -scala-version use the specified version of scala + -binary-version use the specified scala version when searching for dependencies # java version (default: java from PATH, currently $(java -version 2>&1 | grep version)) - -java-home alternate JAVA_HOME + -java-home alternate JAVA_HOME # passing options to the jvm - note it does NOT use JAVA_OPTS due to pollution # The default set is used if JVM_OPTS is unset and no -jvm-opts file is found - $(default_jvm_opts) - JVM_OPTS environment variable holding either the jvm args directly, or - the reference to a file containing jvm args if given path is prepended by '@' (e.g. '@/etc/jvmopts') - Note: "@"-file is overridden by local '.jvmopts' or '-jvm-opts' argument. - -jvm-opts file containing jvm args (if not given, .jvmopts in project root is used if present) - -Dkey=val pass -Dkey=val directly to the jvm - -J-X pass option -X directly to the jvm (-J is stripped) + $(default_jvm_opts) + JVM_OPTS environment variable holding either the jvm args directly, or + the reference to a file containing jvm args if given path is prepended by '@' (e.g. '@/etc/jvmopts') + Note: "@"-file is overridden by local '.jvmopts' or '-jvm-opts' argument. + -jvm-opts file containing jvm args (if not given, .jvmopts in project root is used if present) + -Dkey=val pass -Dkey=val directly to the jvm + -J-X pass option -X directly to the jvm (-J is stripped) # passing options to sbt, OR to this runner - SBT_OPTS environment variable holding either the sbt args directly, or - the reference to a file containing sbt args if given path is prepended by '@' (e.g. '@/etc/sbtopts') - Note: "@"-file is overridden by local '.sbtopts' or '-sbt-opts' argument. - -sbt-opts file containing sbt args (if not given, .sbtopts in project root is used if present) - -S-X add -X to sbt's scalacOptions (-S is stripped) + SBT_OPTS environment variable holding either the sbt args directly, or + the reference to a file containing sbt args if given path is prepended by '@' (e.g. '@/etc/sbtopts') + Note: "@"-file is overridden by local '.sbtopts' or '-sbt-opts' argument. + -sbt-opts file containing sbt args (if not given, .sbtopts in project root is used if present) + -S-X add -X to sbt's scalacOptions (-S is stripped) + + # passing options exclusively to this runner + SBTX_OPTS environment variable holding either the sbt-extras args directly, or + the reference to a file containing sbt-extras args if given path is prepended by '@' (e.g. '@/etc/sbtxopts') + Note: "@"-file is overridden by local '.sbtxopts' or '-sbtx-opts' argument. + -sbtx-opts file containing sbt-extras args (if not given, .sbtxopts in project root is used if present) EOM + exit 0 } -process_args () { - require_arg () { +process_args() { + require_arg() { local type="$1" local opt="$2" local arg="$3" @@ -367,50 +462,56 @@ process_args () { } while [[ $# -gt 0 ]]; do case "$1" in - -h|-help) usage; exit 0 ;; - -v) verbose=true && shift ;; - -d) addSbt "--debug" && shift ;; - -w) addSbt "--warn" && shift ;; - -q) addSbt "--error" && shift ;; - -x) debugUs=true && shift ;; - -trace) require_arg integer "$1" "$2" && trace_level="$2" && shift 2 ;; - -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; - -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; - -no-share) noshare=true && shift ;; - -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; - -sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;; - -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; - -offline) addSbt "set offline in Global := true" && shift ;; - -jvm-debug) require_arg port "$1" "$2" && addDebugger "$2" && shift 2 ;; - -batch) batch=true && shift ;; - -prompt) require_arg "expr" "$1" "$2" && setThisBuild shellPrompt "(s => { val e = Project.extract(s) ; $2 })" && shift 2 ;; - -script) require_arg file "$1" "$2" && sbt_script="$2" && addJava "-Dsbt.main.class=sbt.ScriptMain" && shift 2 ;; - - -sbt-create) sbt_create=true && shift ;; - -sbt-jar) require_arg path "$1" "$2" && sbt_jar="$2" && shift 2 ;; + -h | -help) usage ;; + -v) verbose=true && shift ;; + -d) addSbt "--debug" && shift ;; + -w) addSbt "--warn" && shift ;; + -q) addSbt "--error" && shift ;; + -x) shift ;; # currently unused + -trace) require_arg integer "$1" "$2" && trace_level="$2" && shift 2 ;; + -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; + + -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; + -sbt-create) sbt_create=true && shift ;; + -sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;; + -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; + -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; + -no-share) noshare=true && shift ;; + -offline) addSbt "set offline in Global := true" && shift ;; + -jvm-debug) require_arg port "$1" "$2" && addDebugger "$2" && shift 2 ;; + -batch) batch=true && shift ;; + -prompt) require_arg "expr" "$1" "$2" && setThisBuild shellPrompt "(s => { val e = Project.extract(s) ; $2 })" && shift 2 ;; + -script) require_arg file "$1" "$2" && sbt_script="$2" && addJava "-Dsbt.main.class=sbt.ScriptMain" && shift 2 ;; + -sbt-version) require_arg version "$1" "$2" && sbt_explicit_version="$2" && shift 2 ;; - -sbt-force-latest) sbt_explicit_version="$sbt_release_version" && shift ;; - -sbt-dev) sbt_explicit_version="$sbt_unreleased_version" && shift ;; - -sbt-launch-dir) require_arg path "$1" "$2" && sbt_launch_dir="$2" && shift 2 ;; - -sbt-launch-repo) require_arg path "$1" "$2" && sbt_launch_repo="$2" && shift 2 ;; - -scala-version) require_arg version "$1" "$2" && setScalaVersion "$2" && shift 2 ;; - -binary-version) require_arg version "$1" "$2" && setThisBuild scalaBinaryVersion "\"$2\"" && shift 2 ;; - -scala-home) require_arg path "$1" "$2" && setThisBuild scalaHome "_root_.scala.Some(file(\"$2\"))" && shift 2 ;; - -java-home) require_arg path "$1" "$2" && setJavaHome "$2" && shift 2 ;; - -sbt-opts) require_arg path "$1" "$2" && sbt_opts_file="$2" && shift 2 ;; - -jvm-opts) require_arg path "$1" "$2" && jvm_opts_file="$2" && shift 2 ;; - - -D*) addJava "$1" && shift ;; - -J*) addJava "${1:2}" && shift ;; - -S*) addScalac "${1:2}" && shift ;; - -28) setScalaVersion "$latest_28" && shift ;; - -29) setScalaVersion "$latest_29" && shift ;; - -210) setScalaVersion "$latest_210" && shift ;; - -211) setScalaVersion "$latest_211" && shift ;; - -212) setScalaVersion "$latest_212" && shift ;; - -213) setScalaVersion "$latest_213" && shift ;; - new) sbt_new=true && : ${sbt_explicit_version:=$sbt_release_version} && addResidual "$1" && shift ;; - *) addResidual "$1" && shift ;; + -sbt-force-latest) sbt_explicit_version="$sbt_release_version" && shift ;; + -sbt-dev) sbt_explicit_version="$sbt_unreleased_version" && shift ;; + -sbt-jar) require_arg path "$1" "$2" && sbt_jar="$2" && shift 2 ;; + -sbt-launch-dir) require_arg path "$1" "$2" && sbt_launch_dir="$2" && shift 2 ;; + -sbt-launch-repo) require_arg path "$1" "$2" && sbt_launch_repo="$2" && shift 2 ;; + + -28) setScalaVersion "$latest_28" && shift ;; + -29) setScalaVersion "$latest_29" && shift ;; + -210) setScalaVersion "$latest_210" && shift ;; + -211) setScalaVersion "$latest_211" && shift ;; + -212) setScalaVersion "$latest_212" && shift ;; + -213) setScalaVersion "$latest_213" && shift ;; + + -scala-version) require_arg version "$1" "$2" && setScalaVersion "$2" && shift 2 ;; + -binary-version) require_arg version "$1" "$2" && setThisBuild scalaBinaryVersion "\"$2\"" && shift 2 ;; + -scala-home) require_arg path "$1" "$2" && setThisBuild scalaHome "_root_.scala.Some(file(\"$2\"))" && shift 2 ;; + -java-home) require_arg path "$1" "$2" && setJavaHome "$2" && shift 2 ;; + -sbt-opts) require_arg path "$1" "$2" && sbt_opts_file="$2" && shift 2 ;; + -sbtx-opts) require_arg path "$1" "$2" && sbtx_opts_file="$2" && shift 2 ;; + -jvm-opts) require_arg path "$1" "$2" && jvm_opts_file="$2" && shift 2 ;; + + -D*) addJava "$1" && shift ;; + -J*) addJava "${1:2}" && shift ;; + -S*) addScalac "${1:2}" && shift ;; + + new) sbt_new=true && : ${sbt_explicit_version:=$sbt_release_version} && addResidual "$1" && shift ;; + + *) addResidual "$1" && shift ;; esac done } @@ -422,19 +523,31 @@ process_args "$@" readConfigFile() { local end=false until $end; do - read || end=true + read -r || end=true [[ $REPLY =~ ^# ]] || [[ -z $REPLY ]] || echo "$REPLY" - done < "$1" + done <"$1" } # if there are file/environment sbt_opts, process again so we # can supply args to this runner if [[ -r "$sbt_opts_file" ]]; then vlog "Using sbt options defined in file $sbt_opts_file" - while read opt; do extra_sbt_opts+=("$opt"); done < <(readConfigFile "$sbt_opts_file") + while read -r opt; do extra_sbt_opts+=("$opt"); done < <(readConfigFile "$sbt_opts_file") elif [[ -n "$SBT_OPTS" && ! ("$SBT_OPTS" =~ ^@.*) ]]; then vlog "Using sbt options defined in variable \$SBT_OPTS" - extra_sbt_opts=( $SBT_OPTS ) + IFS=" " read -r -a extra_sbt_opts <<<"$SBT_OPTS" +else + vlog "No extra sbt options have been defined" +fi + +# if there are file/environment sbtx_opts, process again so we +# can supply args to this runner +if [[ -r "$sbtx_opts_file" ]]; then + vlog "Using sbt options defined in file $sbtx_opts_file" + while read -r opt; do extra_sbt_opts+=("$opt"); done < <(readConfigFile "$sbtx_opts_file") +elif [[ -n "$SBTX_OPTS" && ! ("$SBTX_OPTS" =~ ^@.*) ]]; then + vlog "Using sbt options defined in variable \$SBTX_OPTS" + IFS=" " read -r -a extra_sbt_opts <<<"$SBTX_OPTS" else vlog "No extra sbt options have been defined" fi @@ -453,25 +566,24 @@ checkJava # only exists in 0.12+ setTraceLevel() { case "$sbt_version" in - "0.7."* | "0.10."* | "0.11."* ) echoerr "Cannot set trace level in sbt version $sbt_version" ;; - *) setThisBuild traceLevel $trace_level ;; + "0.7."* | "0.10."* | "0.11."*) echoerr "Cannot set trace level in sbt version $sbt_version" ;; + *) setThisBuild traceLevel "$trace_level" ;; esac } # set scalacOptions if we were given any -S opts -[[ ${#scalac_args[@]} -eq 0 ]] || addSbt "set scalacOptions in ThisBuild += \"${scalac_args[@]}\"" +[[ ${#scalac_args[@]} -eq 0 ]] || addSbt "set scalacOptions in ThisBuild += \"${scalac_args[*]}\"" -# Update build.properties on disk to set explicit version - sbt gives us no choice -[[ -n "$sbt_explicit_version" && -z "$sbt_new" ]] && update_build_props_sbt "$sbt_explicit_version" +[[ -n "$sbt_explicit_version" && -z "$sbt_new" ]] && addJava "-Dsbt.version=$sbt_explicit_version" vlog "Detected sbt version $sbt_version" if [[ -n "$sbt_script" ]]; then - residual_args=( $sbt_script ${residual_args[@]} ) + residual_args=("$sbt_script" "${residual_args[@]}") else # no args - alert them there's stuff in here - (( argumentCount > 0 )) || { + ((argumentCount > 0)) || { vlog "Starting $script_name: invoke with -help for other options" - residual_args=( shell ) + residual_args=(shell) } fi @@ -487,6 +599,7 @@ EOM } # pick up completion if present; todo +# shellcheck disable=SC1091 [[ -r .sbt_completion.sh ]] && source .sbt_completion.sh # directory to store sbt launchers @@ -496,7 +609,7 @@ EOM # no jar? download it. [[ -r "$sbt_jar" ]] || acquire_sbt_jar || { # still no jar? uh-oh. - echo "Download failed. Obtain the jar manually and place it at $sbt_jar" + echo "Could not download and verify the launcher. Obtain the jar manually and place it at $sbt_jar" exit 1 } @@ -506,12 +619,12 @@ if [[ -n "$noshare" ]]; then done else case "$sbt_version" in - "0.7."* | "0.10."* | "0.11."* | "0.12."* ) + "0.7."* | "0.10."* | "0.11."* | "0.12."*) [[ -n "$sbt_dir" ]] || { sbt_dir="$HOME/.sbt/$sbt_version" vlog "Using $sbt_dir as sbt dir, -sbt-dir to override." } - ;; + ;; esac if [[ -n "$sbt_dir" ]]; then @@ -521,58 +634,21 @@ fi if [[ -r "$jvm_opts_file" ]]; then vlog "Using jvm options defined in file $jvm_opts_file" - while read opt; do extra_jvm_opts+=("$opt"); done < <(readConfigFile "$jvm_opts_file") + while read -r opt; do extra_jvm_opts+=("$opt"); done < <(readConfigFile "$jvm_opts_file") elif [[ -n "$JVM_OPTS" && ! ("$JVM_OPTS" =~ ^@.*) ]]; then vlog "Using jvm options defined in \$JVM_OPTS variable" - extra_jvm_opts=( $JVM_OPTS ) + IFS=" " read -r -a extra_jvm_opts <<<"$JVM_OPTS" else vlog "Using default jvm options" - extra_jvm_opts=( $(default_jvm_opts) ) + IFS=" " read -r -a extra_jvm_opts <<<"$( default_jvm_opts)" fi # traceLevel is 0.12+ [[ -n "$trace_level" ]] && setTraceLevel -main () { - execRunner "$java_cmd" \ - "${extra_jvm_opts[@]}" \ - "${java_args[@]}" \ - -jar "$sbt_jar" \ - "${sbt_commands[@]}" \ - "${residual_args[@]}" -} - -# sbt inserts this string on certain lines when formatting is enabled: -# val OverwriteLine = "\r\u001BM\u001B[2K" -# ...in order not to spam the console with a million "Resolving" lines. -# Unfortunately that makes it that much harder to work with when -# we're not going to print those lines anyway. We strip that bit of -# line noise, but leave the other codes to preserve color. -mainFiltered () { - local ansiOverwrite='\r\x1BM\x1B[2K' - local excludeRegex=$(egrep -v '^#|^$' ~/.sbtignore | paste -sd'|' -) - - echoLine () { - local line="$1" - local line1="$(echo "$line" | sed 's/\r\x1BM\x1B\[2K//g')" # This strips the OverwriteLine code. - local line2="$(echo "$line1" | sed 's/\x1B\[[0-9;]*[JKmsu]//g')" # This strips all codes - we test regexes against this. - - if [[ $line2 =~ $excludeRegex ]]; then - [[ -n $debugUs ]] && echo "[X] $line1" - else - [[ -n $debugUs ]] && echo " $line1" || echo "$line1" - fi - } - - echoLine "Starting sbt with output filtering enabled." - main | while read -r line; do echoLine "$line"; done -} - -# Only filter if there's a filter file and we don't see a known interactive command. -# Obviously this is super ad hoc but I don't know how to improve on it. Testing whether -# stdin is a terminal is useless because most of my use cases for this filtering are -# exactly when I'm at a terminal, running sbt non-interactively. -shouldFilter () { [[ -f ~/.sbtignore ]] && ! egrep -q '\b(shell|console|consoleProject)\b' <<<"${residual_args[@]}"; } - -# run sbt -if shouldFilter; then mainFiltered; else main; fi +execRunner "$java_cmd" \ + "${extra_jvm_opts[@]}" \ + "${java_args[@]}" \ + -jar "$sbt_jar" \ + "${sbt_commands[@]}" \ + "${residual_args[@]}" From 18c12ec35be6056d619d1535754e17aa24a5d7bd Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Sun, 30 Aug 2020 22:24:18 +0200 Subject: [PATCH 139/417] use latest version of jackdon (2.11.2) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3329fbfd6..62761a910 100644 --- a/build.sbt +++ b/build.sbt @@ -116,7 +116,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9.3", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.11.2", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From ed6997c97ba863469d2bf120e37e2d44a19d9d16 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Sun, 30 Aug 2020 22:39:29 +0200 Subject: [PATCH 140/417] jackson 2.10.5 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 62761a910..35c2558ef 100644 --- a/build.sbt +++ b/build.sbt @@ -116,7 +116,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.11.2", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 0348a49e7a44a422f92561bab0d8f231c47dd1f7 Mon Sep 17 00:00:00 2001 From: Minh Date: Mon, 31 Aug 2020 11:23:20 -0700 Subject: [PATCH 141/417] fix indexing bug in constructor (#525) fix ValueFactory.newMap(Entry...pairs), which is currently iterating by 2 when it should be iterating through each passed in pair. --- msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java b/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java index 5fc8f81fe..21a4f85dd 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java @@ -232,7 +232,7 @@ public static ImmutableMapValue emptyMap() public static MapValue newMap(Map.Entry... pairs) { Value[] kvs = new Value[pairs.length * 2]; - for (int i = 0; i < pairs.length; i += 2) { + for (int i = 0; i < pairs.length; ++i) { kvs[i * 2] = pairs[i].getKey(); kvs[i * 2 + 1] = pairs[i].getValue(); } From 36144f98977d46ee3018bd8a7b42bcbfb3dc7a24 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 12 Sep 2020 15:53:40 +0900 Subject: [PATCH 142/417] Add 0.8.21 release note --- RELEASE_NOTES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index dd241f178..519988d0a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,11 @@ # Release Notes +## 0.8.21 + * Fix indexing bug in ValueFactory [#525](https://github.com/msgpack/msgpack-java/pull/525) + * Support numeric types in MessagePackParser.getText() [#527](https://github.com/msgpack/msgpack-java/pull/527) + * Use jackson-databind 2.10.5 for security vulnerability [#528](https://github.com/msgpack/msgpack-java/pull/528) + * (internal) Ensure building msgpack-java for Java 7 target [#523](https://github.com/msgpack/msgpack-java/pull/523) + ## 0.8.20 * Rebuild 0.8.19 with JDK8 From ab664e7f06abdb52dbfad850acf5e8ba08807a50 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 12 Sep 2020 16:00:52 +0900 Subject: [PATCH 143/417] Setting version to 0.8.21 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 9e4cb15e6..90144eb91 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.21-SNAPSHOT" +version in ThisBuild := "0.8.21" From a67d8dbbaf4293be0820a68a27fcb044a5f12414 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 12 Sep 2020 16:10:53 +0900 Subject: [PATCH 144/417] Setting version to 0.8.22-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 90144eb91..fbd50a0e5 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.21" +version in ThisBuild := "0.8.22-SNAPSHOT" From 5c2be3ad87cc433308d60efeab8ccf3203c0dae1 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 13 Dec 2020 16:08:32 +0900 Subject: [PATCH 145/417] Upgrade to setup-scala v10 to fix GitHub Action CI (#538) * Use latest setup-scala * Update CI.yml Co-authored-by: Taro L. Saito --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 53b8c7090..fde9f4608 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: olafurpg/setup-scala@v7 + - uses: olafurpg/setup-scala@v10 with: java-version: adopt@1.11 - uses: actions/cache@v2 @@ -46,7 +46,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: olafurpg/setup-scala@v7 + - uses: olafurpg/setup-scala@v10 with: java-version: adopt@1.8 - uses: actions/cache@v2 From 136f32b85728c2d8057ee743dcaa71de93640224 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 12 Dec 2020 21:39:03 +0900 Subject: [PATCH 146/417] Support ext type as map-key --- .../jackson/dataformat/MessagePackParser.java | 28 +++-- .../dataformat/MessagePackParserTest.java | 107 ++++++++++++++++++ 2 files changed, 127 insertions(+), 8 deletions(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 9974c2743..55aacd66b 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -341,7 +341,13 @@ public JsonToken nextToken() type = Type.EXT; ExtensionTypeHeader header = messageUnpacker.unpackExtensionTypeHeader(); extensionTypeValue = new MessagePackExtensionType(header.getType(), messageUnpacker.readPayload(header.getLength())); - nextToken = JsonToken.VALUE_EMBEDDED_OBJECT; + if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { + parsingContext.setCurrentName(getExtensionTypeValue().toString()); + nextToken = JsonToken.FIELD_NAME; + } + else { + nextToken = JsonToken.VALUE_EMBEDDED_OBJECT; + } break; default: throw new IllegalStateException("Shouldn't reach here"); @@ -563,6 +569,18 @@ public BigDecimal getDecimalValue() } } + private Object getExtensionTypeValue() + throws IOException + { + if (extTypeCustomDesers != null) { + ExtensionTypeCustomDeserializers.Deser deser = extTypeCustomDesers.getDeser(extensionTypeValue.getType()); + if (deser != null) { + return deser.deserialize(extensionTypeValue.getData()); + } + } + return extensionTypeValue; + } + @Override public Object getEmbeddedObject() throws IOException, JsonParseException @@ -571,13 +589,7 @@ public Object getEmbeddedObject() case BYTES: return bytesValue; case EXT: - if (extTypeCustomDesers != null) { - ExtensionTypeCustomDeserializers.Deser deser = extTypeCustomDesers.getDeser(extensionTypeValue.getType()); - if (deser != null) { - return deser.deserialize(extensionTypeValue.getData()); - } - } - return extensionTypeValue; + return getExtensionTypeValue(); default: throw new IllegalStateException("Invalid type=" + type); } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 1041a7599..64ea94996 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -15,6 +15,7 @@ // package org.msgpack.jackson.dataformat; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; @@ -22,13 +23,19 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; import org.junit.Test; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; +import org.msgpack.value.ExtensionValue; +import org.msgpack.value.MapValue; +import org.msgpack.value.ValueFactory; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -44,6 +51,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; @@ -775,6 +783,105 @@ public Object deserialize(byte[] data) assertThat((String) values.get(4), is("Java")); } + + static class UUIDSerializer + extends StdSerializer + { + private final byte code; + + UUIDSerializer(byte code) + { + super(UUID.class); + this.code = code; + } + + public void serialize(UUID value, JsonGenerator jsonGenerator, SerializerProvider provider) + throws IOException + { + if (jsonGenerator instanceof MessagePackGenerator) { + MessagePackGenerator messagePackGenerator = (MessagePackGenerator) jsonGenerator; + messagePackGenerator.writeExtensionType(new MessagePackExtensionType(code, toBytes(value))); + } else { + throw new RuntimeException("Something went wrong with the serialization"); + } + } + + @SuppressWarnings("WeakerAccess") + static byte[] toBytes(UUID value) + { + return value.toString().getBytes(); + } + + static UUID fromBytes(byte[] value) + { + return UUID.fromString(new String(value)); + } + } + + @Test + public void extensionTypeInMap() + throws IOException + { + byte uuidTypeCode = 42; + + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addCustomDeser(uuidTypeCode, new ExtensionTypeCustomDeserializers.Deser() + { + @Override + public Object deserialize(byte[] value1) + throws IOException + { + return UUIDSerializer.fromBytes(value1); + } + }); + + ObjectMapper objectMapper = new ObjectMapper( + new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); + + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addDeserializer(UUID.class, + new JsonDeserializer() + { + @Override + public UUID deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return UUID.fromString(p.readValueAs(String.class)); + } + }); + objectMapper.registerModule(simpleModule); + + // Prepare serialized data + Map originalMap = new HashMap<>(); + byte[] serializedData; + { + ValueFactory.MapBuilder mapBuilder = ValueFactory.newMapBuilder(); + for (int i = 0; i < 4; i++) { + UUID uuidKey = UUID.randomUUID(); + UUID uuidValue = UUID.randomUUID(); + ExtensionValue k = ValueFactory.newExtension(uuidTypeCode, uuidKey.toString().getBytes()); + ExtensionValue v = ValueFactory.newExtension(uuidTypeCode, uuidValue.toString().getBytes()); + mapBuilder.put(k, v); + originalMap.put(uuidKey, uuidValue); + } + ByteArrayOutputStream output = new ByteArrayOutputStream(); + MessagePacker packer = MessagePack.newDefaultPacker(output); + MapValue mapValue = mapBuilder.build(); + mapValue.writeTo(packer); + packer.close(); + + serializedData = output.toByteArray(); + } + + Map deserializedMap = objectMapper.readValue(serializedData, + new TypeReference>() {}); + + assertEquals(originalMap.size(), deserializedMap.size()); + for (Map.Entry entry : originalMap.entrySet()) { + assertEquals(entry.getValue(), deserializedMap.get(entry.getKey())); + } + } + @Test public void parserShouldReadStrAsBin() throws IOException From 8bb06603916f00bcb50ff722f662d4d8a0e3f296 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 12 Dec 2020 23:36:16 +0900 Subject: [PATCH 147/417] Remove verbose code --- .../jackson/dataformat/MessagePackParser.java | 2 + .../dataformat/MessagePackParserTest.java | 56 +------------------ 2 files changed, 4 insertions(+), 54 deletions(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 55aacd66b..6b97e4f12 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -397,6 +397,8 @@ public String getText() return String.valueOf(doubleValue); case BIG_INT: return String.valueOf(biValue); + case EXT: + return new String(extensionTypeValue.getData()); default: throw new IllegalStateException("Invalid type=" + type); } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 64ea94996..15760b5a8 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -15,7 +15,6 @@ // package org.msgpack.jackson.dataformat; -import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; @@ -23,13 +22,10 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; import org.junit.Test; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; @@ -783,41 +779,6 @@ public Object deserialize(byte[] data) assertThat((String) values.get(4), is("Java")); } - - static class UUIDSerializer - extends StdSerializer - { - private final byte code; - - UUIDSerializer(byte code) - { - super(UUID.class); - this.code = code; - } - - public void serialize(UUID value, JsonGenerator jsonGenerator, SerializerProvider provider) - throws IOException - { - if (jsonGenerator instanceof MessagePackGenerator) { - MessagePackGenerator messagePackGenerator = (MessagePackGenerator) jsonGenerator; - messagePackGenerator.writeExtensionType(new MessagePackExtensionType(code, toBytes(value))); - } else { - throw new RuntimeException("Something went wrong with the serialization"); - } - } - - @SuppressWarnings("WeakerAccess") - static byte[] toBytes(UUID value) - { - return value.toString().getBytes(); - } - - static UUID fromBytes(byte[] value) - { - return UUID.fromString(new String(value)); - } - } - @Test public void extensionTypeInMap() throws IOException @@ -828,29 +789,16 @@ public void extensionTypeInMap() extTypeCustomDesers.addCustomDeser(uuidTypeCode, new ExtensionTypeCustomDeserializers.Deser() { @Override - public Object deserialize(byte[] value1) + public Object deserialize(byte[] value) throws IOException { - return UUIDSerializer.fromBytes(value1); + return UUID.fromString(new String(value)); } }); ObjectMapper objectMapper = new ObjectMapper( new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); - SimpleModule simpleModule = new SimpleModule(); - simpleModule.addDeserializer(UUID.class, - new JsonDeserializer() - { - @Override - public UUID deserialize(JsonParser p, DeserializationContext ctxt) - throws IOException, JsonProcessingException - { - return UUID.fromString(p.readValueAs(String.class)); - } - }); - objectMapper.registerModule(simpleModule); - // Prepare serialized data Map originalMap = new HashMap<>(); byte[] serializedData; From 4b2e4a1b1db9d04c490fc017c0c14fc097b35fb3 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 13 Dec 2020 21:50:23 +0900 Subject: [PATCH 148/417] Add MessagePackParserTest#extensionTypeWithPojoInMap --- .../jackson/dataformat/MessagePackParser.java | 2 + .../dataformat/MessagePackParserTest.java | 163 +++++++++++++++++- 2 files changed, 157 insertions(+), 8 deletions(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 6b97e4f12..20c2ddc5f 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -440,6 +440,8 @@ public byte[] getBinaryValue(Base64Variant b64variant) return bytesValue; case STRING: return stringValue.getBytes(MessagePack.UTF8); + case EXT: + return extensionTypeValue.getData(); default: throw new IllegalStateException("Invalid type=" + type); } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 15760b5a8..fce4bb2f5 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import org.junit.Test; import org.msgpack.core.MessagePack; @@ -779,14 +780,160 @@ public Object deserialize(byte[] data) assertThat((String) values.get(4), is("Java")); } + static class TripleBytesPojo + { + public byte first; + public byte second; + public byte third; + + public TripleBytesPojo(byte first, byte second, byte third) + { + this.first = first; + this.second = second; + this.third = third; + } + + @Override + public boolean equals(Object o) + { + if (this == o) { + return true; + } + if (!(o instanceof TripleBytesPojo)) { + return false; + } + + TripleBytesPojo that = (TripleBytesPojo) o; + + if (first != that.first) { + return false; + } + if (second != that.second) { + return false; + } + return third == that.third; + } + + @Override + public int hashCode() + { + int result = first; + result = 31 * result + (int) second; + result = 31 * result + (int) third; + return result; + } + + @Override + public String toString() + { + return String.format("%d-%d-%d", first, second, third); + } + + static class Deserializer + extends StdDeserializer + { + protected Deserializer() + { + super(TripleBytesPojo.class); + } + + @Override + public TripleBytesPojo deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return TripleBytesPojo.deserialize(p.getBinaryValue()); + } + } + + static class KeyDeserializer + extends com.fasterxml.jackson.databind.KeyDeserializer + { + @Override + public Object deserializeKey(String key, DeserializationContext ctxt) + throws IOException + { + String[] values = key.split("-"); + return new TripleBytesPojo( + Byte.parseByte(values[0]), + Byte.parseByte(values[1]), + Byte.parseByte(values[2])); + } + } + + static byte[] serialize(TripleBytesPojo obj) + { + return new byte[] { obj.first, obj.second, obj.third }; + } + + static TripleBytesPojo deserialize(byte[] bytes) + { + return new TripleBytesPojo(bytes[0], bytes[1], bytes[2]); + } + } + + @Test + public void extensionTypeWithPojoInMap() + throws IOException + { + byte extTypeCode = 42; + + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addCustomDeser(extTypeCode, new ExtensionTypeCustomDeserializers.Deser() + { + @Override + public Object deserialize(byte[] value) + throws IOException + { + return TripleBytesPojo.deserialize(value); + } + }); + + SimpleModule module = new SimpleModule(); + module.addDeserializer(TripleBytesPojo.class, new TripleBytesPojo.Deserializer()); + module.addKeyDeserializer(TripleBytesPojo.class, new TripleBytesPojo.KeyDeserializer()); + ObjectMapper objectMapper = new ObjectMapper( + new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)) + .registerModule(module); + + // Prepare serialized data + Map originalMap = new HashMap<>(); + byte[] serializedData; + { + ValueFactory.MapBuilder mapBuilder = ValueFactory.newMapBuilder(); + for (int i = 0; i < 4; i++) { + TripleBytesPojo keyObj = new TripleBytesPojo((byte) i, (byte) (i + 1), (byte) (i + 2)); + TripleBytesPojo valueObj = new TripleBytesPojo((byte) (i * 2), (byte) (i * 3), (byte) (i * 4)); + ExtensionValue k = ValueFactory.newExtension(extTypeCode, TripleBytesPojo.serialize(keyObj)); + ExtensionValue v = ValueFactory.newExtension(extTypeCode, TripleBytesPojo.serialize(valueObj)); + mapBuilder.put(k, v); + originalMap.put(keyObj, valueObj); + } + ByteArrayOutputStream output = new ByteArrayOutputStream(); + MessagePacker packer = MessagePack.newDefaultPacker(output); + MapValue mapValue = mapBuilder.build(); + mapValue.writeTo(packer); + packer.close(); + + serializedData = output.toByteArray(); + } + + Map deserializedMap = objectMapper.readValue(serializedData, + new TypeReference>() {}); + + assertEquals(originalMap.size(), deserializedMap.size()); + for (Map.Entry entry : originalMap.entrySet()) { + assertEquals(entry.getValue(), deserializedMap.get(entry.getKey())); + } + } + @Test - public void extensionTypeInMap() + public void extensionTypeWithUuidInMap() throws IOException { - byte uuidTypeCode = 42; + byte extTypeCode = 42; ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); - extTypeCustomDesers.addCustomDeser(uuidTypeCode, new ExtensionTypeCustomDeserializers.Deser() + extTypeCustomDesers.addCustomDeser(extTypeCode, new ExtensionTypeCustomDeserializers.Deser() { @Override public Object deserialize(byte[] value) @@ -805,12 +952,12 @@ public Object deserialize(byte[] value) { ValueFactory.MapBuilder mapBuilder = ValueFactory.newMapBuilder(); for (int i = 0; i < 4; i++) { - UUID uuidKey = UUID.randomUUID(); - UUID uuidValue = UUID.randomUUID(); - ExtensionValue k = ValueFactory.newExtension(uuidTypeCode, uuidKey.toString().getBytes()); - ExtensionValue v = ValueFactory.newExtension(uuidTypeCode, uuidValue.toString().getBytes()); + UUID keyObj = UUID.randomUUID(); + UUID valueObj = UUID.randomUUID(); + ExtensionValue k = ValueFactory.newExtension(extTypeCode, keyObj.toString().getBytes()); + ExtensionValue v = ValueFactory.newExtension(extTypeCode, valueObj.toString().getBytes()); mapBuilder.put(k, v); - originalMap.put(uuidKey, uuidValue); + originalMap.put(keyObj, valueObj); } ByteArrayOutputStream output = new ByteArrayOutputStream(); MessagePacker packer = MessagePack.newDefaultPacker(output); From 651e220b377691a0d0c0b626340f859f26d34404 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Tue, 15 Dec 2020 22:55:31 +0900 Subject: [PATCH 149/417] Add comments --- .../org/msgpack/jackson/dataformat/MessagePackParserTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index fce4bb2f5..7b94af1f9 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -826,6 +826,7 @@ public int hashCode() @Override public String toString() { + // This key format is used when serialized as map key return String.format("%d-%d-%d", first, second, third); } @@ -943,6 +944,8 @@ public Object deserialize(byte[] value) } }); + // In this case with UUID, we don't need to add custom deserializers + // since jackson-databind already has it. ObjectMapper objectMapper = new ObjectMapper( new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); From 344ebd1995eef99727d06e42f705161f6bd29eac Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Tue, 15 Dec 2020 23:46:57 +0900 Subject: [PATCH 150/417] Describe how to use ext type in Map --- msgpack-jackson/README.md | 158 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 150 insertions(+), 8 deletions(-) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 00be68c67..8c2ac430e 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -207,16 +207,15 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial @JsonSerialize(keyUsing = MessagePackKeySerializer.class) private Map intMap = new HashMap<>(); - : - { - intMap.put(42, "Hello"); + : - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - byte[] bytes = objectMapper.writeValueAsBytes(intMap); + intMap.put(42, "Hello"); - Map deserialized = objectMapper.readValue(bytes, new TypeReference>() {}); - System.out.println(deserialized); // => {42=Hello} - } + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + byte[] bytes = objectMapper.writeValueAsBytes(intMap); + + Map deserialized = objectMapper.readValue(bytes, new TypeReference>() {}); + System.out.println(deserialized); // => {42=Hello} ``` ### Deserialize extension types with ExtensionTypeCustomDeserializers @@ -316,6 +315,149 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial // => Java ``` +#### Use extension type as Map key + +```java + static class TripleBytesPojo + { + public byte first; + public byte second; + public byte third; + + public TripleBytesPojo(byte first, byte second, byte third) + { + this.first = first; + this.second = second; + this.third = third; + } + + @Override + public boolean equals(Object o) + { + : + } + + @Override + public int hashCode() + { + : + } + + @Override + public String toString() + { + // This key format is used when serialized as map key + return String.format("%d-%d-%d", first, second, third); + } + + static class KeyDeserializer + extends com.fasterxml.jackson.databind.KeyDeserializer + { + @Override + public Object deserializeKey(String key, DeserializationContext ctxt) + throws IOException + { + String[] values = key.split("-"); + return new TripleBytesPojo(Byte.parseByte(values[0]), Byte.parseByte(values[1]), Byte.parseByte(values[2])); + } + } + + static TripleBytesPojo deserialize(byte[] bytes) + { + return new TripleBytesPojo(bytes[0], bytes[1], bytes[2]); + } + } + + : + + byte extTypeCode = 42; + + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addCustomDeser(extTypeCode, new ExtensionTypeCustomDeserializers.Deser() + { + @Override + public Object deserialize(byte[] value) + throws IOException + { + return TripleBytesPojo.deserialize(value); + } + }); + + SimpleModule module = new SimpleModule(); + module.addKeyDeserializer(TripleBytesPojo.class, new TripleBytesPojo.KeyDeserializer()); + ObjectMapper objectMapper = new ObjectMapper( + new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)) + .registerModule(module); + + Map deserializedMap = + objectMapper.readValue(serializedData, + new TypeReference>() {}); +``` + +#### Use extension type as Map value + +```java + static class TripleBytesPojo + { + public byte first; + public byte second; + public byte third; + + public TripleBytesPojo(byte first, byte second, byte third) + { + this.first = first; + this.second = second; + this.third = third; + } + + static class Deserializer + extends StdDeserializer + { + protected Deserializer() + { + super(TripleBytesPojo.class); + } + + @Override + public TripleBytesPojo deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return TripleBytesPojo.deserialize(p.getBinaryValue()); + } + } + + static TripleBytesPojo deserialize(byte[] bytes) + { + return new TripleBytesPojo(bytes[0], bytes[1], bytes[2]); + } + } + + : + + byte extTypeCode = 42; + + ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); + extTypeCustomDesers.addCustomDeser(extTypeCode, new ExtensionTypeCustomDeserializers.Deser() + { + @Override + public Object deserialize(byte[] value) + throws IOException + { + return TripleBytesPojo.deserialize(value); + } + }); + + SimpleModule module = new SimpleModule(); + module.addDeserializer(TripleBytesPojo.class, new TripleBytesPojo.Deserializer()); + ObjectMapper objectMapper = new ObjectMapper( + new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)) + .registerModule(module); + + Map deserializedMap = + objectMapper.readValue(serializedData, + new TypeReference>() {}); +``` + ### Serialize a nested object that also serializes When you serialize an object that has a nested object also serializing with ObjectMapper and MessagePackFactory like the following code, it throws NullPointerException since the nested MessagePackFactory modifies a shared state stored in ThreadLocal. From 4411cac2c7311f56d2a39f0d0bfe5b44ea229535 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 16 Dec 2020 16:53:25 +0900 Subject: [PATCH 151/417] Small improvement --- .../java/org/msgpack/jackson/dataformat/MessagePackParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 20c2ddc5f..758b3af15 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -398,7 +398,7 @@ public String getText() case BIG_INT: return String.valueOf(biValue); case EXT: - return new String(extensionTypeValue.getData()); + return getExtensionTypeValue().toString(); default: throw new IllegalStateException("Invalid type=" + type); } From 86b729d6aaa038eb83c847dd03a3d31298b14d6d Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 16 Dec 2020 20:37:46 +0900 Subject: [PATCH 152/417] Refactoring --- .../msgpack/jackson/dataformat/MessagePackParser.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 758b3af15..2dd15ca0b 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -342,7 +342,7 @@ public JsonToken nextToken() ExtensionTypeHeader header = messageUnpacker.unpackExtensionTypeHeader(); extensionTypeValue = new MessagePackExtensionType(header.getType(), messageUnpacker.readPayload(header.getLength())); if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(getExtensionTypeValue().toString()); + parsingContext.setCurrentName(deserializedExtensionTypeValue().toString()); nextToken = JsonToken.FIELD_NAME; } else { @@ -398,7 +398,7 @@ public String getText() case BIG_INT: return String.valueOf(biValue); case EXT: - return getExtensionTypeValue().toString(); + return deserializedExtensionTypeValue().toString(); default: throw new IllegalStateException("Invalid type=" + type); } @@ -573,7 +573,7 @@ public BigDecimal getDecimalValue() } } - private Object getExtensionTypeValue() + private Object deserializedExtensionTypeValue() throws IOException { if (extTypeCustomDesers != null) { @@ -582,7 +582,7 @@ private Object getExtensionTypeValue() return deser.deserialize(extensionTypeValue.getData()); } } - return extensionTypeValue; + throw new RuntimeException("Unsupported extension type=" + extensionTypeValue.getType()); } @Override @@ -593,7 +593,7 @@ public Object getEmbeddedObject() case BYTES: return bytesValue; case EXT: - return getExtensionTypeValue(); + return deserializedExtensionTypeValue(); default: throw new IllegalStateException("Invalid type=" + type); } From edd094282368d26fff7808ca792faa0ce488be61 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 16 Dec 2020 21:00:57 +0900 Subject: [PATCH 153/417] Keep compatible behavior --- .../java/org/msgpack/jackson/dataformat/MessagePackParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 2dd15ca0b..2a95b69a0 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -582,7 +582,7 @@ private Object deserializedExtensionTypeValue() return deser.deserialize(extensionTypeValue.getData()); } } - throw new RuntimeException("Unsupported extension type=" + extensionTypeValue.getType()); + return extensionTypeValue; } @Override From a3a84cd40b0e516982b6bb34e382f03f97aef0f5 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 16 Dec 2020 22:21:21 +0900 Subject: [PATCH 154/417] Remove 2 exttype deser APIs --- msgpack-jackson/README.md | 61 +------------------ .../ExtensionTypeCustomDeserializers.java | 33 +--------- .../dataformat/MessagePackFactoryTest.java | 14 ++++- .../dataformat/MessagePackParserTest.java | 49 ++------------- 4 files changed, 19 insertions(+), 138 deletions(-) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 8c2ac430e..38e2bf5b5 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -222,66 +222,7 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial `ExtensionTypeCustomDeserializers` helps you to deserialize extension types easily. -#### With target Java class - -```java - NestedListComplexPojo parent = new NestedListComplexPojo(); - parent.children = Arrays.asList(new TinyPojo("Foo"), new TinyPojo("Bar")); - - // In this application, extension type 17 is used for NestedListComplexPojo - byte[] bytes; - { - // This ObjectMapper is just for temporary serialization - ObjectMapper tempObjectMapper = new ObjectMapper(new MessagePackFactory()); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - MessagePacker packer = MessagePack.newDefaultPacker(outputStream); - - byte[] extBytes = tempObjectMapper.writeValueAsBytes(parent); - packer.packExtensionTypeHeader((byte) 17, extBytes.length); - packer.addPayload(extBytes); - packer.close(); - - bytes = outputStream.toByteArray(); - } - - // Register the type and the class to ExtensionTypeCustomDeserializers - ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); - extTypeCustomDesers.addTargetClass((byte) 17, NestedListComplexPojo.class); - ObjectMapper objectMapper = new ObjectMapper( - new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); - - System.out.println(objectMapper.readValue(bytes, Object.class)); - // => NestedListComplexPojo{children=[TinyPojo{name='Foo'}, TinyPojo{name='Bar'}]} -``` - -#### With type reference - -```java - Map map = new HashMap<>(); - map.put("one", 1); - map.put("two", 2); - - // In this application, extension type 31 is used for Map - byte[] bytes; - { - // Same as above - : - packer.packExtensionTypeHeader((byte) 31, extBytes.length); - : - } - - // Register the type and the type reference to ExtensionTypeCustomDeserializers - ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); - extTypeCustomDesers.addTargetTypeReference((byte) 31, - new TypeReference>() {}); - ObjectMapper objectMapper = new ObjectMapper( - new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); - - System.out.println(objectMapper.readValue(bytes, Object.class)); - // => {one=1, two=2} -``` - -#### With custom deserializer +#### Deserialize extension type value directly ```java // In this application, extension type 59 is used for byte[] diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java index ef86ebbb8..ae2e63537 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java @@ -15,21 +15,16 @@ // package org.msgpack.jackson.dataformat; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; - import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class ExtensionTypeCustomDeserializers { - private final ObjectMapper objectMapper; - private Map deserTable = new ConcurrentHashMap(); + private Map deserTable = new ConcurrentHashMap<>(); public ExtensionTypeCustomDeserializers() { - objectMapper = new ObjectMapper(new MessagePackFactory().setReuseResourceInParser(false)); } public ExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers src) @@ -38,32 +33,6 @@ public ExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers src) this.deserTable.putAll(src.deserTable); } - public void addTargetClass(byte type, final Class klass) - { - deserTable.put(type, new Deser() - { - @Override - public Object deserialize(byte[] data) - throws IOException - { - return objectMapper.readValue(data, klass); - } - }); - } - - public void addTargetTypeReference(byte type, final TypeReference typeReference) - { - deserTable.put(type, new Deser() - { - @Override - public Object deserialize(byte[] data) - throws IOException - { - return objectMapper.readValue(data, typeReference); - } - }); - } - public void addCustomDeser(byte type, final Deser deser) { deserTable.put(type, new Deser() diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java index c3379c3df..f8d7ac3c8 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java @@ -65,7 +65,19 @@ private void assertCopy(boolean advancedConfig) ObjectMapper objectMapper; if (advancedConfig) { ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); - extTypeCustomDesers.addTargetClass((byte) 42, TinyPojo.class); + extTypeCustomDesers.addCustomDeser((byte) 42, + new ExtensionTypeCustomDeserializers.Deser() + { + @Override + public Object deserialize(byte[] data) + throws IOException + { + TinyPojo pojo = new TinyPojo(); + pojo.t = new String(data); + return pojo; + } + } + ); MessagePack.PackerConfig msgpackPackerConfig = new MessagePack.PackerConfig().withStr8FormatSupport(false); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 7b94af1f9..976324e7c 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -704,34 +704,12 @@ public void extensionTypeCustomDeserializers() { ByteArrayOutputStream out = new ByteArrayOutputStream(); MessagePacker packer = MessagePack.newDefaultPacker(out); - packer.packArrayHeader(5); + packer.packArrayHeader(3); // 0: Integer packer.packInt(42); // 1: String packer.packString("foo bar"); - // 2: ExtensionType(class desr) - { - TinyPojo t0 = new TinyPojo(); - t0.t = "t0"; - TinyPojo t1 = new TinyPojo(); - t1.t = "t1"; - NestedListComplexPojo parent = new NestedListComplexPojo(); - parent.s = "parent"; - parent.foos = Arrays.asList(t0, t1); - byte[] bytes = objectMapper.writeValueAsBytes(parent); - packer.packExtensionTypeHeader((byte) 17, bytes.length); - packer.addPayload(bytes); - } - // 3: ExtensionType(type reference deser) - { - Map map = new HashMap(); - map.put("one", 1); - map.put("two", 2); - byte[] bytes = objectMapper.writeValueAsBytes(map); - packer.packExtensionTypeHeader((byte) 99, bytes.length); - packer.addPayload(bytes); - } - // 4: ExtensionType(custom deser) + // 2: ExtensionType { packer.packExtensionTypeHeader((byte) 31, 4); packer.addPayload(new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}); @@ -739,8 +717,6 @@ public void extensionTypeCustomDeserializers() packer.close(); ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers(); - extTypeCustomDesers.addTargetClass((byte) 17, NestedListComplexPojo.class); - extTypeCustomDesers.addTargetTypeReference((byte) 99, new TypeReference>() {}); extTypeCustomDesers.addCustomDeser((byte) 31, new ExtensionTypeCustomDeserializers.Deser() { @Override public Object deserialize(byte[] data) @@ -757,27 +733,10 @@ public Object deserialize(byte[] data) new ObjectMapper(new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); List values = objectMapper.readValue(new ByteArrayInputStream(out.toByteArray()), new TypeReference>() {}); - assertThat(values.size(), is(5)); + assertThat(values.size(), is(3)); assertThat((Integer) values.get(0), is(42)); assertThat((String) values.get(1), is("foo bar")); - { - Object v = values.get(2); - assertThat(v, is(instanceOf(NestedListComplexPojo.class))); - NestedListComplexPojo pojo = (NestedListComplexPojo) v; - assertThat(pojo.s, is("parent")); - assertThat(pojo.foos.size(), is(2)); - assertThat(pojo.foos.get(0).t, is("t0")); - assertThat(pojo.foos.get(1).t, is("t1")); - } - { - Object v = values.get(3); - assertThat(v, is(instanceOf(Map.class))); - Map map = (Map) v; - assertThat(map.size(), is(2)); - assertThat(map.get("one"), is(1)); - assertThat(map.get("two"), is(2)); - } - assertThat((String) values.get(4), is("Java")); + assertThat((String) values.get(2), is("Java")); } static class TripleBytesPojo From d3236bf4dc8c38b14d5505035a50571d1b886048 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 16 Dec 2020 22:36:57 +0900 Subject: [PATCH 155/417] Remove unused import --- .../org/msgpack/jackson/dataformat/MessagePackParserTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 976324e7c..a416c92bd 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -52,7 +52,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; From 0f5305ede92a5d7ff03aa033e0495f1431b14bb1 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 17 Dec 2020 20:16:26 +0900 Subject: [PATCH 156/417] Fix a bug that fails to serialize BigDecimal --- .../org/msgpack/jackson/dataformat/MessagePackGenerator.java | 3 ++- .../msgpack/jackson/dataformat/MessagePackGeneratorTest.java | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index 988817a30..96aa6a063 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -270,7 +270,8 @@ private void packBigDecimal(BigDecimal decimal) if (failedToPackAsBI) { double doubleValue = decimal.doubleValue(); //Check to make sure this BigDecimal can be represented as a double - if (!decimal.stripTrailingZeros().toEngineeringString().equals(BigDecimal.valueOf(doubleValue).toEngineeringString())) { + if (!decimal.stripTrailingZeros().toEngineeringString().equals( + BigDecimal.valueOf(doubleValue).stripTrailingZeros().toEngineeringString())) { throw new IllegalArgumentException("MessagePack cannot serialize a BigDecimal that can't be represented as double. " + decimal); } messagePacker.packDouble(doubleValue); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index 549f2f90a..e2c202bc3 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -304,10 +304,12 @@ public void testBigDecimal() double d0 = 1.23456789; double d1 = 1.23450000000000000000006789; String d2 = "12.30"; + String d3 = "0.00001"; List bigDecimals = Arrays.asList( BigDecimal.valueOf(d0), BigDecimal.valueOf(d1), new BigDecimal(d2), + new BigDecimal(d3), BigDecimal.valueOf(Double.MIN_VALUE), BigDecimal.valueOf(Double.MAX_VALUE), BigDecimal.valueOf(Double.MIN_NORMAL) @@ -320,6 +322,7 @@ public void testBigDecimal() assertEquals(d0, unpacker.unpackDouble(), 0.000000000000001); assertEquals(d1, unpacker.unpackDouble(), 0.000000000000001); assertEquals(Double.valueOf(d2), unpacker.unpackDouble(), 0.000000000000001); + assertEquals(Double.valueOf(d3), unpacker.unpackDouble(), 0.000000000000001); assertEquals(Double.MIN_VALUE, unpacker.unpackDouble(), 0.000000000000001); assertEquals(Double.MAX_VALUE, unpacker.unpackDouble(), 0.000000000000001); assertEquals(Double.MIN_NORMAL, unpacker.unpackDouble(), 0.000000000000001); From 31c04d2fb36e8a1a6ef6cf197a4d20ed1695eeb4 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 18 Dec 2020 21:07:03 +0900 Subject: [PATCH 157/417] Add some updates of 0.8.22 to RELEASE_NOTES --- RELEASE_NOTES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 519988d0a..564ac679c 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,10 @@ # Release Notes +## 0.8.22 + * Support extension type key in Map [#535](https://github.com/msgpack/msgpack-java/pull/535) + * Remove addTargetClass() and addTargetTypeReference() from ExtensionTypeCustomDeserializers [#539](https://github.com/msgpack/msgpack-java/pull/539) + * Fix a bug BigDecimal serializaion fails [#540](https://github.com/msgpack/msgpack-java/pull/540) + ## 0.8.21 * Fix indexing bug in ValueFactory [#525](https://github.com/msgpack/msgpack-java/pull/525) * Support numeric types in MessagePackParser.getText() [#527](https://github.com/msgpack/msgpack-java/pull/527) From b05625d38ade202207a7c5308501bd68a4ced3bf Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 18 Dec 2020 21:25:00 +0900 Subject: [PATCH 158/417] Setting version to 0.8.22 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index fbd50a0e5..c4ae2919b 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.22-SNAPSHOT" +version in ThisBuild := "0.8.22" From a7bcbecd74f692d1a9d366d77ceb4e1e9269c8df Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 18 Dec 2020 21:28:47 +0900 Subject: [PATCH 159/417] Setting version to 0.8.23-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index c4ae2919b..64351653c 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.22" +version in ThisBuild := "0.8.23-SNAPSHOT" From 4976b7f24a8efe3a7b48d5a42533f4462d686fca Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sun, 14 Feb 2021 23:54:19 -0800 Subject: [PATCH 160/417] #542: Add a warning note for the usage of MessageUnpacker.readPayloadAsReference (#546) --- .../src/main/java/org/msgpack/core/MessageUnpacker.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index cd0c44dec..6d0c4ced0 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -1616,6 +1616,9 @@ public void readPayload(byte[] dst, int off, int len) /** * Reads payload bytes of binary, extension, or raw string types as a reference to internal buffer. * + * Note: This methods may return raw memory region, access to which has no strict boundary checks. + * To use this method safely, you need to understand the internal buffer handling of msgpack-java. + * *

      * This consumes specified amount of bytes and returns its reference or copy. This method tries to * return reference as much as possible because it is faster. However, it may copy data to a newly From f67b6e5431b2e0ba8f6ae975a3af4b1af298fee6 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 16 Feb 2021 09:00:53 -0800 Subject: [PATCH 161/417] Fixes #544: Fix a bug in reading EXT32 with 2GB size (#545) * Fixes #544: Fix a bug in reading EXT32 with 2GB size * Add comment --- .../org/msgpack/core/MessageUnpacker.java | 8 ++++++- .../msgpack/core/InvalidDataReadTest.scala | 23 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 6d0c4ced0..0d4631527 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -553,7 +553,10 @@ public void skipValue(int count) skipPayload(readNextLength16() + 1); break; case EXT32: - skipPayload(readNextLength32() + 1); + int extLen = readNextLength32(); + // Skip the first ext type header (1-byte) first in case ext length is Integer.MAX_VALUE + skipPayload(1); + skipPayload(extLen); break; case ARRAY16: count += readNextLength16(); @@ -1474,6 +1477,9 @@ public int unpackBinaryHeader() private void skipPayload(int numBytes) throws IOException { + if (numBytes < 0) { + throw new IllegalArgumentException("payload size must be >= 0: " + numBytes); + } while (true) { int bufferRemaining = buffer.size() - position; if (bufferRemaining >= numBytes) { diff --git a/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala new file mode 100644 index 000000000..4950da82a --- /dev/null +++ b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala @@ -0,0 +1,23 @@ +package org.msgpack.core + +/** + * + */ +class InvalidDataReadTest extends MessagePackSpec { + + "Reading long EXT32" in { + // Prepare an EXT32 data with 2GB (Int.MaxValue size) payload for testing the behavior of MessageUnpacker.skipValue() + // Actually preparing 2GB of data, however, is too much for CI, so we create only the header part. + val msgpack = createMessagePackData(p => p.packExtensionTypeHeader(MessagePack.Code.EXT32, Int.MaxValue)) + val u = MessagePack.newDefaultUnpacker(msgpack) + try { + // This error will be thrown after reading the header as the input has no EXT32 body + intercept[MessageInsufficientBufferException] { + u.skipValue() + } + } + finally { + u.close() + } + } +} From 7f4a388307c8bcd8fb32a769544f5df33ba87fba Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 10:18:17 -0700 Subject: [PATCH 162/417] Remove Travis build (#550) --- .travis.yml | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f198f64fb..000000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: scala - -arch: arm64 -os: linux - -cache: - directories: - - $HOME/.m2/repository/ - - $HOME/.ivy2/cache/ - - $HOME/.sbt/boot/ - - $HOME/.coursier - -branches: - only: - - develop - -matrix: - include: - - env: PROJECT=java11 - jdk: openjdk11 - script: - - ./sbt test - - ./sbt test -J-Dmsgpack.universal-buffer=true From 75d33d10e547b15ee0705686815476840601253f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Peignier?= Date: Tue, 11 May 2021 10:24:20 -0700 Subject: [PATCH 163/417] Prevent having two different unpacking methods (#548) * Prevent having two different unpacking methods * Fix loop --- .../org/msgpack/core/MessageUnpacker.java | 23 +++-- .../main/java/org/msgpack/value/Variable.java | 88 +++++++++++-------- 2 files changed, 59 insertions(+), 52 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 0d4631527..6d0d57ab3 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -32,10 +32,6 @@ import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import static org.msgpack.core.Preconditions.checkNotNull; @@ -690,22 +686,23 @@ public Variable unpackValue(Variable var) } case ARRAY: { int size = unpackArrayHeader(); - List list = new ArrayList(size); + Value[] kvs = new Value[size]; for (int i = 0; i < size; i++) { - list.add(unpackValue()); + kvs[i] = unpackValue(); } - var.setArrayValue(list); + var.setArrayValue(kvs); return var; } case MAP: { int size = unpackMapHeader(); - Map map = new HashMap(); - for (int i = 0; i < size; i++) { - Value k = unpackValue(); - Value v = unpackValue(); - map.put(k, v); + Value[] kvs = new Value[size * 2]; + for (int i = 0; i < size * 2; ) { + kvs[i] = unpackValue(); + i++; + kvs[i] = unpackValue(); + i++; } - var.setMapValue(map); + var.setMapValue(kvs); return var; } case EXTENSION: { diff --git a/msgpack-core/src/main/java/org/msgpack/value/Variable.java b/msgpack-core/src/main/java/org/msgpack/value/Variable.java index 59e6930cb..28295fe1c 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/Variable.java +++ b/msgpack-core/src/main/java/org/msgpack/value/Variable.java @@ -30,6 +30,7 @@ import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -798,6 +799,14 @@ public void writeTo(MessagePacker pk) // public Variable setArrayValue(List v) + { + this.type = Type.LIST; + this.accessor = arrayAccessor; + this.objectValue = v.toArray(); + return this; + } + + public Variable setArrayValue(Value[] v) { this.type = Type.LIST; this.accessor = arrayAccessor; @@ -824,29 +833,29 @@ public ArrayValue asArrayValue() @Override public ImmutableArrayValue immutableValue() { - return ValueFactory.newArray(list()); + return ValueFactory.newArray(array()); } @Override public int size() { - return list().size(); + return array().length; } @Override public Value get(int index) { - return list().get(index); + return array()[index]; } @Override public Value getOrNilValue(int index) { - List l = list(); - if (l.size() < index && index >= 0) { + Value[] a = array(); + if (a.length < index && index >= 0) { return ValueFactory.newNil(); } - return l.get(index); + return a[index]; } @Override @@ -856,21 +865,21 @@ public Iterator iterator() } @Override - @SuppressWarnings("unchecked") public List list() { - return (List) objectValue; + return Arrays.asList(array()); + } + + public Value[] array() + { + return (Value[]) objectValue; } @Override public void writeTo(MessagePacker pk) throws IOException { - List l = list(); - pk.packArrayHeader(l.size()); - for (Value e : l) { - e.writeTo(pk); - } + immutableValue().writeTo(pk); } } @@ -882,7 +891,25 @@ public Variable setMapValue(Map v) { this.type = Type.MAP; this.accessor = mapAccessor; - this.objectValue = v; + Value[] kvs = new Value[v.size() * 2]; + Iterator> ite = v.entrySet().iterator(); + int i = 0; + while (ite.hasNext()) { + Map.Entry pair = ite.next(); + kvs[i] = pair.getKey(); + i++; + kvs[i] = pair.getValue(); + i++; + } + this.objectValue = kvs; + return this; + } + + public Variable setMapValue(Value[] kvs) + { + this.type = Type.MAP; + this.accessor = mapAccessor; + this.objectValue = kvs; return this; } @@ -905,66 +932,49 @@ public MapValue asMapValue() @Override public ImmutableMapValue immutableValue() { - return ValueFactory.newMap(map()); + return ValueFactory.newMap(getKeyValueArray()); } @Override public int size() { - return map().size(); + return getKeyValueArray().length / 2; } @Override public Set keySet() { - return map().keySet(); + return immutableValue().keySet(); } @Override public Set> entrySet() { - return map().entrySet(); + return immutableValue().entrySet(); } @Override public Collection values() { - return map().values(); + return immutableValue().values(); } @Override public Value[] getKeyValueArray() { - Map v = map(); - Value[] kvs = new Value[v.size() * 2]; - Iterator> ite = v.entrySet().iterator(); - int i = 0; - while (ite.hasNext()) { - Map.Entry pair = ite.next(); - kvs[i] = pair.getKey(); - i++; - kvs[i] = pair.getValue(); - i++; - } - return kvs; + return (Value[]) objectValue; } - @SuppressWarnings("unchecked") public Map map() { - return (Map) objectValue; + return immutableValue().map(); } @Override public void writeTo(MessagePacker pk) throws IOException { - Map m = map(); - pk.packArrayHeader(m.size()); - for (Map.Entry pair : m.entrySet()) { - pair.getKey().writeTo(pk); - pair.getValue().writeTo(pk); - } + immutableValue().writeTo(pk); } } From 2cb3f6d4d7fa1c00e14c362311a301ea80cadf10 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 10:35:51 -0700 Subject: [PATCH 164/417] Run GitHub actions for develop and main branches (#551) --- .github/workflows/CI.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index fde9f4608..f289bc708 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -10,6 +10,8 @@ on: push: branches: - master + - develop + - main paths: - '**.scala' - '**.java' From ed544b594a4e08b0c0d0eb5fa00a3e4aaffce3d4 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 11:06:37 -0700 Subject: [PATCH 165/417] Update build settings to use latest version of sbt and plugins (#552) --- .gitignore | 1 + README.md | 4 ++-- build.sbt | 36 +++++++++++++++++------------------- project/build.properties | 2 +- project/plugins.sbt | 19 ++++++++++--------- sbt | 21 ++++++++++++++------- version.sbt | 2 +- 7 files changed, 46 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index b85c5a96a..7ea10b4bd 100755 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ lib .idea atlassian-ide-plugin.xml .idea/copyright/msgpack.xml +.bsp \ No newline at end of file diff --git a/README.md b/README.md index c1dbc2461..dffb2bc09 100644 --- a/README.md +++ b/README.md @@ -88,9 +88,9 @@ Here is a list of sbt commands for daily development: > release # Run the release procedure (set a new version, run tests, upload artifacts, then deploy to Sonatype) -# If you need to perform the individual release steps manually, use the following commands: +# [optional] When you need to perform the individual release steps manually, use the following commands: > publishSigned # Publish GPG signed artifacts to the Sonatype repository -> sonatypeRelease # Publish to the Maven Central (It will be synched within less than 4 hours) +> sonatypeBundleRelease # Publish to the Maven Central (It will be synched within less than 4 hours) ``` For publishing to Maven central, msgpack-java uses [sbt-sonatype](https://github.com/xerial/sbt-sonatype) plugin. Set Sonatype account information (user name and password) in the global sbt settings. To protect your password, never include this file in your project. diff --git a/build.sbt b/build.sbt index 35c2558ef..609cb1a3d 100644 --- a/build.sbt +++ b/build.sbt @@ -1,26 +1,29 @@ import ReleaseTransformations._ +Global / onChangedBuildSource := ReloadOnSourceChanges + +// For performance testing, ensure each test run one-by-one +Global / concurrentRestrictions := Seq( + Tags.limit(Tags.Test, 1) +) + val buildSettings = Seq[Setting[_]]( organization := "org.msgpack", organizationName := "MessagePack", organizationHomepage := Some(new URL("http://msgpack.org/")), description := "MessagePack for Java", - scalaVersion := "2.12.8", - logBuffered in Test := false, + scalaVersion := "2.12.13", + Test / logBuffered := false, // msgpack-java should be a pure-java library, so remove Scala specific configurations autoScalaLibrary := false, crossPaths := false, - // For performance testing, ensure each test run one-by-one - concurrentRestrictions in Global := Seq( - Tags.limit(Tags.Test, 1) - ), // JVM options for building scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-feature"), - javaOptions in Test ++= Seq("-ea"), + Test / javaOptions ++= Seq("-ea"), javacOptions ++= Seq("-source", "1.7", "-target", "1.7"), - javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation"), + Compile / compile / javacOptions ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation"), // Use lenient validation mode when generating Javadoc (for Java8) - javacOptions in doc := { + doc / javacOptions := { val opts = Seq("-source", "1.7") if (scala.util.Properties.isJavaAtLeast("1.8")) { opts ++ Seq("-Xdoclint:none") @@ -29,7 +32,7 @@ val buildSettings = Seq[Setting[_]]( } }, // Release settings - releaseTagName := { (version in ThisBuild).value }, + releaseTagName := { (ThisBuild / version).value }, releaseProcess := Seq[ReleaseStep]( checkSnapshotDependencies, inquireVersions, @@ -39,26 +42,21 @@ val buildSettings = Seq[Setting[_]]( commitReleaseVersion, tagRelease, releaseStepCommand("publishSigned"), + releaseStepCommand("sonatypeBundleRelease"), setNextVersion, commitNextVersion, - releaseStepCommand("sonatypeReleaseAll"), pushChanges ), // Add sonatype repository settings - publishTo := Some( - if (isSnapshot.value) - Opts.resolver.sonatypeSnapshots - else - Opts.resolver.sonatypeStaging - ), + publishTo := sonatypePublishToBundle.value, // Find bugs findbugsReportType := Some(FindbugsReport.FancyHtml), findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html"), // Style check config: (sbt-jchekcstyle) jcheckStyleConfig := "facebook", // Run jcheckstyle both for main and test codes - (compile in Compile) := ((compile in Compile) dependsOn (jcheckStyle in Compile)).value, - (compile in Test) := ((compile in Test) dependsOn (jcheckStyle in Test)).value + Compile / compile := ((Compile / compile) dependsOn (Compile / jcheckStyle)).value, + Test / compile := ((Test / compile) dependsOn (Test / jcheckStyle)).value ) val junitInterface = "com.novocode" % "junit-interface" % "0.11" % "test" diff --git a/project/build.properties b/project/build.properties index e2820dd8c..182d2a9b8 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.2.8 +sbt.version=1.5.2 diff --git a/project/plugins.sbt b/project/plugins.sbt index 647c13328..9e68f5fe3 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,11 +1,12 @@ -addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.11") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.5") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.2") -addSbtPlugin("com.github.sbt" % "sbt-findbugs" % "2.0.0") -addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.0.3") -addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.5") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.3") -addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.5.1") +addSbtPlugin("com.github.sbt" % "sbt-release" % "1.0.15") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") +addSbtPlugin("com.github.sbt" % "sbt-findbugs" % "2.0.0") +// TODO: Fixes jacoco error: +// java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter +//addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") +addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") +addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.5") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") scalacOptions ++= Seq("-deprecation", "-feature") diff --git a/sbt b/sbt index 11a73fbcf..1aac2d3f6 100755 --- a/sbt +++ b/sbt @@ -34,11 +34,11 @@ set -o pipefail -declare -r sbt_release_version="1.3.13" -declare -r sbt_unreleased_version="1.4.0-M1" +declare -r sbt_release_version="1.5.1" +declare -r sbt_unreleased_version="1.5.1" -declare -r latest_213="2.13.3" -declare -r latest_212="2.12.12" +declare -r latest_213="2.13.5" +declare -r latest_212="2.12.13" declare -r latest_211="2.11.12" declare -r latest_210="2.10.7" declare -r latest_29="2.9.3" @@ -48,7 +48,7 @@ declare -r buildProps="project/build.properties" declare -r sbt_launch_ivy_release_repo="https://repo.typesafe.com/typesafe/ivy-releases" declare -r sbt_launch_ivy_snapshot_repo="https://repo.scala-sbt.org/scalasbt/ivy-snapshots" -declare -r sbt_launch_mvn_release_repo="https://repo.scala-sbt.org/scalasbt/maven-releases" +declare -r sbt_launch_mvn_release_repo="https://repo1.maven.org/maven2" declare -r sbt_launch_mvn_snapshot_repo="https://repo.scala-sbt.org/scalasbt/maven-snapshots" declare -r default_jvm_opts_common="-Xms512m -Xss2m -XX:MaxInlineLevel=18" @@ -247,11 +247,18 @@ java_version() { echo "$version" } +is_apple_silicon() { [[ "$(uname -s)" == "Darwin" && "$(uname -m)" == "arm64" ]]; } + # MaxPermSize critical on pre-8 JVMs but incurs noisy warning on 8+ default_jvm_opts() { local -r v="$(java_version)" if [[ $v -ge 10 ]]; then - echo "$default_jvm_opts_common -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler" + if is_apple_silicon; then + # As of Dec 2020, JVM for Apple Silicon (M1) doesn't support JVMCI + echo "$default_jvm_opts_common" + else + echo "$default_jvm_opts_common -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler" + fi elif [[ $v -ge 8 ]]; then echo "$default_jvm_opts_common" else @@ -471,7 +478,7 @@ process_args() { -trace) require_arg integer "$1" "$2" && trace_level="$2" && shift 2 ;; -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; - -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; + -no-colors) addJava "-Dsbt.log.noformat=true" && addJava "-Dsbt.color=false" && shift ;; -sbt-create) sbt_create=true && shift ;; -sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;; -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; diff --git a/version.sbt b/version.sbt index 64351653c..4cd3886e6 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.23-SNAPSHOT" +ThisBuild / version := "0.8.23-SNAPSHOT" From e96b85c43cb270be033a7f9f27be3a2582064928 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 11:28:04 -0700 Subject: [PATCH 166/417] Remove findbugs (#553) * Remove findbugs * Remove findbug settings --- build.sbt | 8 +------- project/plugins.sbt | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/build.sbt b/build.sbt index 609cb1a3d..7ec3c0284 100644 --- a/build.sbt +++ b/build.sbt @@ -49,9 +49,6 @@ val buildSettings = Seq[Setting[_]]( ), // Add sonatype repository settings publishTo := sonatypePublishToBundle.value, - // Find bugs - findbugsReportType := Some(FindbugsReport.FancyHtml), - findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html"), // Style check config: (sbt-jchekcstyle) jcheckStyleConfig := "facebook", // Run jcheckstyle both for main and test codes @@ -68,10 +65,7 @@ lazy val root = Project(id = "msgpack-java", base = file(".")) // Do not publish the root project publishArtifact := false, publish := {}, - publishLocal := {}, - findbugs := { - // do not run findbugs for the root project - } + publishLocal := {} ) .aggregate(msgpackCore, msgpackJackson) diff --git a/project/plugins.sbt b/project/plugins.sbt index 9e68f5fe3..5b367eb18 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,7 +1,6 @@ addSbtPlugin("com.github.sbt" % "sbt-release" % "1.0.15") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") -addSbtPlugin("com.github.sbt" % "sbt-findbugs" % "2.0.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") From 84b3abdc29b4561e71e5e3409361b5d0c2c875b7 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 11:49:03 -0700 Subject: [PATCH 167/417] Update ScalaTest and ScalaCheck versions (#554) --- build.sbt | 4 ++-- .../org/msgpack/core/MessagePackSpec.scala | 7 ++++--- .../org/msgpack/core/MessagePackTest.scala | 18 +++++++++--------- .../org/msgpack/value/ValueFactoryTest.scala | 4 +++- .../scala/org/msgpack/value/ValueTest.scala | 7 +++++-- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/build.sbt b/build.sbt index 7ec3c0284..78257bff5 100644 --- a/build.sbt +++ b/build.sbt @@ -86,8 +86,8 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) libraryDependencies ++= Seq( // msgpack-core should have no external dependencies junitInterface, - "org.scalatest" %% "scalatest" % "3.0.8" % "test", - "org.scalacheck" %% "scalacheck" % "1.14.0" % "test", + "org.scalatest" %% "scalatest" % "3.2.7" % "test", + "org.scalacheck" %% "scalacheck" % "1.15.4" % "test", "org.xerial" %% "xerial-core" % "3.6.0" % "test", "org.msgpack" % "msgpack" % "0.6.12" % "test", "commons-codec" % "commons-codec" % "1.12" % "test", diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala index 468468c17..ae1f5ae45 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala @@ -16,15 +16,16 @@ package org.msgpack.core import java.io.ByteArrayOutputStream - import org.scalatest._ -import org.scalatest.prop.PropertyChecks +import org.scalatest.matchers.should.Matchers +import org.scalatest.prop.TableDrivenPropertyChecks +import org.scalatest.wordspec.AnyWordSpec import xerial.core.log.{LogLevel, Logger} import xerial.core.util.{TimeReport, Timer} import scala.language.implicitConversions -trait MessagePackSpec extends WordSpec with Matchers with GivenWhenThen with OptionValues with BeforeAndAfter with PropertyChecks with Benchmark with Logger { +trait MessagePackSpec extends AnyWordSpec with Matchers with GivenWhenThen with OptionValues with BeforeAndAfter with Benchmark with Logger { implicit def toTag(s: String): Tag = Tag(s) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 2d2f1d1f6..d2a209bb0 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -19,10 +19,11 @@ import java.io.ByteArrayOutputStream import java.math.BigInteger import java.nio.CharBuffer import java.nio.charset.{CodingErrorAction, UnmappableCharacterException} - import org.msgpack.core.MessagePack.Code -import org.msgpack.core.MessagePack.{UnpackerConfig, PackerConfig} +import org.msgpack.core.MessagePack.{PackerConfig, UnpackerConfig} import org.msgpack.value.{Value, Variable} +import org.scalacheck.Arbitrary +import org.scalacheck.Prop.{forAll, propBoolean} import scala.util.Random @@ -176,7 +177,7 @@ class MessagePackTest extends MessagePackSpec { unpack: MessageUnpacker => A, packerConfig: PackerConfig = new PackerConfig(), unpackerConfig: UnpackerConfig = new UnpackerConfig() - ): Unit = { + ): Boolean = { var b: Array[Byte] = null try { val bs = new ByteArrayOutputStream() @@ -189,6 +190,7 @@ class MessagePackTest extends MessagePackSpec { val unpacker = unpackerConfig.newUnpacker(b) val ret = unpack(unpacker) ret shouldBe v + true } catch { case e: Exception => warn(e.getMessage) @@ -357,11 +359,9 @@ class MessagePackTest extends MessagePackSpec { } "pack/unpack strings" taggedAs ("string") in { - - forAll { (v: String) => - whenever(isValidUTF8(v)) { - check(v, _.packString(v), _.unpackString) - } + val utf8Strings = Arbitrary.arbitrary[String].suchThat(isValidUTF8 _) + utf8Strings.map { v => + check(v, _.packString(v), _.unpackString) } } @@ -532,7 +532,7 @@ class MessagePackTest extends MessagePackSpec { "pack/unpack extension types" taggedAs ("ext") in { forAll { (dataLen: Int, tpe: Byte) => val l = Math.abs(dataLen) - whenever(l >= 0) { + l >= 0 ==> { val ext = new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(tpe), l) check(ext, _.packExtensionTypeHeader(ext.getType, ext.getLength), _.unpackExtensionTypeHeader()) diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala index 8b11e0ca0..c9bc8f8f0 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala @@ -16,6 +16,7 @@ package org.msgpack.value import org.msgpack.core.MessagePackSpec +import org.scalacheck.Prop.forAll /** * @@ -34,7 +35,7 @@ class ValueFactoryTest extends MessagePackSpec { isMap: Boolean = false, isExtension: Boolean = false, isRaw: Boolean = false, - isNumber: Boolean = false) { + isNumber: Boolean = false): Boolean = { v.isNilValue shouldBe isNil v.isBooleanValue shouldBe isBoolean v.isIntegerValue shouldBe isInteger @@ -46,6 +47,7 @@ class ValueFactoryTest extends MessagePackSpec { v.isExtensionValue shouldBe isExtension v.isRawValue shouldBe isRaw v.isNumberValue shouldBe isNumber + true } "ValueFactory" should { diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala index 0e1fb8c40..eeb663bc6 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala @@ -17,11 +17,12 @@ package org.msgpack.value import java.math.BigInteger import org.msgpack.core._ +import org.scalacheck.Prop.{forAll, propBoolean} import scala.util.parsing.json.JSON class ValueTest extends MessagePackSpec { - def checkSuccinctType(pack: MessagePacker => Unit, expectedAtMost: MessageFormat) { + def checkSuccinctType(pack: MessagePacker => Unit, expectedAtMost: MessageFormat): Boolean = { val b = createMessagePackData(pack) val v1 = MessagePack.newDefaultUnpacker(b).unpackValue() val mf = v1.asIntegerValue().mostSuccinctMessageFormat() @@ -33,6 +34,8 @@ class ValueTest extends MessagePackSpec { val mf2 = v2.asIntegerValue().mostSuccinctMessageFormat() mf2.getValueType shouldBe ValueType.INTEGER mf2.ordinal() shouldBe <=(expectedAtMost.ordinal()) + + true } "Value" should { @@ -53,7 +56,7 @@ class ValueTest extends MessagePackSpec { checkSuccinctType(_.packBigInteger(BigInteger.valueOf(v)), MessageFormat.INT64) } forAll { (v: Long) => - whenever(v > 0) { + v > 0 ==> { // Create value between 2^63-1 < v <= 2^64-1 checkSuccinctType(_.packBigInteger(BigInteger.valueOf(Long.MaxValue).add(BigInteger.valueOf(v))), MessageFormat.UINT64) } From 8faab5655ccbd380e2e66d00ab053c5e9ea65054 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 14:09:03 -0700 Subject: [PATCH 168/417] Use dynamic versioning with Git tags v0.x.y format (#555) --- build.sbt | 12 +++++------- project/plugins.sbt | 7 ++++--- version.sbt | 1 - 3 files changed, 9 insertions(+), 11 deletions(-) delete mode 100644 version.sbt diff --git a/build.sbt b/build.sbt index 78257bff5..0d0cdba67 100644 --- a/build.sbt +++ b/build.sbt @@ -7,6 +7,11 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) +// Use dynamic snapshot version strings for non tagged versions +ThisBuild / dynverSonatypeSnapshots := true +// Use coursier friendly version separator +ThisBuild / dynverSeparator := "-" + val buildSettings = Seq[Setting[_]]( organization := "org.msgpack", organizationName := "MessagePack", @@ -32,19 +37,12 @@ val buildSettings = Seq[Setting[_]]( } }, // Release settings - releaseTagName := { (ThisBuild / version).value }, releaseProcess := Seq[ReleaseStep]( checkSnapshotDependencies, inquireVersions, runClean, runTest, - setReleaseVersion, - commitReleaseVersion, tagRelease, - releaseStepCommand("publishSigned"), - releaseStepCommand("sonatypeBundleRelease"), - setNextVersion, - commitNextVersion, pushChanges ), // Add sonatype repository settings diff --git a/project/plugins.sbt b/project/plugins.sbt index 5b367eb18..043c1f730 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,11 +1,12 @@ -addSbtPlugin("com.github.sbt" % "sbt-release" % "1.0.15") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") +addSbtPlugin("com.github.sbt" % "sbt-release" % "1.0.15") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.5") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") +addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") scalacOptions ++= Seq("-deprecation", "-feature") diff --git a/version.sbt b/version.sbt deleted file mode 100644 index 4cd3886e6..000000000 --- a/version.sbt +++ /dev/null @@ -1 +0,0 @@ -ThisBuild / version := "0.8.23-SNAPSHOT" From 3539d9752a2a7e481cef9688af025bbba6b9c806 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 14:12:09 -0700 Subject: [PATCH 169/417] Publish a snapshot version for every main branch commit (#556) --- .github/workflows/snapshot.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/snapshot.yml diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 000000000..1fde65f15 --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,32 @@ +name: Snapshot Release + +on: + push: + branches: + - develop + - main + paths: + - '**.scala' + - '**.java' + - '**.sbt' + tag: + - '!v*' + +jobs: + publish_snapshots: + name: Publish snapshots + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 10000 + # Fetch all tags so that sbt-dynver can find the previous release version + - run: git fetch --tags + - uses: olafurpg/setup-scala@v10 + with: + java-version: adopt@1.11 + - name: Publish snapshots + env: + SONATYPE_USERNAME: '${{ secrets.SONATYPE_USER }}' + SONATYPE_PASSWORD: '${{ secrets.SONATYPE_PASS }}' + run: ./sbt publish From 7c3b6e5b2de010276143e8fc98c008abd86361b7 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 14:43:43 -0700 Subject: [PATCH 170/417] Add a script for releasing a new version of msgpack-java at CI --- .github/workflows/release.yml | 36 ++++++++++++++++++++ README.md | 4 ++- build.sbt | 1 + sonatype.sbt | 62 ++++++++++------------------------- 4 files changed, 57 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..487c521ab --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,36 @@ +name: Release to Sonatype + +on: + push: + tags: + - v* + workflow_dispatch: + +jobs: + publish: + name: Release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 10000 + # Fetch all tags so that sbt-dynver can find the previous release version + - run: git fetch --tags -f + # Install OpenJDK 11 + - uses: olafurpg/setup-scala@v10 + with: + java-version: adopt@1.11 + - name: Setup GPG + env: + PGP_SECRET: ${{ secrets.PGP_SECRET }} + run: echo $PGP_SECRET | base64 --decode | gpg --import --batch --yes + - name: Build bundle + env: + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + run: | + ./sbt publish + - name: Release to Sonatype + env: + SONATYPE_USERNAME: '${{ secrets.SONATYPE_USER }}' + SONATYPE_PASSWORD: '${{ secrets.SONATYPE_PASS }}' + run: ./sbt sonatypeBundleRelease diff --git a/README.md b/README.md index dffb2bc09..7b41f0c83 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,9 @@ Here is a list of sbt commands for daily development: > sonatypeBundleRelease # Publish to the Maven Central (It will be synched within less than 4 hours) ``` -For publishing to Maven central, msgpack-java uses [sbt-sonatype](https://github.com/xerial/sbt-sonatype) plugin. Set Sonatype account information (user name and password) in the global sbt settings. To protect your password, never include this file in your project. +Once you run a release command, a new git tag v(version number) will be pushed to GitHub. GitHub Action will deploy a new release version to Maven Central (Sonatype). + +For publishing to Maven central using a local machine, msgpack-java uses [sbt-sonatype](https://github.com/xerial/sbt-sonatype) plugin. Set Sonatype account information (user name and password) in the global sbt settings. To protect your password, never include this file in your project. ___$HOME/.sbt/(sbt-version)/sonatype.sbt___ diff --git a/build.sbt b/build.sbt index 0d0cdba67..86abaf76e 100644 --- a/build.sbt +++ b/build.sbt @@ -22,6 +22,7 @@ val buildSettings = Seq[Setting[_]]( // msgpack-java should be a pure-java library, so remove Scala specific configurations autoScalaLibrary := false, crossPaths := false, + publishMavenStyle := true, // JVM options for building scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-feature"), Test / javaOptions ++= Seq("-ea"), diff --git a/sonatype.sbt b/sonatype.sbt index b94a33d4c..f016335a0 100644 --- a/sonatype.sbt +++ b/sonatype.sbt @@ -1,46 +1,18 @@ -sonatypeProfileName := "org.msgpack" +import xerial.sbt.Sonatype._ -pomExtra in Global := { - http://msgpack.org/ - - - Apache 2 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - scm:git:github.com/msgpack/msgpack-java.git - scm:git:git@github.com:msgpack/msgpack-java.git - github.com/msgpack/msgpack-java.git - - - UTF-8 - - - - frsyuki - Sadayuki Furuhashi - frsyuki@users.sourceforge.jp - - - muga - Muga Nishizawa - muga.nishizawa@gmail.com - - - oza - Tsuyoshi Ozawa - https://github.com/oza - - - komamitsu - Mitsunori Komatsu - komamitsu@gmail.com - - - xerial - Taro L. Saito - leo@xerial.org - - -} +ThisBuild / sonatypeProfileName := "org.msgpack" +ThisBuild / homepage := Some(url("https://msgpack.org/")) +ThisBuild / licenses := Seq("APL2" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")) +ThisBuild / scmInfo := Some( + ScmInfo( + url("https://github.com/msgpack/msgpack-java"), + "scm:git@github.com:msgpack/msgpack-java.git" + ) +) +ThisBuild / developers := List( + Developer(id = "frsyuki", name = "Sadayuki Furuhashi", email = "frsyuki@users.sourceforge.jp", url = url("https://github.com/frsyuki")), + Developer(id = "muga", name = "Muga Nishizawa", email = "muga.nishizawa@gmail.com", url = url("https://github.com/muga")), + Developer(id = "oza", name = "Tsuyoshi Ozawa", email = "ozawa.tsuyoshi@gmail.com", url = url("https://github.com/oza")), + Developer(id = "komamitsu", name = "Mitsunori Komatsu", email = "komamitsu@gmail.com", url = url("https://github.com/komamitsu")), + Developer(id = "xerial", name = "Taro L. Saito", email = "leo@xerial.org", url = url("https://github.com/xerial")) +) From d241c369592fc64d6eef40dd70010af2882ef3d4 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 15:01:27 -0700 Subject: [PATCH 171/417] Add 0.8.23 release notes --- RELEASE_NOTES.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 564ac679c..70dc7f220 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,21 @@ # Release Notes +## 0.8.23 + +* Produce stable map values [#548](https://github.com/msgpack/msgpac-java/pull/#548) +* Fixes #544: Fix a bug in reading EXT32 of 2GB size [#545](https://github.com/msgpack/msgpac-java/pull/545) +* Add a warning note for the usage of MessageUnpacker.readPayloadAsReference [#546](https://github.com/msgpack/msgpac-java/pull/546) + +Intenral changes: +* Add a script for releasing a new version of msgpack-java at CI +* Publish a snapshot version for every main branch commit [#556](https://github.com/msgpack/msgpac-java/pull/556) +* Use dynamic versioning with Git tags v0.x.y format [#555](https://github.com/msgpack/msgpac-java/pull/555) +* Update ScalaTest and ScalaCheck versions [#554](https://github.com/msgpack/msgpac-java/pull/554) +* Remove findbugs [#553](https://github.com/msgpack/msgpac-java/pull/553) +* Update build settings to use latest version of sbt and plugins [#552](https://github.com/msgpack/msgpac-java/pull/552) +* Run GitHub Actions for develop and main branches [#551](https://github.com/msgpack/msgpac-java/pull/551) +* Remove Travis build [#550](https://github.com/msgpack/msgpac-java/pull/550) + ## 0.8.22 * Support extension type key in Map [#535](https://github.com/msgpack/msgpack-java/pull/535) * Remove addTargetClass() and addTargetTypeReference() from ExtensionTypeCustomDeserializers [#539](https://github.com/msgpack/msgpack-java/pull/539) From 86762b9168d6948e166860167ec831851b174d39 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 15:21:21 -0700 Subject: [PATCH 172/417] Just use git tag for releasing a new version (#558) * Add 0.8.23 release notes * Update release steps * Fix build.sbt --- .github/workflows/release.yml | 1 + README.md | 26 +++++++++++++++++++------- RELEASE_NOTES.md | 16 ++++++++++++++++ build.sbt | 11 ----------- project/plugins.sbt | 1 - 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 487c521ab..ebb965695 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,6 +2,7 @@ name: Release to Sonatype on: push: + branches: [develop, main] tags: - v* workflow_dispatch: diff --git a/README.md b/README.md index 7b41f0c83..2a6571ad3 100644 --- a/README.md +++ b/README.md @@ -85,17 +85,18 @@ Here is a list of sbt commands for daily development: > publishLocal # Install to local .ivy2 repository > publishM2 # Install to local .m2 Maven repository > publish # Publishing a snapshot version to the Sonatype repository +``` -> release # Run the release procedure (set a new version, run tests, upload artifacts, then deploy to Sonatype) +### Publish to Sonatype (Maven Central) -# [optional] When you need to perform the individual release steps manually, use the following commands: -> publishSigned # Publish GPG signed artifacts to the Sonatype repository -> sonatypeBundleRelease # Publish to the Maven Central (It will be synched within less than 4 hours) -``` +To publish a new version, you only need to add a new git tag and push it to GitHub. GitHub Action will deploy a new release version to Maven Central (Sonatype). -Once you run a release command, a new git tag v(version number) will be pushed to GitHub. GitHub Action will deploy a new release version to Maven Central (Sonatype). +```scala +$ git tag v0.x.y +$ git push origin v0.x.y +``` -For publishing to Maven central using a local machine, msgpack-java uses [sbt-sonatype](https://github.com/xerial/sbt-sonatype) plugin. Set Sonatype account information (user name and password) in the global sbt settings. To protect your password, never include this file in your project. +If you need to publish to Maven central using a local machine, you need to configure [sbt-sonatype](https://github.com/xerial/sbt-sonatype) plugin. First set Sonatype account information (user name and password) in the global sbt settings. To protect your password, never include this file in your project. ___$HOME/.sbt/(sbt-version)/sonatype.sbt___ @@ -106,6 +107,17 @@ credentials += Credentials("Sonatype Nexus Repository Manager", "(Sonatype password)") ``` +You may also need to configure GPG. See the instruction in [sbt-pgp](https://github.com/sbt/sbt-pgp). + +Then, run `publishedSigned` followed by `sonatypeBundleRelease`: +``` +# [optional] When you need to perform the individual release steps manually, use the following commands: +> publishSigned # Publish GPG signed artifacts to the Sonatype repository +> sonatypeBundleRelease # Publish to the Maven Central (It will be synched within less than 4 hours) +``` + +If some sporadic error happens (e.g., Sonatype timeout), rerun `sonatypeBundleRelease` again. + ### Project Structure ``` diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 564ac679c..70dc7f220 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,21 @@ # Release Notes +## 0.8.23 + +* Produce stable map values [#548](https://github.com/msgpack/msgpac-java/pull/#548) +* Fixes #544: Fix a bug in reading EXT32 of 2GB size [#545](https://github.com/msgpack/msgpac-java/pull/545) +* Add a warning note for the usage of MessageUnpacker.readPayloadAsReference [#546](https://github.com/msgpack/msgpac-java/pull/546) + +Intenral changes: +* Add a script for releasing a new version of msgpack-java at CI +* Publish a snapshot version for every main branch commit [#556](https://github.com/msgpack/msgpac-java/pull/556) +* Use dynamic versioning with Git tags v0.x.y format [#555](https://github.com/msgpack/msgpac-java/pull/555) +* Update ScalaTest and ScalaCheck versions [#554](https://github.com/msgpack/msgpac-java/pull/554) +* Remove findbugs [#553](https://github.com/msgpack/msgpac-java/pull/553) +* Update build settings to use latest version of sbt and plugins [#552](https://github.com/msgpack/msgpac-java/pull/552) +* Run GitHub Actions for develop and main branches [#551](https://github.com/msgpack/msgpac-java/pull/551) +* Remove Travis build [#550](https://github.com/msgpack/msgpac-java/pull/550) + ## 0.8.22 * Support extension type key in Map [#535](https://github.com/msgpack/msgpack-java/pull/535) * Remove addTargetClass() and addTargetTypeReference() from ExtensionTypeCustomDeserializers [#539](https://github.com/msgpack/msgpack-java/pull/539) diff --git a/build.sbt b/build.sbt index 86abaf76e..ba034fdb3 100644 --- a/build.sbt +++ b/build.sbt @@ -1,5 +1,3 @@ -import ReleaseTransformations._ - Global / onChangedBuildSource := ReloadOnSourceChanges // For performance testing, ensure each test run one-by-one @@ -37,15 +35,6 @@ val buildSettings = Seq[Setting[_]]( opts } }, - // Release settings - releaseProcess := Seq[ReleaseStep]( - checkSnapshotDependencies, - inquireVersions, - runClean, - runTest, - tagRelease, - pushChanges - ), // Add sonatype repository settings publishTo := sonatypePublishToBundle.value, // Style check config: (sbt-jchekcstyle) diff --git a/project/plugins.sbt b/project/plugins.sbt index 043c1f730..fe129f572 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,3 @@ -addSbtPlugin("com.github.sbt" % "sbt-release" % "1.0.15") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") // TODO: Fixes jacoco error: From 4aadaba3dd852af49d62ddfb21ef71dc33800b80 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 15:24:10 -0700 Subject: [PATCH 173/417] Fix release target --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ebb965695..487c521ab 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,6 @@ name: Release to Sonatype on: push: - branches: [develop, main] tags: - v* workflow_dispatch: From cf70b646ba3bebf36347d0baf8b8b489a1548845 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 15:28:20 -0700 Subject: [PATCH 174/417] Fix release command --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 487c521ab..bdeefbdd2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,7 +28,7 @@ jobs: env: PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} run: | - ./sbt publish + ./sbt publishSigned - name: Release to Sonatype env: SONATYPE_USERNAME: '${{ secrets.SONATYPE_USER }}' From 8832390b7350df5d246ef001e1c37398c045dfff Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 11 May 2021 15:40:31 -0700 Subject: [PATCH 175/417] Fix broken links in release notes --- RELEASE_NOTES.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 70dc7f220..fa4ba22f3 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,19 +2,19 @@ ## 0.8.23 -* Produce stable map values [#548](https://github.com/msgpack/msgpac-java/pull/#548) -* Fixes #544: Fix a bug in reading EXT32 of 2GB size [#545](https://github.com/msgpack/msgpac-java/pull/545) -* Add a warning note for the usage of MessageUnpacker.readPayloadAsReference [#546](https://github.com/msgpack/msgpac-java/pull/546) +* Produce stable map values [#548](https://github.com/msgpack/msgpack-java/pull/548) +* Fixes #544: Fix a bug in reading EXT32 of 2GB size [#545](https://github.com/msgpack/msgpack-java/pull/545) +* Add a warning note for the usage of MessageUnpacker.readPayloadAsReference [#546](https://github.com/msgpack/msgpack-java/pull/546) Intenral changes: * Add a script for releasing a new version of msgpack-java at CI -* Publish a snapshot version for every main branch commit [#556](https://github.com/msgpack/msgpac-java/pull/556) -* Use dynamic versioning with Git tags v0.x.y format [#555](https://github.com/msgpack/msgpac-java/pull/555) -* Update ScalaTest and ScalaCheck versions [#554](https://github.com/msgpack/msgpac-java/pull/554) -* Remove findbugs [#553](https://github.com/msgpack/msgpac-java/pull/553) -* Update build settings to use latest version of sbt and plugins [#552](https://github.com/msgpack/msgpac-java/pull/552) -* Run GitHub Actions for develop and main branches [#551](https://github.com/msgpack/msgpac-java/pull/551) -* Remove Travis build [#550](https://github.com/msgpack/msgpac-java/pull/550) +* Publish a snapshot version for every main branch commit [#556](https://github.com/msgpack/msgpack-java/pull/556) +* Use dynamic versioning with Git tags v0.x.y format [#555](https://github.com/msgpack/msgpack-java/pull/555) +* Update ScalaTest and ScalaCheck versions [#554](https://github.com/msgpack/msgpack-java/pull/554) +* Remove findbugs [#553](https://github.com/msgpack/msgpack-java/pull/553) +* Update build settings to use latest version of sbt and plugins [#552](https://github.com/msgpack/msgpack-java/pull/552) +* Run GitHub Actions for develop and main branches [#551](https://github.com/msgpack/msgpack-java/pull/551) +* Remove Travis build [#550](https://github.com/msgpack/msgpack-java/pull/550) ## 0.8.22 * Support extension type key in Map [#535](https://github.com/msgpack/msgpack-java/pull/535) From 98acc3412f03e8885e41bfb8df43f4ecdc16fd22 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 12 May 2021 00:44:32 +0200 Subject: [PATCH 176/417] Update sbt-osgi to 0.9.6 (#561) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index fe129f572..d0fd94755 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.5") +addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") From ad5107d1152e8d68083e4763bf63afee6b6349fb Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 12 May 2021 00:44:49 +0200 Subject: [PATCH 177/417] Update scalatest to 3.2.8 (#564) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ba034fdb3..a97c20f7b 100644 --- a/build.sbt +++ b/build.sbt @@ -74,7 +74,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) libraryDependencies ++= Seq( // msgpack-core should have no external dependencies junitInterface, - "org.scalatest" %% "scalatest" % "3.2.7" % "test", + "org.scalatest" %% "scalatest" % "3.2.8" % "test", "org.scalacheck" %% "scalacheck" % "1.15.4" % "test", "org.xerial" %% "xerial-core" % "3.6.0" % "test", "org.msgpack" % "msgpack" % "0.6.12" % "test", From b6ff94f461e93ca867f7942ae08230697a5ea4e5 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sun, 16 May 2021 23:42:40 -0700 Subject: [PATCH 178/417] Use JDK8 for msgpack-java release (#567) --- .github/workflows/release.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bdeefbdd2..d105d9d1b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,10 +16,11 @@ jobs: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version - run: git fetch --tags -f - # Install OpenJDK 11 + # Install OpenJDK 8 - uses: olafurpg/setup-scala@v10 with: - java-version: adopt@1.11 + # We need to use JDK8 for Android compatibility https://github.com/msgpack/msgpack-java/issues/516 + java-version: adopt@1.8 - name: Setup GPG env: PGP_SECRET: ${{ secrets.PGP_SECRET }} From 2864da3291ffbe4ce8fba3ecd5b43b556864c290 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sun, 16 May 2021 23:43:50 -0700 Subject: [PATCH 179/417] 0.8.24 release --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index fa4ba22f3..e04b4d566 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Release Notes +## 0.8.24 + +* Rebuild with JDK8 for Android compatibility [#567](https://github.com/msgpack/msgpack-java/pull/567) + ## 0.8.23 * Produce stable map values [#548](https://github.com/msgpack/msgpack-java/pull/548) From 1b2ec92ed43caa0af347abc390e75d021343aee2 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 17 May 2021 13:32:32 -0700 Subject: [PATCH 180/417] Timestamp support (#565) * Add add support for Timestamp type * Add timestamp tests * Fix timestamp pack overflow * Add timestamp value support * Support timestamp in unpackValue * Use AirSpec for integration with ScalaCheck * Fix ValueFactoryTest * Remove scalatest * Remove xerial-core dependency * Remove unnecessary dependencies * Variable.writeTo roundtrip tests * Use consistent code style Co-authored-by: Sadayuki Furuhashi --- README.md | 2 +- build.sbt | 18 +- .../java/org/msgpack/core/MessagePack.java | 2 + .../java/org/msgpack/core/MessagePacker.java | 107 ++ .../org/msgpack/core/MessageUnpacker.java | 62 +- .../value/ImmutableTimestampValue.java | 26 + .../org/msgpack/value/ImmutableValue.java | 3 + .../org/msgpack/value/TimestampValue.java | 33 + .../main/java/org/msgpack/value/Value.java | 18 + .../java/org/msgpack/value/ValueFactory.java | 17 + .../java/org/msgpack/value/ValueType.java | 6 + .../main/java/org/msgpack/value/Variable.java | 112 ++- .../value/impl/AbstractImmutableValue.java | 13 + .../impl/ImmutableTimestampValueImpl.java | 198 ++++ .../msgpack/core/InvalidDataReadTest.scala | 34 +- .../core/MessageBufferPackerTest.scala | 22 +- .../org/msgpack/core/MessageFormatTest.scala | 13 +- .../org/msgpack/core/MessagePackSpec.scala | 26 +- .../org/msgpack/core/MessagePackTest.scala | 941 +++++++++--------- .../org/msgpack/core/MessagePackerTest.scala | 59 +- .../msgpack/core/MessageUnpackerTest.scala | 137 ++- .../msgpack/core/buffer/ByteStringTest.scala | 20 +- .../core/buffer/MessageBufferInputTest.scala | 65 +- .../core/buffer/MessageBufferOutputTest.scala | 30 +- .../core/buffer/MessageBufferTest.scala | 377 ++++--- .../core/example/MessagePackExampleTest.scala | 14 +- .../value/RawStringValueImplTest.scala | 22 +- .../org/msgpack/value/ValueFactoryTest.scala | 77 +- .../scala/org/msgpack/value/ValueTest.scala | 31 +- .../org/msgpack/value/ValueTypeTest.scala | 95 +- .../org/msgpack/value/VariableTest.scala | 310 ++++++ 31 files changed, 1934 insertions(+), 956 deletions(-) create mode 100644 msgpack-core/src/main/java/org/msgpack/value/ImmutableTimestampValue.java create mode 100644 msgpack-core/src/main/java/org/msgpack/value/TimestampValue.java create mode 100644 msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java create mode 100644 msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala diff --git a/README.md b/README.md index 2a6571ad3..1a7c1f439 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Here is a list of sbt commands for daily development: > ~test:compile # Compile both source and test codes > ~test # Run tests upon source code change > ~testOnly *MessagePackTest # Run tests in the specified class -> ~testOnly *MessagePackTest -- -n prim # Run the test tagged as "prim" +> ~testOnly *MessagePackTest -- (pattern) # Run tests matching the pattern > project msgpack-core # Focus on a specific project > package # Create a jar file in the target folder of each project > findbugs # Produce findbugs report in target/findbugs diff --git a/build.sbt b/build.sbt index a97c20f7b..eae3cd51a 100644 --- a/build.sbt +++ b/build.sbt @@ -5,6 +5,8 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) +val AIRFRAME_VERSION = "20.4.1" + // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true // Use coursier friendly version separator @@ -71,15 +73,19 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack.value", "org.msgpack.value.impl" ), + testFrameworks += new TestFramework("wvlet.airspec.Framework"), libraryDependencies ++= Seq( // msgpack-core should have no external dependencies junitInterface, - "org.scalatest" %% "scalatest" % "3.2.8" % "test", - "org.scalacheck" %% "scalacheck" % "1.15.4" % "test", - "org.xerial" %% "xerial-core" % "3.6.0" % "test", - "org.msgpack" % "msgpack" % "0.6.12" % "test", - "commons-codec" % "commons-codec" % "1.12" % "test", - "com.typesafe.akka" %% "akka-actor" % "2.5.23" % "test" + "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", + "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", + // Add property testing support with forAll methods + "org.scalacheck" %% "scalacheck" % "1.15.4" % "test", + // For performance comparison with msgpack v6 + "org.msgpack" % "msgpack" % "0.6.12" % "test", + // For integration test with Akka + "com.typesafe.akka" %% "akka-actor" % "2.5.23" % "test", + "org.scala-lang.modules" %% "scala-collection-compat" % "2.4.3" % "test" ) ) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index ed8b1e405..edd449b34 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -165,6 +165,8 @@ public static final boolean isFixedRaw(byte b) public static final byte MAP32 = (byte) 0xdf; public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; + + public static final byte EXT_TIMESTAMP = (byte) -1; } private MessagePack() diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 6837f9f72..4cf789d9f 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -32,6 +32,7 @@ import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; +import java.time.Instant; import static org.msgpack.core.MessagePack.Code.ARRAY16; import static org.msgpack.core.MessagePack.Code.ARRAY32; @@ -41,6 +42,7 @@ import static org.msgpack.core.MessagePack.Code.EXT16; import static org.msgpack.core.MessagePack.Code.EXT32; import static org.msgpack.core.MessagePack.Code.EXT8; +import static org.msgpack.core.MessagePack.Code.EXT_TIMESTAMP; import static org.msgpack.core.MessagePack.Code.FALSE; import static org.msgpack.core.MessagePack.Code.FIXARRAY_PREFIX; import static org.msgpack.core.MessagePack.Code.FIXEXT1; @@ -798,6 +800,111 @@ else if (s.length() < (1 << 16)) { return this; } + /** + * Writes a Timestamp value. + * + *

      + * This method writes a timestamp value using timestamp format family. + * + * @param instant the timestamp to be written + * @return this packer + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packTimestamp(Instant instant) + throws IOException + { + return packTimestamp(instant.getEpochSecond(), instant.getNano()); + } + + /** + * Writes a Timesamp value using a millisecond value (e.g., System.currentTimeMillis()) + * @param millis the millisecond value + * @return this packer + * @throws IOException when underlying output throws IOException + */ + public MessagePacker packTimestamp(long millis) + throws IOException + { + return packTimestamp(Instant.ofEpochMilli(millis)); + } + + private static final long NANOS_PER_SECOND = 1000000000L; + + /** + * Writes a Timestamp value. + * + *

      + * This method writes a timestamp value using timestamp format family. + * + * @param epochSecond the number of seconds from 1970-01-01T00:00:00Z + * @param nanoAdjustment the nanosecond adjustment to the number of seconds, positive or negative + * @return this + * @throws IOException when underlying output throws IOException + * @throws ArithmeticException when epochSecond plus nanoAdjustment in seconds exceeds the range of long + */ + public MessagePacker packTimestamp(long epochSecond, int nanoAdjustment) + throws IOException, ArithmeticException + { + long sec = Math.addExact(epochSecond, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND)); + long nsec = Math.floorMod((long) nanoAdjustment, NANOS_PER_SECOND); + + if (sec >>> 34 == 0) { + // sec can be serialized in 34 bits. + long data64 = (nsec << 34) | sec; + if ((data64 & 0xffffffff00000000L) == 0L) { + // sec can be serialized in 32 bits and nsec is 0. + // use timestamp 32 + writeTimestamp32((int) sec); + } + else { + // sec exceeded 32 bits or nsec is not 0. + // use timestamp 64 + writeTimestamp64(data64); + } + } + else { + // use timestamp 96 format + writeTimestamp96(sec, (int) nsec); + } + return this; + } + + private void writeTimestamp32(int sec) + throws IOException + { + // timestamp 32 in fixext 4 + ensureCapacity(6); + buffer.putByte(position++, FIXEXT4); + buffer.putByte(position++, EXT_TIMESTAMP); + buffer.putInt(position, sec); + position += 4; + } + + private void writeTimestamp64(long data64) + throws IOException + { + // timestamp 64 in fixext 8 + ensureCapacity(10); + buffer.putByte(position++, FIXEXT8); + buffer.putByte(position++, EXT_TIMESTAMP); + buffer.putLong(position, data64); + position += 8; + } + + private void writeTimestamp96(long sec, int nsec) + throws IOException + { + // timestamp 96 in ext 8 + ensureCapacity(15); + buffer.putByte(position++, EXT8); + buffer.putByte(position++, (byte) 12); // length of nsec and sec + buffer.putByte(position++, EXT_TIMESTAMP); + buffer.putInt(position, nsec); + position += 4; + buffer.putLong(position, sec); + position += 8; + } + /** * Writes header of an Array value. *

      diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 6d0d57ab3..b43204beb 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -32,7 +32,9 @@ import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; +import java.time.Instant; +import static org.msgpack.core.MessagePack.Code.EXT_TIMESTAMP; import static org.msgpack.core.Preconditions.checkNotNull; /** @@ -595,6 +597,12 @@ private static MessagePackException unexpected(String expected, byte b) } } + private static MessagePackException unexpectedExtension(String expected, int expectedType, int actualType) + { + return new MessageTypeException(String.format("Expected extension type %s (%d), but got extension type %d", + expected, expectedType, actualType)); + } + public ImmutableValue unpackValue() throws IOException { @@ -643,7 +651,12 @@ public ImmutableValue unpackValue() } case EXTENSION: { ExtensionTypeHeader extHeader = unpackExtensionTypeHeader(); - return ValueFactory.newExtension(extHeader.getType(), readPayload(extHeader.getLength())); + switch (extHeader.getType()) { + case EXT_TIMESTAMP: + return ValueFactory.newTimestamp(unpackTimestamp(extHeader)); + default: + return ValueFactory.newExtension(extHeader.getType(), readPayload(extHeader.getLength())); + } } default: throw new MessageNeverUsedFormatException("Unknown value type"); @@ -707,7 +720,13 @@ public Variable unpackValue(Variable var) } case EXTENSION: { ExtensionTypeHeader extHeader = unpackExtensionTypeHeader(); - var.setExtensionValue(extHeader.getType(), readPayload(extHeader.getLength())); + switch (extHeader.getType()) { + case EXT_TIMESTAMP: + var.setTimestampValue(unpackTimestamp(extHeader)); + break; + default: + var.setExtensionValue(extHeader.getType(), readPayload(extHeader.getLength())); + } return var; } default: @@ -1257,6 +1276,45 @@ private String decodeStringFastPath(int length) } } + public Instant unpackTimestamp() + throws IOException + { + ExtensionTypeHeader ext = unpackExtensionTypeHeader(); + return unpackTimestamp(ext); + } + + /** + * Internal method that can be used only when the extension type header is already read. + */ + private Instant unpackTimestamp(ExtensionTypeHeader ext) throws IOException + { + if (ext.getType() != EXT_TIMESTAMP) { + throw unexpectedExtension("Timestamp", EXT_TIMESTAMP, ext.getType()); + } + switch (ext.getLength()) { + case 4: { + // Need to convert Java's int (int32) to uint32 + long u32 = readInt() & 0xffffffffL; + return Instant.ofEpochSecond(u32); + } + case 8: { + long data64 = readLong(); + int nsec = (int) (data64 >>> 34); + long sec = data64 & 0x00000003ffffffffL; + return Instant.ofEpochSecond(sec, nsec); + } + case 12: { + // Need to convert Java's int (int32) to uint32 + long nsecU32 = readInt() & 0xffffffffL; + long sec = readLong(); + return Instant.ofEpochSecond(sec, nsecU32); + } + default: + throw new MessageFormatException(String.format("Timestamp extension type (%d) expects 4, 8, or 12 bytes of payload but got %d bytes", + EXT_TIMESTAMP, ext.getLength())); + } + } + /** * Reads header of an array. * diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableTimestampValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableTimestampValue.java new file mode 100644 index 000000000..bd4a901bb --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableTimestampValue.java @@ -0,0 +1,26 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.value; + +/** + * Immutable representation of MessagePack's Timestamp type. + * + * @see org.msgpack.value.TimestampValue + */ +public interface ImmutableTimestampValue + extends TimestampValue, ImmutableValue +{ +} diff --git a/msgpack-core/src/main/java/org/msgpack/value/ImmutableValue.java b/msgpack-core/src/main/java/org/msgpack/value/ImmutableValue.java index 88798a13d..f85c69bac 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ImmutableValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ImmutableValue.java @@ -47,4 +47,7 @@ public interface ImmutableValue @Override public ImmutableStringValue asStringValue(); + + @Override + public ImmutableTimestampValue asTimestampValue(); } diff --git a/msgpack-core/src/main/java/org/msgpack/value/TimestampValue.java b/msgpack-core/src/main/java/org/msgpack/value/TimestampValue.java new file mode 100644 index 000000000..465579b01 --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/value/TimestampValue.java @@ -0,0 +1,33 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.value; + +import java.time.Instant; + +/** + * Value representation of MessagePack's Timestamp type. + */ +public interface TimestampValue + extends ExtensionValue +{ + long getEpochSecond(); + + int getNano(); + + long toEpochMillis(); + + Instant toInstant(); +} diff --git a/msgpack-core/src/main/java/org/msgpack/value/Value.java b/msgpack-core/src/main/java/org/msgpack/value/Value.java index 546dfbbf4..a3d1ac365 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/Value.java +++ b/msgpack-core/src/main/java/org/msgpack/value/Value.java @@ -16,6 +16,7 @@ package org.msgpack.value; import org.msgpack.core.MessagePacker; +import org.msgpack.core.MessageTypeCastException; import java.io.IOException; @@ -180,6 +181,14 @@ public interface Value */ boolean isExtensionValue(); + /** + * Returns true if the type of this value is Timestamp. + * + * If this method returns true, {@code asTimestamp} never throws exceptions. + * Note that you can't use instanceof or cast ((MapValue) thisValue) to check type of a value because type of a mutable value is variable. + */ + boolean isTimestampValue(); + /** * Returns the value as {@code NilValue}. Otherwise throws {@code MessageTypeCastException}. * @@ -280,6 +289,15 @@ public interface Value */ ExtensionValue asExtensionValue(); + /** + * Returns the value as {@code TimestampValue}. Otherwise throws {@code MessageTypeCastException}. + * + * Note that you can't use instanceof or cast ((TimestampValue) thisValue) to check type of a value because type of a mutable value is variable. + * + * @throws MessageTypeCastException If type of this value is not Map. + */ + TimestampValue asTimestampValue(); + /** * Serializes the value using the specified {@code MessagePacker} * diff --git a/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java b/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java index 21a4f85dd..dc1e28da8 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ValueFactory.java @@ -25,8 +25,10 @@ import org.msgpack.value.impl.ImmutableMapValueImpl; import org.msgpack.value.impl.ImmutableNilValueImpl; import org.msgpack.value.impl.ImmutableStringValueImpl; +import org.msgpack.value.impl.ImmutableTimestampValueImpl; import java.math.BigInteger; +import java.time.Instant; import java.util.AbstractMap; import java.util.Arrays; import java.util.LinkedHashMap; @@ -295,4 +297,19 @@ public static ImmutableExtensionValue newExtension(byte type, byte[] data) { return new ImmutableExtensionValueImpl(type, data); } + + public static ImmutableTimestampValue newTimestamp(Instant timestamp) + { + return new ImmutableTimestampValueImpl(timestamp); + } + + public static ImmutableTimestampValue newTimestamp(long millis) + { + return newTimestamp(Instant.ofEpochMilli(millis)); + } + + public static ImmutableTimestampValue newTimestamp(long epochSecond, int nanoAdjustment) + { + return newTimestamp(Instant.ofEpochSecond(epochSecond, nanoAdjustment)); + } } diff --git a/msgpack-core/src/main/java/org/msgpack/value/ValueType.java b/msgpack-core/src/main/java/org/msgpack/value/ValueType.java index b06478402..8eeb957b3 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/ValueType.java +++ b/msgpack-core/src/main/java/org/msgpack/value/ValueType.java @@ -36,6 +36,12 @@ public enum ValueType MAP(false, false), EXTENSION(false, false); + /** + * Design note: We do not add Timestamp as a ValueType here because + * detecting Timestamp values requires reading 1-3 bytes ahead while the other + * value types can be determined just by reading the first one byte. + */ + private final boolean numberType; private final boolean rawType; diff --git a/msgpack-core/src/main/java/org/msgpack/value/Variable.java b/msgpack-core/src/main/java/org/msgpack/value/Variable.java index 28295fe1c..ae88170c7 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/Variable.java +++ b/msgpack-core/src/main/java/org/msgpack/value/Variable.java @@ -30,6 +30,7 @@ import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; +import java.time.Instant; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; @@ -109,6 +110,12 @@ public boolean isExtensionValue() return getValueType().isExtensionType(); } + @Override + public boolean isTimestampValue() + { + return false; + } + @Override public NilValue asNilValue() { @@ -175,6 +182,12 @@ public ExtensionValue asExtensionValue() throw new MessageTypeCastException(); } + @Override + public TimestampValue asTimestampValue() + { + throw new MessageTypeCastException(); + } + @Override public boolean equals(Object obj) { @@ -211,7 +224,8 @@ public static enum Type RAW_STRING(ValueType.STRING), LIST(ValueType.ARRAY), MAP(ValueType.MAP), - EXTENSION(ValueType.EXTENSION); + EXTENSION(ValueType.EXTENSION), + TIMESTAMP(ValueType.EXTENSION); private final ValueType valueType; @@ -235,6 +249,7 @@ public ValueType getValueType() private final ArrayValueAccessor arrayAccessor = new ArrayValueAccessor(); private final MapValueAccessor mapAccessor = new MapValueAccessor(); private final ExtensionValueAccessor extensionAccessor = new ExtensionValueAccessor(); + private final TimestampValueAccessor timestampAccessor = new TimestampValueAccessor(); private Type type; @@ -1031,6 +1046,86 @@ public void writeTo(MessagePacker pk) } } + public Variable setTimestampValue(Instant timestamp) + { + this.type = Type.TIMESTAMP; + this.accessor = timestampAccessor; + this.objectValue = ValueFactory.newTimestamp(timestamp); + return this; + } + + private class TimestampValueAccessor + extends AbstractValueAccessor + implements TimestampValue + { + @Override + public boolean isTimestampValue() + { + return true; + } + + @Override + public ValueType getValueType() + { + return ValueType.EXTENSION; + } + + @Override + public TimestampValue asTimestampValue() + { + return this; + } + + @Override + public ImmutableTimestampValue immutableValue() + { + return (ImmutableTimestampValue) objectValue; + } + + @Override + public byte getType() + { + return ((ImmutableTimestampValue) objectValue).getType(); + } + + @Override + public byte[] getData() + { + return ((ImmutableTimestampValue) objectValue).getData(); + } + + @Override + public void writeTo(MessagePacker pk) + throws IOException + { + ((ImmutableTimestampValue) objectValue).writeTo(pk); + } + + @Override + public long getEpochSecond() + { + return ((ImmutableTimestampValue) objectValue).getEpochSecond(); + } + + @Override + public int getNano() + { + return ((ImmutableTimestampValue) objectValue).getNano(); + } + + @Override + public long toEpochMillis() + { + return ((ImmutableTimestampValue) objectValue).toEpochMillis(); + } + + @Override + public Instant toInstant() + { + return ((ImmutableTimestampValue) objectValue).toInstant(); + } + } + //// // Value // @@ -1144,6 +1239,12 @@ public boolean isExtensionValue() return getValueType().isExtensionType(); } + @Override + public boolean isTimestampValue() + { + return this.type == Type.TIMESTAMP; + } + @Override public NilValue asNilValue() { @@ -1242,4 +1343,13 @@ public ExtensionValue asExtensionValue() } return (ExtensionValue) accessor; } + + @Override + public TimestampValue asTimestampValue() + { + if (!isTimestampValue()) { + throw new MessageTypeCastException(); + } + return (TimestampValue) accessor; + } } diff --git a/msgpack-core/src/main/java/org/msgpack/value/impl/AbstractImmutableValue.java b/msgpack-core/src/main/java/org/msgpack/value/impl/AbstractImmutableValue.java index 1dae99cf2..18fcd2753 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/impl/AbstractImmutableValue.java +++ b/msgpack-core/src/main/java/org/msgpack/value/impl/AbstractImmutableValue.java @@ -27,6 +27,7 @@ import org.msgpack.value.ImmutableNumberValue; import org.msgpack.value.ImmutableRawValue; import org.msgpack.value.ImmutableStringValue; +import org.msgpack.value.ImmutableTimestampValue; import org.msgpack.value.ImmutableValue; abstract class AbstractImmutableValue @@ -98,6 +99,12 @@ public boolean isExtensionValue() return getValueType().isExtensionType(); } + @Override + public boolean isTimestampValue() + { + return false; + } + @Override public ImmutableNilValue asNilValue() { @@ -163,4 +170,10 @@ public ImmutableExtensionValue asExtensionValue() { throw new MessageTypeCastException(); } + + @Override + public ImmutableTimestampValue asTimestampValue() + { + throw new MessageTypeCastException(); + } } diff --git a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java new file mode 100644 index 000000000..227c85d0b --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java @@ -0,0 +1,198 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.value.impl; + +import org.msgpack.core.MessagePacker; +import org.msgpack.core.buffer.MessageBuffer; +import org.msgpack.value.ExtensionValue; +import org.msgpack.value.ImmutableExtensionValue; +import org.msgpack.value.ImmutableTimestampValue; +import org.msgpack.value.TimestampValue; +import org.msgpack.value.Value; +import org.msgpack.value.ValueType; + +import java.io.IOException; +import java.time.Instant; +import java.util.Arrays; + +import static org.msgpack.core.MessagePack.Code.EXT_TIMESTAMP; + +/** + * {@code ImmutableTimestampValueImpl} Implements {@code ImmutableTimestampValue} using a {@code byte} and a {@code byte[]} fields. + * + * @see TimestampValue + */ +public class ImmutableTimestampValueImpl + extends AbstractImmutableValue + implements ImmutableExtensionValue, ImmutableTimestampValue +{ + private final Instant instant; + private byte[] data; + + public ImmutableTimestampValueImpl(Instant timestamp) + { + this.instant = timestamp; + } + + @Override + public boolean isTimestampValue() + { + return true; + } + + @Override + public byte getType() + { + return EXT_TIMESTAMP; + } + + @Override + public ValueType getValueType() + { + // Note: Future version should return ValueType.TIMESTAMP instead. + return ValueType.EXTENSION; + } + + @Override + public ImmutableTimestampValue immutableValue() + { + return this; + } + + @Override + public ImmutableExtensionValue asExtensionValue() + { + return this; + } + + @Override + public ImmutableTimestampValue asTimestampValue() + { + return this; + } + + @Override + public byte[] getData() + { + if (data == null) { + // See MessagePacker.packTimestampImpl + byte[] bytes; + long sec = getEpochSecond(); + int nsec = getNano(); + if (sec >>> 34 == 0) { + long data64 = (nsec << 34) | sec; + if ((data64 & 0xffffffff00000000L) == 0L) { + bytes = new byte[4]; + MessageBuffer.wrap(bytes).putInt(0, (int) sec); + } + else { + bytes = new byte[8]; + MessageBuffer.wrap(bytes).putLong(0, data64); + } + } + else { + bytes = new byte[12]; + MessageBuffer buffer = MessageBuffer.wrap(bytes); + buffer.putInt(0, nsec); + buffer.putLong(4, sec); + } + data = bytes; + } + return data; + } + + @Override + public long getEpochSecond() + { + return instant.getEpochSecond(); + } + + @Override + public int getNano() + { + return instant.getNano(); + } + + @Override + public long toEpochMillis() + { + return instant.toEpochMilli(); + } + + @Override + public Instant toInstant() + { + return instant; + } + + @Override + public void writeTo(MessagePacker packer) + throws IOException + { + packer.packTimestamp(instant); + } + + @Override + public boolean equals(Object o) + { + // Implements same behavior with ImmutableExtensionValueImpl. + if (o == this) { + return true; + } + if (!(o instanceof Value)) { + return false; + } + Value v = (Value) o; + + if (!v.isExtensionValue()) { + return false; + } + ExtensionValue ev = v.asExtensionValue(); + + // Here should use isTimestampValue and asTimestampValue instead. However, because + // adding these methods to Value interface can't keep backward compatibility without + // using "default" keyword since Java 7, here uses instanceof of and cast instead. + if (ev instanceof TimestampValue) { + TimestampValue tv = (TimestampValue) ev; + return instant.equals(tv.toInstant()); + } + else { + return EXT_TIMESTAMP == ev.getType() && Arrays.equals(getData(), ev.getData()); + } + } + + @Override + public int hashCode() + { + // Implements same behavior with ImmutableExtensionValueImpl. + int hash = EXT_TIMESTAMP; + hash *= 31; + hash = instant.hashCode(); + return hash; + } + + @Override + public String toJson() + { + return "\"" + toInstant().toString() + "\""; + } + + @Override + public String toString() + { + return toInstant().toString(); + } +} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala index 4950da82a..4e39ff85c 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala @@ -1,23 +1,25 @@ package org.msgpack.core +import org.msgpack.core.MessagePackSpec.createMessagePackData +import wvlet.airspec.AirSpec + /** - * - */ -class InvalidDataReadTest extends MessagePackSpec { + * + */ +class InvalidDataReadTest extends AirSpec { - "Reading long EXT32" in { - // Prepare an EXT32 data with 2GB (Int.MaxValue size) payload for testing the behavior of MessageUnpacker.skipValue() - // Actually preparing 2GB of data, however, is too much for CI, so we create only the header part. - val msgpack = createMessagePackData(p => p.packExtensionTypeHeader(MessagePack.Code.EXT32, Int.MaxValue)) - val u = MessagePack.newDefaultUnpacker(msgpack) - try { - // This error will be thrown after reading the header as the input has no EXT32 body - intercept[MessageInsufficientBufferException] { - u.skipValue() - } - } - finally { - u.close() + test("Reading long EXT32") { + // Prepare an EXT32 data with 2GB (Int.MaxValue size) payload for testing the behavior of MessageUnpacker.skipValue() + // Actually preparing 2GB of data, however, is too much for CI, so we create only the header part. + val msgpack = createMessagePackData(p => p.packExtensionTypeHeader(MessagePack.Code.EXT32, Int.MaxValue)) + val u = MessagePack.newDefaultUnpacker(msgpack) + try { + // This error will be thrown after reading the header as the input has no EXT32 body + intercept[MessageInsufficientBufferException] { + u.skipValue() } + } finally { + u.close() + } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala index 2194e42ea..58b29f435 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala @@ -17,12 +17,12 @@ package org.msgpack.core import java.io.ByteArrayOutputStream import java.util.Arrays - import org.msgpack.value.ValueFactory._ +import wvlet.airspec.AirSpec -class MessageBufferPackerTest extends MessagePackSpec { - "MessageBufferPacker" should { - "be equivalent to ByteArrayOutputStream" in { +class MessageBufferPackerTest extends AirSpec { + test("MessageBufferPacker") { + test("be equivalent to ByteArrayOutputStream") { val packer1 = MessagePack.newDefaultBufferPacker packer1.packValue(newMap(newString("a"), newInteger(1), newString("b"), newString("s"))) @@ -34,17 +34,17 @@ class MessageBufferPackerTest extends MessagePackSpec { packer1.toByteArray shouldBe stream.toByteArray } - "clear unflushed" in { + test("clear unflushed") { val packer = MessagePack.newDefaultBufferPacker - packer.packInt(1); - packer.clear(); - packer.packInt(2); + packer.packInt(1) + packer.clear() + packer.packInt(2) - packer.toByteArray shouldBe Array(2) + packer.toByteArray shouldBe Array[Byte](2) val buffer = packer.toBufferList().get(0) - buffer.toByteArray() shouldBe Array(2) + buffer.toByteArray() shouldBe Array[Byte](2) val array = Arrays.copyOf(buffer.sliceAsByteBuffer().array(), buffer.size()) - array shouldBe Array(2) + array shouldBe Array[Byte](2) } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala index e7e9a4c36..5f3447617 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala @@ -17,20 +17,21 @@ package org.msgpack.core import org.msgpack.core.MessagePack.Code import org.msgpack.value.ValueType -import org.scalatest.exceptions.TestFailedException +import wvlet.airspec.AirSpec +import wvlet.airspec.spi.AirSpecException import scala.util.Random /** * Created on 2014/05/07. */ -class MessageFormatTest extends MessagePackSpec { - "MessageFormat" should { - "cover all byte codes" in { +class MessageFormatTest extends AirSpec with Benchmark { + test("MessageFormat") { + test("cover all byte codes") { def checkV(b: Byte, tpe: ValueType) { try MessageFormat.valueOf(b).getValueType shouldBe tpe catch { - case e: TestFailedException => + case e: AirSpecException => error(f"Failure when looking at byte ${b}%02x") throw e } @@ -102,7 +103,7 @@ class MessageFormatTest extends MessagePackSpec { } } - "improve the valueOf performance" in { + test("improve the valueOf performance") { val N = 1000000 val idx = (0 until N).map(x => Random.nextInt(256).toByte).toArray[Byte] diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala index ae1f5ae45..dee315cd9 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala @@ -15,22 +15,13 @@ // package org.msgpack.core -import java.io.ByteArrayOutputStream -import org.scalatest._ -import org.scalatest.matchers.should.Matchers -import org.scalatest.prop.TableDrivenPropertyChecks -import org.scalatest.wordspec.AnyWordSpec -import xerial.core.log.{LogLevel, Logger} -import xerial.core.util.{TimeReport, Timer} - -import scala.language.implicitConversions - -trait MessagePackSpec extends AnyWordSpec with Matchers with GivenWhenThen with OptionValues with BeforeAndAfter with Benchmark with Logger { +import wvlet.log.LogLevel +import wvlet.log.io.{TimeReport, Timer} - implicit def toTag(s: String): Tag = Tag(s) +import java.io.ByteArrayOutputStream +object MessagePackSpec { def toHex(arr: Array[Byte]) = arr.map(x => f"$x%02x").mkString(" ") - def createMessagePackData(f: MessagePacker => Unit): Array[Byte] = { val b = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(b) @@ -41,20 +32,19 @@ trait MessagePackSpec extends AnyWordSpec with Matchers with GivenWhenThen with } trait Benchmark extends Timer { + private val numWarmUpRuns = 10 - val numWarmUpRuns = 10 - - override protected def time[A](blockName: String, logLevel: LogLevel, repeat: Int)(f: => A): TimeReport = { + override protected def time[A](blockName: String, logLevel: LogLevel = LogLevel.INFO, repeat: Int = 1, blockRepeat: Int = 1)(f: => A): TimeReport = { super.time(blockName, logLevel = LogLevel.INFO, repeat)(f) } - override protected def block[A](name: String, repeat: Int)(f: => A): TimeReport = { + override protected def block[A](name: String)(f: => A): TimeReport = { var i = 0 while (i < numWarmUpRuns) { f i += 1 } - super.block(name, repeat)(f) + super.block(name)(f) } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index d2a209bb0..f60702ed8 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -15,28 +15,31 @@ // package org.msgpack.core +import org.msgpack.core.MessagePack.{Code, PackerConfig, UnpackerConfig} +import org.msgpack.core.MessagePackSpec.toHex +import org.msgpack.value.{Value, Variable} +import org.scalacheck.Prop.propBoolean +import org.scalacheck.{Arbitrary, Gen} +import wvlet.airspec.AirSpec +import wvlet.airspec.spi.PropertyCheck + import java.io.ByteArrayOutputStream import java.math.BigInteger import java.nio.CharBuffer import java.nio.charset.{CodingErrorAction, UnmappableCharacterException} -import org.msgpack.core.MessagePack.Code -import org.msgpack.core.MessagePack.{PackerConfig, UnpackerConfig} -import org.msgpack.value.{Value, Variable} -import org.scalacheck.Arbitrary -import org.scalacheck.Prop.{forAll, propBoolean} - +import java.time.Instant import scala.util.Random /** * Created on 2014/05/07. */ -class MessagePackTest extends MessagePackSpec { +class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { - def isValidUTF8(s: String) = { + private def isValidUTF8(s: String) = { MessagePack.UTF8.newEncoder().canEncode(s) } - def containsUnmappableCharacter(s: String): Boolean = { + private def containsUnmappableCharacter(s: String): Boolean = { try { MessagePack.UTF8 .newEncoder() @@ -50,549 +53,585 @@ class MessagePackTest extends MessagePackSpec { } } - "MessagePack" should { + test("clone packer config") { + val config = new PackerConfig() + .withBufferSize(10) + .withBufferFlushThreshold(32 * 1024) + .withSmallStringOptimizationThreshold(142) + val copy = config.clone() - "clone packer config" in { - val config = new PackerConfig() - .withBufferSize(10) - .withBufferFlushThreshold(32 * 1024) - .withSmallStringOptimizationThreshold(142) - val copy = config.clone() + copy shouldBe config + } - copy shouldBe config - } + test("clone unpacker config") { + val config = new UnpackerConfig() + .withBufferSize(1) + .withActionOnMalformedString(CodingErrorAction.IGNORE) + .withActionOnUnmappableString(CodingErrorAction.REPORT) + .withAllowReadingBinaryAsString(false) + .withStringDecoderBufferSize(34) + .withStringSizeLimit(4324) + + val copy = config.clone() + copy shouldBe config + } - "clone unpacker config" in { - val config = new UnpackerConfig() - .withBufferSize(1) - .withActionOnMalformedString(CodingErrorAction.IGNORE) - .withActionOnUnmappableString(CodingErrorAction.REPORT) - .withAllowReadingBinaryAsString(false) - .withStringDecoderBufferSize(34) - .withStringSizeLimit(4324) + test("detect fixint values") { - val copy = config.clone() - copy shouldBe config + for (i <- 0 until 0x79) { + Code.isPosFixInt(i.toByte) shouldBe true } - "detect fixint values" in { - - for (i <- 0 until 0x79) { - Code.isPosFixInt(i.toByte) shouldBe true - } - - for (i <- 0x80 until 0xFF) { - Code.isPosFixInt(i.toByte) shouldBe false - } + for (i <- 0x80 until 0xFF) { + Code.isPosFixInt(i.toByte) shouldBe false } + } - "detect fixarray values" in { - val packer = MessagePack.newDefaultBufferPacker() - packer.packArrayHeader(0) - packer.close - val bytes = packer.toByteArray - MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() shouldBe 0 - try { - MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() - fail("Shouldn't reach here") - } catch { - case e: MessageTypeException => // OK - } + test("detect fixarray values") { + val packer = MessagePack.newDefaultBufferPacker() + packer.packArrayHeader(0) + packer.close + val bytes = packer.toByteArray + MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() shouldBe 0 + try { + MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() + fail("Shouldn't reach here") + } catch { + case e: MessageTypeException => // OK } + } - "detect fixmap values" in { - val packer = MessagePack.newDefaultBufferPacker() - packer.packMapHeader(0) - packer.close - val bytes = packer.toByteArray - MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() shouldBe 0 - try { - MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() - fail("Shouldn't reach here") - } catch { - case e: MessageTypeException => // OK - } + test("detect fixmap values") { + val packer = MessagePack.newDefaultBufferPacker() + packer.packMapHeader(0) + packer.close + val bytes = packer.toByteArray + MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() shouldBe 0 + try { + MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() + fail("Shouldn't reach here") + } catch { + case e: MessageTypeException => // OK } + } - "detect fixint quickly" in { + test("detect fixint quickly") { - val N = 100000 - val idx = (0 until N).map(x => Random.nextInt(256).toByte).toArray[Byte] + val N = 100000 + val idx = (0 until N).map(x => Random.nextInt(256).toByte).toArray[Byte] - time("check fixint", repeat = 100) { + time("check fixint", repeat = 100) { - block("mask") { - var i = 0 - var count = 0 - while (i < N) { - if ((idx(i) & Code.POSFIXINT_MASK) == 0) { - count += 1 - } - i += 1 + block("mask") { + var i = 0 + var count = 0 + while (i < N) { + if ((idx(i) & Code.POSFIXINT_MASK) == 0) { + count += 1 } + i += 1 } + } - block("mask in func") { - var i = 0 - var count = 0 - while (i < N) { - if (Code.isPosFixInt(idx(i))) { - count += 1 - } - i += 1 + block("mask in func") { + var i = 0 + var count = 0 + while (i < N) { + if (Code.isPosFixInt(idx(i))) { + count += 1 } + i += 1 } + } - block("shift cmp") { - var i = 0 - var count = 0 - while (i < N) { - if ((idx(i) >>> 7) == 0) { - count += 1 - } - i += 1 + block("shift cmp") { + var i = 0 + var count = 0 + while (i < N) { + if ((idx(i) >>> 7) == 0) { + count += 1 } - + i += 1 } } } - "detect neg fix int values" in { - - for (i <- 0 until 0xe0) { - Code.isNegFixInt(i.toByte) shouldBe false - } + } - for (i <- 0xe0 until 0xFF) { - Code.isNegFixInt(i.toByte) shouldBe true - } + test("detect neg fix int values") { + for (i <- 0 until 0xe0) { + Code.isNegFixInt(i.toByte) shouldBe false } - def check[A]( - v: A, - pack: MessagePacker => Unit, - unpack: MessageUnpacker => A, - packerConfig: PackerConfig = new PackerConfig(), - unpackerConfig: UnpackerConfig = new UnpackerConfig() - ): Boolean = { - var b: Array[Byte] = null - try { - val bs = new ByteArrayOutputStream() - val packer = packerConfig.newPacker(bs) - pack(packer) - packer.close() - - b = bs.toByteArray - - val unpacker = unpackerConfig.newUnpacker(b) - val ret = unpack(unpacker) - ret shouldBe v - true - } catch { - case e: Exception => - warn(e.getMessage) - if (b != null) { - warn(s"packed data (size:${b.length}): ${toHex(b)}") - } - throw e - } + for (i <- 0xe0 until 0xFF) { + Code.isNegFixInt(i.toByte) shouldBe true } - def checkException[A]( - v: A, - pack: MessagePacker => Unit, - unpack: MessageUnpacker => A, - packerConfig: PackerConfig = new PackerConfig(), - unpaackerConfig: UnpackerConfig = new UnpackerConfig() - ): Unit = { - var b: Array[Byte] = null - val bs = new ByteArrayOutputStream() - val packer = packerConfig.newPacker(bs) + } + + private def check[A]( + v: A, + pack: MessagePacker => Unit, + unpack: MessageUnpacker => A, + packerConfig: PackerConfig = new PackerConfig(), + unpackerConfig: UnpackerConfig = new UnpackerConfig() + ): Boolean = { + var b: Array[Byte] = null + try { + val bs = new ByteArrayOutputStream() + val packer = packerConfig.newPacker(bs) pack(packer) packer.close() b = bs.toByteArray - val unpacker = unpaackerConfig.newUnpacker(b) + val unpacker = unpackerConfig.newUnpacker(b) val ret = unpack(unpacker) - - fail("cannot not reach here") + ret shouldBe v + true + } catch { + case e: Exception => + warn(e.getMessage) + if (b != null) { + warn(s"packed data (size:${b.length}): ${toHex(b)}") + } + throw e } + } - def checkOverflow[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A) { - try { - checkException[A](v, pack, unpack) - } catch { - case e: MessageIntegerOverflowException => // OK - } + private def checkException[A]( + v: A, + pack: MessagePacker => Unit, + unpack: MessageUnpacker => A, + packerConfig: PackerConfig = new PackerConfig(), + unpaackerConfig: UnpackerConfig = new UnpackerConfig() + ): Unit = { + var b: Array[Byte] = null + val bs = new ByteArrayOutputStream() + val packer = packerConfig.newPacker(bs) + pack(packer) + packer.close() + + b = bs.toByteArray + + val unpacker = unpaackerConfig.newUnpacker(b) + val ret = unpack(unpacker) + + fail("cannot not reach here") + } + + private def checkOverflow[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A) { + try { + checkException[A](v, pack, unpack) + } catch { + case e: MessageIntegerOverflowException => // OK } + } - "pack/unpack primitive values" taggedAs ("prim") in { - forAll { (v: Boolean) => - check(v, _.packBoolean(v), _.unpackBoolean) - } - forAll { (v: Byte) => - check(v, _.packByte(v), _.unpackByte) - } - forAll { (v: Short) => - check(v, _.packShort(v), _.unpackShort) - } - forAll { (v: Int) => - check(v, _.packInt(v), _.unpackInt) - } - forAll { (v: Float) => - check(v, _.packFloat(v), _.unpackFloat) - } - forAll { (v: Long) => - check(v, _.packLong(v), _.unpackLong) - } - forAll { (v: Double) => - check(v, _.packDouble(v), _.unpackDouble) - } - check(null, _.packNil, { unpacker => - unpacker.unpackNil(); null - }) + test("pack/unpack primitive values") { + forAll { (v: Boolean) => + check(v, _.packBoolean(v), _.unpackBoolean) + } + forAll { (v: Byte) => + check(v, _.packByte(v), _.unpackByte) + } + forAll { (v: Short) => + check(v, _.packShort(v), _.unpackShort) + } + forAll { (v: Int) => + check(v, _.packInt(v), _.unpackInt) } + forAll { (v: Float) => + check(v, _.packFloat(v), _.unpackFloat) + } + forAll { (v: Long) => + check(v, _.packLong(v), _.unpackLong) + } + forAll { (v: Double) => + check(v, _.packDouble(v), _.unpackDouble) + } + check(null, _.packNil, { unpacker => + unpacker.unpackNil(); null + }) + } - "skipping a nil value" taggedAs ("try") in { - check(true, _.packNil, _.tryUnpackNil) - check(false, { packer => - packer.packString("val") - }, { unpacker => - unpacker.tryUnpackNil() - }) - check("val", { packer => - packer.packString("val") - }, { unpacker => - unpacker.tryUnpackNil(); unpacker.unpackString() - }) - check("val", { packer => - packer.packNil(); packer.packString("val") - }, { unpacker => - unpacker.tryUnpackNil(); unpacker.unpackString() - }) - try { - checkException(null, { _ => - }, _.tryUnpackNil) - } catch { - case e: MessageInsufficientBufferException => // OK - } + test("skipping a nil value") { + check(true, _.packNil, _.tryUnpackNil) + check(false, { packer => + packer.packString("val") + }, { unpacker => + unpacker.tryUnpackNil() + }) + check("val", { packer => + packer.packString("val") + }, { unpacker => + unpacker.tryUnpackNil(); unpacker.unpackString() + }) + check("val", { packer => + packer.packNil(); packer.packString("val") + }, { unpacker => + unpacker.tryUnpackNil(); unpacker.unpackString() + }) + try { + checkException(null, { _ => + }, _.tryUnpackNil) + } catch { + case e: MessageInsufficientBufferException => // OK } + } - "pack/unpack integer values" taggedAs ("int") in { - val sampleData = Seq[Long](Int.MinValue.toLong - - 10, - -65535, - -8191, - -1024, - -255, - -127, - -63, - -31, - -15, - -7, - -3, - -1, - 0, - 2, - 4, - 8, - 16, - 32, - 64, - 128, - 256, - 1024, - 8192, - 65536, - Int.MaxValue.toLong + 10) - for (v <- sampleData) { - check(v, _.packLong(v), _.unpackLong) - - if (v.isValidInt) { - val vi = v.toInt - check(vi, _.packInt(vi), _.unpackInt) - } else { - checkOverflow(v, _.packLong(v), _.unpackInt) - } + test("pack/unpack integer values") { + val sampleData = Seq[Long](Int.MinValue.toLong - + 10, + -65535, + -8191, + -1024, + -255, + -127, + -63, + -31, + -15, + -7, + -3, + -1, + 0, + 2, + 4, + 8, + 16, + 32, + 64, + 128, + 256, + 1024, + 8192, + 65536, + Int.MaxValue.toLong + 10) + for (v <- sampleData) { + check(v, _.packLong(v), _.unpackLong) + + if (v.isValidInt) { + val vi = v.toInt + check(vi, _.packInt(vi), _.unpackInt) + } else { + checkOverflow(v, _.packLong(v), _.unpackInt) + } + + if (v.isValidShort) { + val vi = v.toShort + check(vi, _.packShort(vi), _.unpackShort) + } else { + checkOverflow(v, _.packLong(v), _.unpackShort) + } + + if (v.isValidByte) { + val vi = v.toByte + check(vi, _.packByte(vi), _.unpackByte) + } else { + checkOverflow(v, _.packLong(v), _.unpackByte) + } - if (v.isValidShort) { - val vi = v.toShort - check(vi, _.packShort(vi), _.unpackShort) - } else { - checkOverflow(v, _.packLong(v), _.unpackShort) - } + } - if (v.isValidByte) { - val vi = v.toByte - check(vi, _.packByte(vi), _.unpackByte) - } else { - checkOverflow(v, _.packLong(v), _.unpackByte) - } + } - } + test("pack/unpack BigInteger") { + forAll { (a: Long) => + val v = BigInteger.valueOf(a) + check(v, _.packBigInteger(v), _.unpackBigInteger) + } + for (bi <- Seq(BigInteger.valueOf(Long.MaxValue).add(BigInteger.valueOf(1)))) { + check(bi, _.packBigInteger(bi), _.unpackBigInteger()) } - "pack/unpack BigInteger" taggedAs ("bi") in { - forAll { (a: Long) => - val v = BigInteger.valueOf(a) - check(v, _.packBigInteger(v), _.unpackBigInteger) + for (bi <- Seq(BigInteger.valueOf(Long.MaxValue).shiftLeft(10))) { + try { + checkException(bi, _.packBigInteger(bi), _.unpackBigInteger()) + fail("cannot reach here") + } catch { + case e: IllegalArgumentException => // OK } + } - for (bi <- Seq(BigInteger.valueOf(Long.MaxValue).add(BigInteger.valueOf(1)))) { - check(bi, _.packBigInteger(bi), _.unpackBigInteger()) - } + } - for (bi <- Seq(BigInteger.valueOf(Long.MaxValue).shiftLeft(10))) { - try { - checkException(bi, _.packBigInteger(bi), _.unpackBigInteger()) - fail("cannot reach here") - } catch { - case e: IllegalArgumentException => // OK - } - } + test("pack/unpack strings") { + val utf8Strings = Arbitrary.arbitrary[String].suchThat(isValidUTF8 _) + utf8Strings.map { v => + check(v, _.packString(v), _.unpackString) + } + } + test("pack/unpack large strings") { + // Large string + val strLen = Seq(1000, 2000, 10000, 50000, 100000, 500000) + for (l <- strLen) { + val v: String = + Iterator.continually(Random.nextString(l * 10)).find(isValidUTF8).get + check(v, _.packString(v), _.unpackString) } + } - "pack/unpack strings" taggedAs ("string") in { - val utf8Strings = Arbitrary.arbitrary[String].suchThat(isValidUTF8 _) - utf8Strings.map { v => - check(v, _.packString(v), _.unpackString) + test("report errors when packing/unpacking malformed strings") { + // TODO produce malformed utf-8 strings in Java8" + pending + // Create 100 malformed UTF8 Strings + val r = new Random(0) + val malformedStrings = Iterator + .continually { + val b = new Array[Byte](10) + r.nextBytes(b) + b + } + .filter(b => !isValidUTF8(new String(b))) + .take(100) + + for (malformedBytes <- malformedStrings) { + // Pack tests + val malformed = new String(malformedBytes) + try { + checkException(malformed, _.packString(malformed), _.unpackString()) + } catch { + case e: MessageStringCodingException => // OK } - } - "pack/unpack large strings" taggedAs ("large-string") in { - // Large string - val strLen = Seq(1000, 2000, 10000, 50000, 100000, 500000) - for (l <- strLen) { - val v: String = - Iterator.continually(Random.nextString(l * 10)).find(isValidUTF8).get - check(v, _.packString(v), _.unpackString) + try { + checkException(malformed, { packer => + packer.packRawStringHeader(malformedBytes.length) + packer.writePayload(malformedBytes) + }, _.unpackString()) + } catch { + case e: MessageStringCodingException => // OK } } + } - "report errors when packing/unpacking malformed strings" taggedAs ("malformed") in { - // TODO produce malformed utf-8 strings in Java8" - pending - // Create 100 malformed UTF8 Strings - val r = new Random(0) - val malformedStrings = Iterator - .continually { - val b = new Array[Byte](10) - r.nextBytes(b) - b - } - .filter(b => !isValidUTF8(new String(b))) - .take(100) - - for (malformedBytes <- malformedStrings) { - // Pack tests - val malformed = new String(malformedBytes) - try { - checkException(malformed, _.packString(malformed), _.unpackString()) - } catch { - case e: MessageStringCodingException => // OK - } + test("report errors when packing/unpacking strings that contain unmappable characters") { - try { - checkException(malformed, { packer => - packer.packRawStringHeader(malformedBytes.length) - packer.writePayload(malformedBytes) - }, _.unpackString()) - } catch { - case e: MessageStringCodingException => // OK - } - } - } + val unmappable = Array[Byte](0xfc.toByte, 0x0a.toByte) + //val unmappableChar = Array[Char](new Character(0xfc0a).toChar) - "report errors when packing/unpacking strings that contain unmappable characters" taggedAs ("unmap") in { + // Report error on unmappable character + val unpackerConfig = new UnpackerConfig() + .withActionOnMalformedString(CodingErrorAction.REPORT) + .withActionOnUnmappableString(CodingErrorAction.REPORT) - val unmappable = Array[Byte](0xfc.toByte, 0x0a.toByte) - //val unmappableChar = Array[Char](new Character(0xfc0a).toChar) + for (bytes <- Seq(unmappable)) { + try { + checkException(bytes, { packer => + packer.packRawStringHeader(bytes.length) + packer.writePayload(bytes) + }, _.unpackString(), new PackerConfig(), unpackerConfig) + } catch { + case e: MessageStringCodingException => // OK + } + } + } - // Report error on unmappable character - val unpackerConfig = new UnpackerConfig() - .withActionOnMalformedString(CodingErrorAction.REPORT) - .withActionOnUnmappableString(CodingErrorAction.REPORT) + test("pack/unpack binary") { + forAll { (v: Array[Byte]) => + check( + v, { packer => + packer.packBinaryHeader(v.length); packer.writePayload(v) + }, { unpacker => + val len = unpacker.unpackBinaryHeader() + val out = new Array[Byte](len) + unpacker.readPayload(out, 0, len) + out + } + ) + } - for (bytes <- Seq(unmappable)) { - When("unpacking") - try { - checkException(bytes, { packer => - packer.packRawStringHeader(bytes.length) - packer.writePayload(bytes) - }, _.unpackString(), new PackerConfig(), unpackerConfig) - } catch { - case e: MessageStringCodingException => // OK + val len = Seq(1000, 2000, 10000, 50000, 100000, 500000) + for (l <- len) { + val v = new Array[Byte](l) + Random.nextBytes(v) + check( + v, { packer => + packer.packBinaryHeader(v.length); packer.writePayload(v) + }, { unpacker => + val len = unpacker.unpackBinaryHeader() + val out = new Array[Byte](len) + unpacker.readPayload(out, 0, len) + out } - } + ) } + } - "pack/unpack binary" taggedAs ("binary") in { - forAll { (v: Array[Byte]) => - check( - v, { packer => - packer.packBinaryHeader(v.length); packer.writePayload(v) - }, { unpacker => - val len = unpacker.unpackBinaryHeader() - val out = new Array[Byte](len) - unpacker.readPayload(out, 0, len) - out - } - ) - } + val testHeaderLength = Seq(1, 2, 4, 8, 16, 17, 32, 64, 255, 256, 1000, 2000, 10000, 50000, 100000, 500000) - val len = Seq(1000, 2000, 10000, 50000, 100000, 500000) - for (l <- len) { - val v = new Array[Byte](l) - Random.nextBytes(v) - check( - v, { packer => - packer.packBinaryHeader(v.length); packer.writePayload(v) - }, { unpacker => - val len = unpacker.unpackBinaryHeader() - val out = new Array[Byte](len) - unpacker.readPayload(out, 0, len) - out + test("pack/unpack arrays") { + forAll { (v: Array[Int]) => + check( + v, { packer => + packer.packArrayHeader(v.length) + v.map(packer.packInt(_)) + }, { unpacker => + val len = unpacker.unpackArrayHeader() + val out = new Array[Int](len) + for (i <- 0 until v.length) { + out(i) = unpacker.unpackInt } - ) - } + out + } + ) } - val testHeaderLength = Seq(1, 2, 4, 8, 16, 17, 32, 64, 255, 256, 1000, 2000, 10000, 50000, 100000, 500000) - - "pack/unpack arrays" taggedAs ("array") in { - forAll { (v: Array[Int]) => - check( - v, { packer => - packer.packArrayHeader(v.length) - v.map(packer.packInt(_)) - }, { unpacker => - val len = unpacker.unpackArrayHeader() - val out = new Array[Int](len) - for (i <- 0 until v.length) { - out(i) = unpacker.unpackInt - } - out - } - ) - } + for (l <- testHeaderLength) { + check(l, _.packArrayHeader(l), _.unpackArrayHeader()) + } - for (l <- testHeaderLength) { - check(l, _.packArrayHeader(l), _.unpackArrayHeader()) - } + try { + checkException(0, _.packArrayHeader(-1), _.unpackArrayHeader) + } catch { + case e: IllegalArgumentException => // OK + } - try { - checkException(0, _.packArrayHeader(-1), _.unpackArrayHeader) - } catch { - case e: IllegalArgumentException => // OK - } + } - } + test("pack/unpack maps") { + forAll { (v: Array[Int]) => + val m = v.map(i => (i, i.toString)).toSeq - "pack/unpack maps" taggedAs ("map") in { - forAll { (v: Array[Int]) => - val m = v.map(i => (i, i.toString)) - - check( - m, { packer => - packer.packMapHeader(v.length) - m.map { - case (k: Int, v: String) => - packer.packInt(k) - packer.packString(v) - } - }, { unpacker => - val len = unpacker.unpackMapHeader() - val b = Seq.newBuilder[(Int, String)] - for (i <- 0 until len) { - b += ((unpacker.unpackInt, unpacker.unpackString)) - } - b.result + check( + m, { packer => + packer.packMapHeader(v.length) + m.map { + case (k: Int, v: String) => + packer.packInt(k) + packer.packString(v) } - ) - } - - for (l <- testHeaderLength) { - check(l, _.packMapHeader(l), _.unpackMapHeader()) - } + }, { unpacker => + val len = unpacker.unpackMapHeader() + val b = Seq.newBuilder[(Int, String)] + for (i <- 0 until len) { + b += ((unpacker.unpackInt, unpacker.unpackString)) + } + b.result + } + ) + } - try { - checkException(0, _.packMapHeader(-1), _.unpackMapHeader) - } catch { - case e: IllegalArgumentException => // OK - } + for (l <- testHeaderLength) { + check(l, _.packMapHeader(l), _.unpackMapHeader()) + } + try { + checkException(0, _.packMapHeader(-1), _.unpackMapHeader) + } catch { + case e: IllegalArgumentException => // OK } - "pack/unpack extension types" taggedAs ("ext") in { - forAll { (dataLen: Int, tpe: Byte) => - val l = Math.abs(dataLen) - l >= 0 ==> { - val ext = - new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(tpe), l) - check(ext, _.packExtensionTypeHeader(ext.getType, ext.getLength), _.unpackExtensionTypeHeader()) - } - } + } - for (l <- testHeaderLength) { - val ext = new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(Random.nextInt(128)), l) + test("pack/unpack extension types") { + forAll { (dataLen: Int, tpe: Byte) => + val l = Math.abs(dataLen) + l >= 0 ==> { + val ext = + new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(tpe), l) check(ext, _.packExtensionTypeHeader(ext.getType, ext.getLength), _.unpackExtensionTypeHeader()) } + } + for (l <- testHeaderLength) { + val ext = new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(Random.nextInt(128)), l) + check(ext, _.packExtensionTypeHeader(ext.getType, ext.getLength), _.unpackExtensionTypeHeader()) } - "pack/unpack maps in lists" in { - val aMap = List(Map("f" -> "x")) + } - check( - aMap, { packer => - packer.packArrayHeader(aMap.size) - for (m <- aMap) { - packer.packMapHeader(m.size) - for ((k, v) <- m) { - packer.packString(k) - packer.packString(v) - } + test("pack/unpack maps in lists") { + val aMap = List(Map("f" -> "x")) + + check( + aMap, { packer => + packer.packArrayHeader(aMap.size) + for (m <- aMap) { + packer.packMapHeader(m.size) + for ((k, v) <- m) { + packer.packString(k) + packer.packString(v) } - }, { unpacker => - val v = new Variable() - unpacker.unpackValue(v) - import scala.collection.JavaConverters._ - v.asArrayValue().asScala - .map { m => - val mv = m.asMapValue() - val kvs = mv.getKeyValueArray - - kvs - .grouped(2) - .map({ kvp: Array[Value] => - val k = kvp(0) - val v = kvp(1) - - (k.asStringValue().asString, v.asStringValue().asString) - }) - .toMap - } - .toList } - ) + }, { unpacker => + val v = new Variable() + unpacker.unpackValue(v) + import scala.collection.JavaConverters._ + v.asArrayValue().asScala + .map { m => + val mv = m.asMapValue() + val kvs = mv.getKeyValueArray + + kvs + .grouped(2) + .map({ kvp: Array[Value] => + val k = kvp(0) + val v = kvp(1) + + (k.asStringValue().asString, v.asStringValue().asString) + }) + .toMap + } + .toList + } + ) + } + + test("pack/unpack timestamp values") { + val posLong = Gen.chooseNum[Long](-31557014167219200L, 31556889864403199L) + val posInt = Gen.chooseNum(0, 1000000000 - 1) // NANOS_PER_SECOND + forAll(posLong, posInt) { (second: Long, nano: Int) => + val v = Instant.ofEpochSecond(second, nano) + check(v, { _.packTimestamp(v) }, { _.unpackTimestamp() }) + } + // Using different insterfaces + forAll(posLong, posInt) { (second: Long, nano: Int) => + val v = Instant.ofEpochSecond(second, nano) + check(v, { _.packTimestamp(second, nano) }, { _.unpackTimestamp() }) + } + val secLessThan34bits = Gen.chooseNum[Long](0, 1L << 34) + forAll(secLessThan34bits, posInt) { (second: Long, nano: Int) => + val v = Instant.ofEpochSecond(second, nano) + check(v, _.packTimestamp(v), _.unpackTimestamp()) + } + forAll(secLessThan34bits, posInt) { (second: Long, nano: Int) => + val v = Instant.ofEpochSecond(second, nano) + check(v, _.packTimestamp(second, nano), _.unpackTimestamp()) } + // Corner-cases around uint32 boundaries + for (v <- Seq( + Instant.ofEpochSecond(Instant.now().getEpochSecond, 123456789L), // uint32 nanoseq (out of int32 range) + Instant.ofEpochSecond(-1302749144L, 0), // 1928-09-19T21:14:16Z + Instant.ofEpochSecond(-747359729L, 0), // 1946-04-27T00:04:31Z + Instant.ofEpochSecond(4257387427L, 0) // 2104-11-29T07:37:07Z + )) { + check(v, _.packTimestamp(v), _.unpackTimestamp()) + } + } + + test("pack/unpack timestamp in millis") { + val posLong = Gen.chooseNum[Long](-31557014167219200L, 31556889864403199L) + forAll(posLong) { (millis: Long) => + val v = Instant.ofEpochMilli(millis) + check(v, { _.packTimestamp(millis) }, { _.unpackTimestamp() }) + } } - "MessagePack.PackerConfig" should { - "be immutable" in { + test("MessagePack.PackerConfig") { + test("should be immutable") { val a = new MessagePack.PackerConfig() val b = a.withBufferSize(64 * 1024) a.equals(b) shouldBe false } - "implement equals" in { + test("should implement equals") { val a = new MessagePack.PackerConfig() val b = new MessagePack.PackerConfig() a.equals(b) shouldBe true @@ -602,14 +641,14 @@ class MessagePackTest extends MessagePackSpec { } } - "MessagePack.UnpackerConfig" should { - "be immutable" in { + test("MessagePack.UnpackerConfig") { + test("should be immutable") { val a = new MessagePack.UnpackerConfig() val b = a.withBufferSize(64 * 1024) a.equals(b) shouldBe false } - "implement equals" in { + test("implement equals") { val a = new MessagePack.UnpackerConfig() val b = new MessagePack.UnpackerConfig() a.equals(b) shouldBe true diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index 5024963fd..096a811b4 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -15,21 +15,21 @@ // package org.msgpack.core -import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream} - -import org.msgpack.core.MessagePack.{UnpackerConfig, PackerConfig} +import org.msgpack.core.MessagePack.PackerConfig import org.msgpack.core.buffer.{ChannelBufferOutput, OutputStreamBufferOutput} import org.msgpack.value.ValueFactory -import xerial.core.io.IOUtil +import wvlet.airspec.AirSpec +import wvlet.log.io.IOUtil.withResource +import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream} import scala.util.Random /** * */ -class MessagePackerTest extends MessagePackSpec { +class MessagePackerTest extends AirSpec with Benchmark { - def verifyIntSeq(answer: Array[Int], packed: Array[Byte]) { + private def verifyIntSeq(answer: Array[Int], packed: Array[Byte]) { val unpacker = MessagePack.newDefaultUnpacker(packed) val b = Array.newBuilder[Int] while (unpacker.hasNext) { @@ -40,27 +40,27 @@ class MessagePackerTest extends MessagePackSpec { result shouldBe answer } - def createTempFile = { + private def createTempFile = { val f = File.createTempFile("msgpackTest", "msgpack") f.deleteOnExit f } - def createTempFileWithOutputStream = { + private def createTempFileWithOutputStream = { val f = createTempFile val out = new FileOutputStream(f) (f, out) } - def createTempFileWithChannel = { + private def createTempFileWithChannel = { val (f, out) = createTempFileWithOutputStream val ch = out.getChannel (f, ch) } - "MessagePacker" should { + test("MessagePacker") { - "reset the internal states" in { + test("reset the internal states") { val intSeq = (0 until 100).map(i => Random.nextInt).toArray val b = new ByteArrayOutputStream @@ -86,13 +86,12 @@ class MessagePackerTest extends MessagePackSpec { verifyIntSeq(intSeq3, b3.toByteArray) } - "improve the performance via reset method" taggedAs ("reset") in { - + test("improve the performance via reset method") { val N = 1000 val t = time("packer", repeat = 10) { block("no-buffer-reset") { val out = new ByteArrayOutputStream - IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => + withResource(MessagePack.newDefaultPacker(out)) { packer => for (i <- 0 until N) { val outputStream = new ByteArrayOutputStream() packer @@ -105,7 +104,7 @@ class MessagePackerTest extends MessagePackSpec { block("buffer-reset") { val out = new ByteArrayOutputStream - IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => + withResource(MessagePack.newDefaultPacker(out)) { packer => val bufferOut = new OutputStreamBufferOutput(new ByteArrayOutputStream()) for (i <- 0 until N) { @@ -119,10 +118,10 @@ class MessagePackerTest extends MessagePackSpec { } } - t("buffer-reset").averageWithoutMinMax should be <= t("no-buffer-reset").averageWithoutMinMax + t("buffer-reset").averageWithoutMinMax <= t("no-buffer-reset").averageWithoutMinMax shouldBe true } - "pack larger string array than byte buf" taggedAs ("larger-string-array-than-byte-buf") in { + test("pack larger string array than byte buf") { // Based on https://github.com/msgpack/msgpack-java/issues/154 def test(bufferSize: Int, stringSize: Int): Boolean = { @@ -148,7 +147,7 @@ class MessagePackerTest extends MessagePackSpec { } } - "reset OutputStreamBufferOutput" in { + test("reset OutputStreamBufferOutput") { val (f0, out0) = createTempFileWithOutputStream val packer = MessagePack.newDefaultPacker(out0) packer.packInt(99) @@ -178,7 +177,7 @@ class MessagePackerTest extends MessagePackSpec { up1.close } - "reset ChannelBufferOutput" in { + test("reset ChannelBufferOutput") { val (f0, out0) = createTempFileWithChannel val packer = MessagePack.newDefaultPacker(out0) packer.packInt(99) @@ -208,7 +207,7 @@ class MessagePackerTest extends MessagePackSpec { up1.close } - "pack a lot of String within expected time" in { + test("pack a lot of String within expected time") { val count = 20000 def measureDuration(outputStream: java.io.OutputStream) = { @@ -231,14 +230,14 @@ class MessagePackerTest extends MessagePackSpec { measureDuration(fileOutput) } } - t("file-output-stream").averageWithoutMinMax shouldBe <(t("byte-array-output-stream").averageWithoutMinMax * 5) + t("file-output-stream").averageWithoutMinMax < (t("byte-array-output-stream").averageWithoutMinMax * 5) shouldBe true } } - "compute totalWrittenBytes" in { + test("compute totalWrittenBytes") { val out = new ByteArrayOutputStream val packerTotalWrittenBytes = - IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => + withResource(MessagePack.newDefaultPacker(out)) { packer => packer .packByte(0) // 1 .packBoolean(true) // 1 @@ -254,7 +253,7 @@ class MessagePackerTest extends MessagePackSpec { out.toByteArray.length shouldBe packerTotalWrittenBytes } - "support read-only buffer" taggedAs ("read-only") in { + test("support read-only buffer") { val payload = Array[Byte](1) val out = new ByteArrayOutputStream() val packer = MessagePack @@ -264,7 +263,7 @@ class MessagePackerTest extends MessagePackSpec { .close() } - "pack small string with STR8" in { + test("pack small string with STR8") { val packer = new PackerConfig().newBufferPacker() packer.packString("Hello. This is a string longer than 32 characters!") val b = packer.toByteArray @@ -274,7 +273,7 @@ class MessagePackerTest extends MessagePackSpec { f shouldBe MessageFormat.STR8 } - "be able to disable STR8 for backward compatibility" in { + test("be able to disable STR8 for backward compatibility") { val config = new PackerConfig() .withStr8FormatSupport(false) @@ -285,7 +284,7 @@ class MessagePackerTest extends MessagePackSpec { f shouldBe MessageFormat.STR16 } - "be able to disable STR8 when using CharsetEncoder" in { + test("be able to disable STR8 when using CharsetEncoder") { val config = new PackerConfig() .withStr8FormatSupport(false) .withSmallStringOptimizationThreshold(0) // Disable small string optimization @@ -294,19 +293,19 @@ class MessagePackerTest extends MessagePackSpec { packer.packString("small string") val unpacker = MessagePack.newDefaultUnpacker(packer.toByteArray) val f = unpacker.getNextFormat - f shouldNot be(MessageFormat.STR8) + f shouldNotBe MessageFormat.STR8 val s = unpacker.unpackString() s shouldBe "small string" } - "write raw binary" taggedAs ("raw-binary") in { + test("write raw binary") { val packer = new MessagePack.PackerConfig().newBufferPacker() val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) packer.writePayload(msg) } - "append raw binary" taggedAs ("append-raw-binary") in { + test("append raw binary") { val packer = new MessagePack.PackerConfig().newBufferPacker() val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index c2c738515..5ae597f27 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -15,14 +15,16 @@ // package org.msgpack.core -import java.io._ -import java.nio.ByteBuffer -import java.util.Collections - +import org.msgpack.core.MessagePackSpec.{createMessagePackData, toHex} import org.msgpack.core.buffer._ import org.msgpack.value.ValueType -import xerial.core.io.IOUtil._ +import wvlet.airspec.AirSpec +import wvlet.log.LogSupport +import wvlet.log.io.IOUtil.withResource +import java.io._ +import java.nio.ByteBuffer +import java.util.Collections import scala.collection.JavaConverters._ import scala.util.Random @@ -43,12 +45,12 @@ object MessageUnpackerTest { } } -import MessageUnpackerTest._ +import org.msgpack.core.MessageUnpackerTest._ -class MessageUnpackerTest extends MessagePackSpec { +class MessageUnpackerTest extends AirSpec with Benchmark { - val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] - def testData: Array[Byte] = { + private val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] + private def testData: Array[Byte] = { val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) @@ -68,9 +70,9 @@ class MessageUnpackerTest extends MessagePackSpec { arr } - val intSeq = (for (i <- 0 until 100) yield Random.nextInt()).toArray[Int] + private val intSeq = (for (i <- 0 until 100) yield Random.nextInt()).toArray[Int] - def testData2: Array[Byte] = { + private def testData2: Array[Byte] = { val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out); @@ -86,7 +88,7 @@ class MessageUnpackerTest extends MessagePackSpec { arr } - def write(packer: MessagePacker, r: Random) { + private def write(packer: MessagePacker, r: Random) { val tpeIndex = Iterator .continually(r.nextInt(MessageFormat.values().length)) .find(_ != MessageFormat.NEVER_USED.ordinal()) @@ -142,7 +144,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } - def testData3(N: Int): Array[Byte] = { + private def testData3(N: Int): Array[Byte] = { val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) @@ -160,7 +162,7 @@ class MessageUnpackerTest extends MessagePackSpec { arr } - def readValue(unpacker: MessageUnpacker) { + private def readValue(unpacker: MessageUnpacker) { val f = unpacker.getNextFormat() f.getValueType match { case ValueType.ARRAY => @@ -181,7 +183,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } - def createTempFile = { + private def createTempFile = { val f = File.createTempFile("msgpackTest", "msgpack") f.deleteOnExit val p = MessagePack.newDefaultPacker(new FileOutputStream(f)) @@ -190,12 +192,12 @@ class MessageUnpackerTest extends MessagePackSpec { f } - def checkFile(u: MessageUnpacker) = { + private def checkFile(u: MessageUnpacker) = { u.unpackInt shouldBe 99 u.hasNext shouldBe false } - def unpackers(data: Array[Byte]): Seq[MessageUnpacker] = { + private def unpackers(data: Array[Byte]): Seq[MessageUnpacker] = { val bb = ByteBuffer.allocate(data.length) val db = ByteBuffer.allocateDirect(data.length) bb.put(data).flip() @@ -210,7 +212,7 @@ class MessageUnpackerTest extends MessagePackSpec { builder.result() } - def unpackerCollectionWithVariousBuffers(data: Array[Byte], chunkSize: Int): Seq[MessageUnpacker] = { + private def unpackerCollectionWithVariousBuffers(data: Array[Byte], chunkSize: Int): Seq[MessageUnpacker] = { val seqBytes = Seq.newBuilder[MessageBufferInput] val seqByteBuffers = Seq.newBuilder[MessageBufferInput] val seqDirectBuffers = Seq.newBuilder[MessageBufferInput] @@ -238,9 +240,9 @@ class MessageUnpackerTest extends MessagePackSpec { builder.result() } - "MessageUnpacker" should { + test("MessageUnpacker") { - "parse message packed data" taggedAs ("unpack") in { + test("parse message packed data") { val arr = testData for (unpacker <- unpackers(arr)) { @@ -255,7 +257,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "skip reading values" in { + test("skip reading values") { for (unpacker <- unpackers(testData)) { var skipCount = 0 @@ -269,7 +271,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "compare skip performance" taggedAs ("skip") in { + test("compare skip performance") { val N = 10000 val data = testData3(N) @@ -297,8 +299,7 @@ class MessageUnpackerTest extends MessagePackSpec { } - "parse int data" in { - + test("parse int data") { debug(intSeq.mkString(", ")) for (unpacker <- unpackers(testData2)) { @@ -319,15 +320,13 @@ class MessageUnpackerTest extends MessagePackSpec { } } - ib.result shouldBe intSeq + ib.result shouldBe intSeq.toSeq unpacker.getTotalReadBytes shouldBe testData2.length } - } - "read data at the buffer boundary" taggedAs ("boundary") in { - - trait SplitTest { + test("read data at the buffer boundary") { + trait SplitTest extends LogSupport { val data: Array[Byte] def run { for (unpacker <- unpackers(data)) { @@ -362,7 +361,7 @@ class MessageUnpackerTest extends MessagePackSpec { new SplitTest { val data = testData3(30) }.run } - "read integer at MessageBuffer boundaries" taggedAs ("integer-buffer-boundary") in { + test("read integer at MessageBuffer boundaries") { val packer = MessagePack.newDefaultBufferPacker() (0 until 1170).foreach { i => packer.packLong(0x0011223344556677L) @@ -385,7 +384,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "read string at MessageBuffer boundaries" taggedAs ("string-buffer-boundary") in { + test("read string at MessageBuffer boundaries") { val packer = MessagePack.newDefaultBufferPacker() (0 until 1170).foreach { i => packer.packString("hello world") @@ -408,7 +407,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "be faster than msgpack-v6 skip" taggedAs ("cmp-skip") in { + test("be faster than msgpack-v6 skip") { trait Fixture { val unpacker: MessageUnpacker @@ -434,7 +433,6 @@ class MessageUnpackerTest extends MessagePackSpec { val t = time("skip performance", repeat = N) { block("v6") { - import org.msgpack.`type`.{ValueType => ValueTypeV6} val v6 = new org.msgpack.MessagePack() val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(data)) var count = 0 @@ -466,15 +464,16 @@ class MessageUnpackerTest extends MessagePackSpec { } } - t("v7-array").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax - t("v7-array-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax - if (!universal) - t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax + t("v7-array").averageWithoutMinMax <= t("v6").averageWithoutMinMax shouldBe true + t("v7-array-buffer").averageWithoutMinMax <= t("v6").averageWithoutMinMax shouldBe true + if (!universal) { + t("v7-direct-buffer").averageWithoutMinMax <= t("v6").averageWithoutMinMax shouldBe true + } } import org.msgpack.`type`.{ValueType => ValueTypeV6} - "be faster than msgpack-v6 read value" taggedAs ("cmp-unpack") in { + test("be faster than msgpack-v6 read value") { def readValueV6(unpacker: org.msgpack.unpacker.MessagePackUnpacker) { val vt = unpacker.getNextType() @@ -598,12 +597,12 @@ class MessageUnpackerTest extends MessagePackSpec { if (t("v7-array-buffer").averageWithoutMinMax > t("v6").averageWithoutMinMax) { warn(s"v7-array-buffer ${t("v7-array-buffer").averageWithoutMinMax} is slower than v6 ${t("v6").averageWithoutMinMax}") } - if (!universal) - t("v7-direct-buffer").averageWithoutMinMax should be <= t("v6").averageWithoutMinMax - + if (!universal) { + t("v7-direct-buffer").averageWithoutMinMax <= t("v6").averageWithoutMinMax shouldBe true + } } - "be faster for reading binary than v6" taggedAs ("cmp-binary") in { + test("be faster for reading binary than v6") { val bos = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(bos) @@ -702,37 +701,37 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "read payload as a reference" taggedAs ("ref") in { + test("read payload as a reference") { val dataSizes = Seq(0, 1, 5, 8, 16, 32, 128, 256, 1024, 2000, 10000, 100000) for (s <- dataSizes) { - When(f"data size is $s%,d") - val data = new Array[Byte](s) - Random.nextBytes(data) - val b = new ByteArrayOutputStream() - val packer = MessagePack.newDefaultPacker(b) - packer.packBinaryHeader(s) - packer.writePayload(data) - packer.close() - - for (unpacker <- unpackers(b.toByteArray)) { - val len = unpacker.unpackBinaryHeader() - len shouldBe s - val ref = unpacker.readPayloadAsReference(len) - unpacker.close() - ref.size() shouldBe s - val stored = new Array[Byte](len) - ref.getBytes(0, stored, 0, len) + test(f"data size is $s%,d") { + val data = new Array[Byte](s) + Random.nextBytes(data) + val b = new ByteArrayOutputStream() + val packer = MessagePack.newDefaultPacker(b) + packer.packBinaryHeader(s) + packer.writePayload(data) + packer.close() + + for (unpacker <- unpackers(b.toByteArray)) { + val len = unpacker.unpackBinaryHeader() + len shouldBe s + val ref = unpacker.readPayloadAsReference(len) + unpacker.close() + ref.size() shouldBe s + val stored = new Array[Byte](len) + ref.getBytes(0, stored, 0, len) - stored shouldBe data + stored shouldBe data + } } } - } - "reset the internal states" taggedAs ("reset") in { + test("reset the internal states") { val data = intSeq val b = createMessagePackData(packer => data foreach packer.packInt) @@ -769,7 +768,7 @@ class MessageUnpackerTest extends MessagePackSpec { } - "improve the performance via reset method" taggedAs ("reset-arr") in { + test("improve the performance via reset method") { val out = new ByteArrayOutputStream val packer = MessagePack.newDefaultPacker(out) @@ -821,7 +820,7 @@ class MessageUnpackerTest extends MessagePackSpec { // t("reuse-array-input").averageWithoutMinMax should be <= t("no-buffer-reset").averageWithoutMinMax } - "reset ChannelBufferInput" in { + test("reset ChannelBufferInput") { val f0 = createTempFile val u = MessagePack.newDefaultUnpacker(new FileInputStream(f0).getChannel) checkFile(u) @@ -833,7 +832,7 @@ class MessageUnpackerTest extends MessagePackSpec { u.close } - "reset InputStreamBufferInput" in { + test("reset InputStreamBufferInput") { val f0 = createTempFile val u = MessagePack.newDefaultUnpacker(new FileInputStream(f0)) checkFile(u) @@ -845,7 +844,7 @@ class MessageUnpackerTest extends MessagePackSpec { u.close } - "unpack large string data" taggedAs ("large-string") in { + test("unpack large string data") { def createLargeData(stringLength: Int): Array[Byte] = { val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) @@ -874,7 +873,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "unpack string crossing end of buffer" in { + test("unpack string crossing end of buffer") { def check(expected: String, strLen: Int) = { val bytes = new Array[Byte](strLen) val out = new ByteArrayOutputStream @@ -910,7 +909,7 @@ class MessageUnpackerTest extends MessagePackSpec { } } - "read value length at buffer boundary" taggedAs ("number-boundary") in { + test("read value length at buffer boundary") { val input = new SplitMessageBufferInput( Array(Array[Byte](MessagePack.Code.STR16), Array[Byte](0x00), diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala index ed79ef6ab..42872fc44 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala @@ -16,14 +16,16 @@ package org.msgpack.core.buffer import akka.util.ByteString -import org.msgpack.core.{MessagePack, MessagePackSpec, MessageUnpacker} +import org.msgpack.core.MessagePack +import org.msgpack.core.MessagePackSpec.createMessagePackData +import wvlet.airspec.AirSpec -class ByteStringTest extends MessagePackSpec { +class ByteStringTest extends AirSpec { - val unpackedString = "foo" - val byteString = ByteString(createMessagePackData(_.packString(unpackedString))) + private val unpackedString = "foo" + private val byteString = ByteString(createMessagePackData(_.packString(unpackedString))) - def unpackString(messageBuffer: MessageBuffer) = { + private def unpackString(messageBuffer: MessageBuffer) = { val input = new MessageBufferInput { private var isRead = false @@ -41,12 +43,14 @@ class ByteStringTest extends MessagePackSpec { MessagePack.newDefaultUnpacker(input).unpackString() } - "Unpacking a ByteString's ByteBuffer" should { - "fail with a regular MessageBuffer" in { + test("Unpacking a ByteString's ByteBuffer") { + test("fail with a regular MessageBuffer") { // can't demonstrate with new ByteBufferInput(byteString.asByteBuffer) // as Travis tests run with JDK6 that picks up MessageBufferU - a[RuntimeException] shouldBe thrownBy(unpackString(new MessageBuffer(byteString.asByteBuffer))) + intercept[RuntimeException] { + unpackString(new MessageBuffer(byteString.asByteBuffer)) + } } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index 060e436a1..4cc4a98a7 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -15,35 +15,35 @@ // package org.msgpack.core.buffer +import org.msgpack.core.MessagePack +import wvlet.airspec.AirSpec +import wvlet.log.io.IOUtil.withResource + import java.io._ -import java.net.{InetSocketAddress} +import java.net.InetSocketAddress import java.nio.ByteBuffer import java.nio.channels.{ServerSocketChannel, SocketChannel} import java.util.concurrent.{Callable, Executors, TimeUnit} import java.util.zip.{GZIPInputStream, GZIPOutputStream} - -import org.msgpack.core.{MessagePack, MessagePackSpec} -import xerial.core.io.IOUtil._ - import scala.util.Random -class MessageBufferInputTest extends MessagePackSpec { +class MessageBufferInputTest extends AirSpec { - val targetInputSize = + private val targetInputSize = Seq(0, 10, 500, 1000, 2000, 4000, 8000, 10000, 30000, 50000, 100000) - def testData(size: Int) = { + private def testData(size: Int) = { //debug(s"test data size: ${size}") val b = new Array[Byte](size) Random.nextBytes(b) b } - def testDataSet = { + private def testDataSet = { targetInputSize.map(testData) } - def runTest(factory: Array[Byte] => MessageBufferInput) { + private def runTest(factory: Array[Byte] => MessageBufferInput) { for (b <- testDataSet) { checkInputData(b, factory(b)) } @@ -74,30 +74,31 @@ class MessageBufferInputTest extends MessagePackSpec { } } - def checkInputData(inputData: Array[Byte], in: MessageBufferInput) { - When(s"input data size = ${inputData.length}") - var cursor = 0 - for (m <- Iterator.continually(in.next).takeWhile(_ != null)) { - m.toByteArray() shouldBe inputData.slice(cursor, cursor + m.size()) - cursor += m.size() + private def checkInputData(inputData: Array[Byte], in: MessageBufferInput) { + test(s"When input data size = ${inputData.length}") { + var cursor = 0 + for (m <- Iterator.continually(in.next).takeWhile(_ != null)) { + m.toByteArray() shouldBe inputData.slice(cursor, cursor + m.size()) + cursor += m.size() + } + cursor shouldBe inputData.length } - cursor shouldBe inputData.length } - "MessageBufferInput" should { - "support byte arrays" in { + test("MessageBufferInput") { + test("support byte arrays") { runTest(new ArrayBufferInput(_)) } - "support ByteBuffers" in { + test("support ByteBuffers") { runTest(b => new ByteBufferInput(b.toByteBuffer)) } - "support InputStreams" taggedAs ("is") in { + test("support InputStreams") { runTest(b => new InputStreamBufferInput(new GZIPInputStream(new ByteArrayInputStream(b.compress)))) } - "support file input channel" taggedAs ("fc") in { + test("support file input channel") { runTest { b => val tmp = b.saveToTmpFile try { @@ -110,13 +111,13 @@ class MessageBufferInputTest extends MessagePackSpec { } } - def createTempFile = { + private def createTempFile = { val f = File.createTempFile("msgpackTest", "msgpack") f.deleteOnExit f } - def createTempFileWithInputStream = { + private def createTempFileWithInputStream = { val f = createTempFile val out = new FileOutputStream(f) MessagePack.newDefaultPacker(out).packInt(42).close @@ -124,19 +125,19 @@ class MessageBufferInputTest extends MessagePackSpec { (f, in) } - def createTempFileWithChannel = { + private def createTempFileWithChannel = { val (f, in) = createTempFileWithInputStream val ch = in.getChannel (f, ch) } - def readInt(buf: MessageBufferInput): Int = { + private def readInt(buf: MessageBufferInput): Int = { val unpacker = MessagePack.newDefaultUnpacker(buf) unpacker.unpackInt } - "InputStreamBufferInput" should { - "reset buffer" in { + test("InputStreamBufferInput") { + test("reset buffer") { val (f0, in0) = createTempFileWithInputStream val buf = new InputStreamBufferInput(in0) readInt(buf) shouldBe 42 @@ -146,7 +147,7 @@ class MessageBufferInputTest extends MessagePackSpec { readInt(buf) shouldBe 42 } - "be non-blocking" taggedAs ("non-blocking") in { + test("be non-blocking") { withResource(new PipedOutputStream()) { pipedOutputStream => withResource(new PipedInputStream()) { pipedInputStream => @@ -173,8 +174,8 @@ class MessageBufferInputTest extends MessagePackSpec { } } - "ChannelBufferInput" should { - "reset buffer" in { + test("ChannelBufferInput") { + test("reset buffer") { val (f0, in0) = createTempFileWithChannel val buf = new ChannelBufferInput(in0) readInt(buf) shouldBe 42 @@ -184,7 +185,7 @@ class MessageBufferInputTest extends MessagePackSpec { readInt(buf) shouldBe 42 } - "unpack without blocking" in { + test("unpack without blocking") { val server = ServerSocketChannel.open.bind(new InetSocketAddress("localhost", 0)) val executorService = Executors.newCachedThreadPool diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala index e048e1ba1..ea9cde57e 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala @@ -15,62 +15,62 @@ // package org.msgpack.core.buffer -import java.io._ +import wvlet.airspec.AirSpec -import org.msgpack.core.MessagePackSpec +import java.io._ -class MessageBufferOutputTest extends MessagePackSpec { +class MessageBufferOutputTest extends AirSpec { - def createTempFile = { + private def createTempFile = { val f = File.createTempFile("msgpackTest", "msgpack") f.deleteOnExit f } - def createTempFileWithOutputStream = { + private def createTempFileWithOutputStream = { val f = createTempFile val out = new FileOutputStream(f) (f, out) } - def createTempFileWithChannel = { + private def createTempFileWithChannel = { val (f, out) = createTempFileWithOutputStream val ch = out.getChannel (f, ch) } - def writeIntToBuf(buf: MessageBufferOutput) = { + private def writeIntToBuf(buf: MessageBufferOutput) = { val mb0 = buf.next(8) mb0.putInt(0, 42) buf.writeBuffer(4) buf.close } - "OutputStreamBufferOutput" should { - "reset buffer" in { + test("OutputStreamBufferOutput") { + test("reset buffer") { val (f0, out0) = createTempFileWithOutputStream val buf = new OutputStreamBufferOutput(out0) writeIntToBuf(buf) - f0.length.toInt should be > 0 + f0.length.toInt > 0 shouldBe true val (f1, out1) = createTempFileWithOutputStream buf.reset(out1) writeIntToBuf(buf) - f1.length.toInt should be > 0 + f1.length.toInt > 0 shouldBe true } } - "ChannelBufferOutput" should { - "reset buffer" in { + test("ChannelBufferOutput") { + test("reset buffer") { val (f0, ch0) = createTempFileWithChannel val buf = new ChannelBufferOutput(ch0) writeIntToBuf(buf) - f0.length.toInt should be > 0 + f0.length.toInt >= 0 shouldBe true val (f1, ch1) = createTempFileWithChannel buf.reset(ch1) writeIntToBuf(buf) - f1.length.toInt should be > 0 + f1.length.toInt > 0 shouldBe true } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala index f0f66b4af..4bb9c69da 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala @@ -15,246 +15,245 @@ // package org.msgpack.core.buffer -import java.nio.ByteBuffer - -import org.msgpack.core.MessagePackSpec +import org.msgpack.core.Benchmark +import wvlet.airspec.AirSpec +import java.nio.ByteBuffer import scala.util.Random /** * Created on 2014/05/01. */ -class MessageBufferTest extends MessagePackSpec { +class MessageBufferTest extends AirSpec with Benchmark { - "MessageBuffer" should { + private val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] - val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] - "check buffer type" in { - val b = MessageBuffer.allocate(0) - info(s"MessageBuffer type: ${b.getClass.getName}") - } + test("check buffer type") { + val b = MessageBuffer.allocate(0) + info(s"MessageBuffer type: ${b.getClass.getName}") + } - "wrap byte array considering position and remaining values" taggedAs ("wrap-ba") in { - val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) - val mb = MessageBuffer.wrap(d, 2, 2) - mb.getByte(0) shouldBe 12 - mb.size() shouldBe 2 - } + test("wrap byte array considering position and remaining values") { + val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) + val mb = MessageBuffer.wrap(d, 2, 2) + mb.getByte(0) shouldBe 12 + mb.size() shouldBe 2 + } - "wrap ByteBuffer considering position and remaining values" taggedAs ("wrap-bb") in { - val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) - val subset = ByteBuffer.wrap(d, 2, 2) - val mb = MessageBuffer.wrap(subset) - mb.getByte(0) shouldBe 12 - mb.size() shouldBe 2 - } + test("wrap ByteBuffer considering position and remaining values") { + val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19) + val subset = ByteBuffer.wrap(d, 2, 2) + val mb = MessageBuffer.wrap(subset) + mb.getByte(0) shouldBe 12 + mb.size() shouldBe 2 + } + + test("have better performance than ByteBuffer") { - "have better performance than ByteBuffer" in { + val N = 1000000 + val M = 64 * 1024 * 1024 - val N = 1000000 - val M = 64 * 1024 * 1024 + val ub = MessageBuffer.allocate(M) + val ud = + if (universal) MessageBuffer.wrap(ByteBuffer.allocate(M)) + else MessageBuffer.wrap(ByteBuffer.allocateDirect(M)) + val hb = ByteBuffer.allocate(M) + val db = ByteBuffer.allocateDirect(M) - val ub = MessageBuffer.allocate(M) - val ud = - if (universal) MessageBuffer.wrap(ByteBuffer.allocate(M)) - else MessageBuffer.wrap(ByteBuffer.allocateDirect(M)) - val hb = ByteBuffer.allocate(M) - val db = ByteBuffer.allocateDirect(M) + def bench(f: Int => Unit) { + var i = 0 + while (i < N) { + f((i * 4) % M) + i += 1 + } + } + + val r = new Random(0) + val rs = new Array[Int](N) + (0 until N).map(i => rs(i) = r.nextInt(N)) + def randomBench(f: Int => Unit) { + var i = 0 + while (i < N) { + f((rs(i) * 4) % M) + i += 1 + } + } - def bench(f: Int => Unit) { + val rep = 3 + info(f"Reading buffers (of size:${M}%,d) ${N}%,d x $rep times") + time("sequential getInt", repeat = rep) { + block("unsafe array") { var i = 0 while (i < N) { - f((i * 4) % M) + ub.getInt((i * 4) % M) i += 1 } } - val r = new Random(0) - val rs = new Array[Int](N) - (0 until N).map(i => rs(i) = r.nextInt(N)) - def randomBench(f: Int => Unit) { + block("unsafe direct") { var i = 0 while (i < N) { - f((rs(i) * 4) % M) + ud.getInt((i * 4) % M) i += 1 } } - val rep = 3 - info(f"Reading buffers (of size:${M}%,d) ${N}%,d x $rep times") - time("sequential getInt", repeat = rep) { - block("unsafe array") { - var i = 0 - while (i < N) { - ub.getInt((i * 4) % M) - i += 1 - } - } - - block("unsafe direct") { - var i = 0 - while (i < N) { - ud.getInt((i * 4) % M) - i += 1 - } - } - - block("allocate") { - var i = 0 - while (i < N) { - hb.getInt((i * 4) % M) - i += 1 - } + block("allocate") { + var i = 0 + while (i < N) { + hb.getInt((i * 4) % M) + i += 1 } + } - block("allocateDirect") { - var i = 0 - while (i < N) { - db.getInt((i * 4) % M) - i += 1 - } + block("allocateDirect") { + var i = 0 + while (i < N) { + db.getInt((i * 4) % M) + i += 1 } } + } - time("random getInt", repeat = rep) { - block("unsafe array") { - var i = 0 - while (i < N) { - ub.getInt((rs(i) * 4) % M) - i += 1 - } + time("random getInt", repeat = rep) { + block("unsafe array") { + var i = 0 + while (i < N) { + ub.getInt((rs(i) * 4) % M) + i += 1 } + } - block("unsafe direct") { - var i = 0 - while (i < N) { - ud.getInt((rs(i) * 4) % M) - i += 1 - } + block("unsafe direct") { + var i = 0 + while (i < N) { + ud.getInt((rs(i) * 4) % M) + i += 1 } + } - block("allocate") { - var i = 0 - while (i < N) { - hb.getInt((rs(i) * 4) % M) - i += 1 - } + block("allocate") { + var i = 0 + while (i < N) { + hb.getInt((rs(i) * 4) % M) + i += 1 } + } - block("allocateDirect") { - var i = 0 - while (i < N) { - db.getInt((rs(i) * 4) % M) - i += 1 - } + block("allocateDirect") { + var i = 0 + while (i < N) { + db.getInt((rs(i) * 4) % M) + i += 1 } } } - val builder = Seq.newBuilder[MessageBuffer] - builder += MessageBuffer.allocate(10) - builder += MessageBuffer.wrap(ByteBuffer.allocate(10)) - if (!universal) builder += MessageBuffer.wrap(ByteBuffer.allocateDirect(10)) - val buffers = builder.result() - - "convert to ByteBuffer" in { - for (t <- buffers) { - val bb = t.sliceAsByteBuffer - bb.position() shouldBe 0 - bb.limit() shouldBe 10 - bb.capacity shouldBe 10 - } + } + + private val builder = Seq.newBuilder[MessageBuffer] + builder += MessageBuffer.allocate(10) + builder += MessageBuffer.wrap(ByteBuffer.allocate(10)) + if (!universal) builder += MessageBuffer.wrap(ByteBuffer.allocateDirect(10)) + private val buffers = builder.result() + + test("convert to ByteBuffer") { + for (t <- buffers) { + val bb = t.sliceAsByteBuffer + bb.position() shouldBe 0 + bb.limit() shouldBe 10 + bb.capacity shouldBe 10 } + } - "put ByteBuffer on itself" in { - for (t <- buffers) { - val b = Array[Byte](0x02, 0x03) - val srcArray = ByteBuffer.wrap(b) - val srcHeap = ByteBuffer.allocate(b.length) - srcHeap.put(b).flip - val srcOffHeap = ByteBuffer.allocateDirect(b.length) - srcOffHeap.put(b).flip - - for (src <- Seq(srcArray, srcHeap, srcOffHeap)) { - // Write header bytes - val header = Array[Byte](0x00, 0x01) - t.putBytes(0, header, 0, header.length) - // Write src after the header - t.putByteBuffer(header.length, src, header.length) - - t.getByte(0) shouldBe 0x00 - t.getByte(1) shouldBe 0x01 - t.getByte(2) shouldBe 0x02 - t.getByte(3) shouldBe 0x03 - } + test("put ByteBuffer on itself") { + for (t <- buffers) { + val b = Array[Byte](0x02, 0x03) + val srcArray = ByteBuffer.wrap(b) + val srcHeap = ByteBuffer.allocate(b.length) + srcHeap.put(b).flip + val srcOffHeap = ByteBuffer.allocateDirect(b.length) + srcOffHeap.put(b).flip + + for (src <- Seq(srcArray, srcHeap, srcOffHeap)) { + // Write header bytes + val header = Array[Byte](0x00, 0x01) + t.putBytes(0, header, 0, header.length) + // Write src after the header + t.putByteBuffer(header.length, src, header.length) + + t.getByte(0) shouldBe 0x00 + t.getByte(1) shouldBe 0x01 + t.getByte(2) shouldBe 0x02 + t.getByte(3) shouldBe 0x03 } } + } - "put MessageBuffer on itself" in { - for (t <- buffers) { - val b = Array[Byte](0x02, 0x03) - val srcArray = ByteBuffer.wrap(b) - val srcHeap = ByteBuffer.allocate(b.length) - srcHeap.put(b).flip - val srcOffHeap = ByteBuffer.allocateDirect(b.length) - srcOffHeap.put(b).flip - val builder = Seq.newBuilder[ByteBuffer] - builder ++= Seq(srcArray, srcHeap) - if (!universal) builder += srcOffHeap - - for (src <- builder.result().map(d => MessageBuffer.wrap(d))) { - // Write header bytes - val header = Array[Byte](0x00, 0x01) - t.putBytes(0, header, 0, header.length) - // Write src after the header - t.putMessageBuffer(header.length, src, 0, header.length) - - t.getByte(0) shouldBe 0x00 - t.getByte(1) shouldBe 0x01 - t.getByte(2) shouldBe 0x02 - t.getByte(3) shouldBe 0x03 - } + test("put MessageBuffer on itself") { + for (t <- buffers) { + val b = Array[Byte](0x02, 0x03) + val srcArray = ByteBuffer.wrap(b) + val srcHeap = ByteBuffer.allocate(b.length) + srcHeap.put(b).flip + val srcOffHeap = ByteBuffer.allocateDirect(b.length) + srcOffHeap.put(b).flip + val builder = Seq.newBuilder[ByteBuffer] + builder ++= Seq(srcArray, srcHeap) + if (!universal) builder += srcOffHeap + + for (src <- builder.result().map(d => MessageBuffer.wrap(d))) { + // Write header bytes + val header = Array[Byte](0x00, 0x01) + t.putBytes(0, header, 0, header.length) + // Write src after the header + t.putMessageBuffer(header.length, src, 0, header.length) + + t.getByte(0) shouldBe 0x00 + t.getByte(1) shouldBe 0x01 + t.getByte(2) shouldBe 0x02 + t.getByte(3) shouldBe 0x03 } } + } - "copy sliced buffer" in { - def prepareBytes: Array[Byte] = { - Array[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07) - } + test("copy sliced buffer") { + def prepareBytes: Array[Byte] = { + Array[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07) + } - def prepareDirectBuffer: ByteBuffer = { - val directBuffer = ByteBuffer.allocateDirect(prepareBytes.length) - directBuffer.put(prepareBytes) - directBuffer.flip - directBuffer - } + def prepareDirectBuffer: ByteBuffer = { + val directBuffer = ByteBuffer.allocateDirect(prepareBytes.length) + directBuffer.put(prepareBytes) + directBuffer.flip + directBuffer + } - def checkSliceAndCopyTo(srcBuffer: MessageBuffer, dstBuffer: MessageBuffer) = { - val sliced = srcBuffer.slice(2, 5) - - sliced.size() shouldBe 5 - sliced.getByte(0) shouldBe 0x02 - sliced.getByte(1) shouldBe 0x03 - sliced.getByte(2) shouldBe 0x04 - sliced.getByte(3) shouldBe 0x05 - sliced.getByte(4) shouldBe 0x06 - - sliced.copyTo(3, dstBuffer, 1, 2) // copy 0x05 and 0x06 to dstBuffer[1] and [2] - - dstBuffer.getByte(0) shouldBe 0x00 - dstBuffer.getByte(1) shouldBe 0x05 // copied by sliced.getByte(3) - dstBuffer.getByte(2) shouldBe 0x06 // copied by sliced.getByte(4) - dstBuffer.getByte(3) shouldBe 0x03 - dstBuffer.getByte(4) shouldBe 0x04 - dstBuffer.getByte(5) shouldBe 0x05 - dstBuffer.getByte(6) shouldBe 0x06 - dstBuffer.getByte(7) shouldBe 0x07 - } + def checkSliceAndCopyTo(srcBuffer: MessageBuffer, dstBuffer: MessageBuffer) = { + val sliced = srcBuffer.slice(2, 5) + + sliced.size() shouldBe 5 + sliced.getByte(0) shouldBe 0x02 + sliced.getByte(1) shouldBe 0x03 + sliced.getByte(2) shouldBe 0x04 + sliced.getByte(3) shouldBe 0x05 + sliced.getByte(4) shouldBe 0x06 + + sliced.copyTo(3, dstBuffer, 1, 2) // copy 0x05 and 0x06 to dstBuffer[1] and [2] + + dstBuffer.getByte(0) shouldBe 0x00 + dstBuffer.getByte(1) shouldBe 0x05 // copied by sliced.getByte(3) + dstBuffer.getByte(2) shouldBe 0x06 // copied by sliced.getByte(4) + dstBuffer.getByte(3) shouldBe 0x03 + dstBuffer.getByte(4) shouldBe 0x04 + dstBuffer.getByte(5) shouldBe 0x05 + dstBuffer.getByte(6) shouldBe 0x06 + dstBuffer.getByte(7) shouldBe 0x07 + } - checkSliceAndCopyTo(MessageBuffer.wrap(prepareBytes), MessageBuffer.wrap(prepareBytes)) - checkSliceAndCopyTo(MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)), MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes))) - if (!universal) { - checkSliceAndCopyTo(MessageBuffer.wrap(prepareDirectBuffer), MessageBuffer.wrap(prepareDirectBuffer)) - } + checkSliceAndCopyTo(MessageBuffer.wrap(prepareBytes), MessageBuffer.wrap(prepareBytes)) + checkSliceAndCopyTo(MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)), MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes))) + if (!universal) { + checkSliceAndCopyTo(MessageBuffer.wrap(prepareDirectBuffer), MessageBuffer.wrap(prepareDirectBuffer)) } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala index cbbfd8751..05dfa6e65 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala @@ -15,28 +15,28 @@ // package org.msgpack.core.example -import org.msgpack.core.MessagePackSpec +import wvlet.airspec.AirSpec /** * */ -class MessagePackExampleTest extends MessagePackSpec { +class MessagePackExampleTest extends AirSpec { - "example" should { + test("example") { - "have basic usage" in { + test("have basic usage") { MessagePackExample.basicUsage() } - "have packer usage" in { + test("have packer usage") { MessagePackExample.packer() } - "have file read/write example" in { + test("have file read/write example") { MessagePackExample.readAndWriteFile(); } - "have configuration example" in { + test("have configuration example") { MessagePackExample.configuration(); } } diff --git a/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala index 7de9d6c6f..fb340553c 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala @@ -15,20 +15,18 @@ // package org.msgpack.value -import org.msgpack.core.MessagePackSpec +import wvlet.airspec.AirSpec -class RawStringValueImplTest extends MessagePackSpec { +class RawStringValueImplTest extends AirSpec { - "StringValue" should { - "return the same hash code if they are equal" in { - val str = "a" - val a1 = ValueFactory.newString(str.getBytes("UTF-8")) - val a2 = ValueFactory.newString(str) + test("return the same hash code if they are equal") { + val str = "a" + val a1 = ValueFactory.newString(str.getBytes("UTF-8")) + val a2 = ValueFactory.newString(str) - a1.shouldEqual(a2) - a1.hashCode.shouldEqual(a2.hashCode) - a2.shouldEqual(a1) - a2.hashCode.shouldEqual(a1.hashCode) - } + a1 shouldBe a2 + a1.hashCode shouldBe a2.hashCode + a2 shouldBe a1 + a2.hashCode shouldBe a1.hashCode } } diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala index c9bc8f8f0..b667ddfcf 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala @@ -15,27 +15,29 @@ // package org.msgpack.value -import org.msgpack.core.MessagePackSpec -import org.scalacheck.Prop.forAll +import org.scalacheck.Gen +import wvlet.airspec.AirSpec +import wvlet.airspec.spi.PropertyCheck /** * */ -class ValueFactoryTest extends MessagePackSpec { +class ValueFactoryTest extends AirSpec with PropertyCheck { - def isValid(v: Value, - expected: ValueType, - isNil: Boolean = false, - isBoolean: Boolean = false, - isInteger: Boolean = false, - isString: Boolean = false, - isFloat: Boolean = false, - isBinary: Boolean = false, - isArray: Boolean = false, - isMap: Boolean = false, - isExtension: Boolean = false, - isRaw: Boolean = false, - isNumber: Boolean = false): Boolean = { + private def isValid(v: Value, + expected: ValueType, + isNil: Boolean = false, + isBoolean: Boolean = false, + isInteger: Boolean = false, + isString: Boolean = false, + isFloat: Boolean = false, + isBinary: Boolean = false, + isArray: Boolean = false, + isMap: Boolean = false, + isExtension: Boolean = false, + isRaw: Boolean = false, + isNumber: Boolean = false, + isTimestamp: Boolean = false): Boolean = { v.isNilValue shouldBe isNil v.isBooleanValue shouldBe isBoolean v.isIntegerValue shouldBe isInteger @@ -47,33 +49,70 @@ class ValueFactoryTest extends MessagePackSpec { v.isExtensionValue shouldBe isExtension v.isRawValue shouldBe isRaw v.isNumberValue shouldBe isNumber + v.isTimestampValue shouldBe isTimestamp true } - "ValueFactory" should { - - "create valid type values" in { + test("ValueFactory") { + test("nil") { isValid(ValueFactory.newNil(), expected = ValueType.NIL, isNil = true) + } + + test("boolean") { forAll { (v: Boolean) => isValid(ValueFactory.newBoolean(v), expected = ValueType.BOOLEAN, isBoolean = true) } + } + + test("int") { forAll { (v: Int) => isValid(ValueFactory.newInteger(v), expected = ValueType.INTEGER, isInteger = true, isNumber = true) } + } + + test("float") { forAll { (v: Float) => isValid(ValueFactory.newFloat(v), expected = ValueType.FLOAT, isFloat = true, isNumber = true) } + } + test("string") { forAll { (v: String) => isValid(ValueFactory.newString(v), expected = ValueType.STRING, isString = true, isRaw = true) } + } + + test("array") { forAll { (v: Array[Byte]) => isValid(ValueFactory.newBinary(v), expected = ValueType.BINARY, isBinary = true, isRaw = true) } + } + + test("empty array") { isValid(ValueFactory.emptyArray(), expected = ValueType.ARRAY, isArray = true) + } + + test("empty map") { isValid(ValueFactory.emptyMap(), expected = ValueType.MAP, isMap = true) + } + + test("ext") { forAll { (v: Array[Byte]) => isValid(ValueFactory.newExtension(0, v), expected = ValueType.EXTENSION, isExtension = true, isRaw = false) } } + + test("timestamp") { + forAll { (millis: Long) => + isValid(ValueFactory.newTimestamp(millis), expected = ValueType.EXTENSION, isExtension = true, isTimestamp = true) + } + } + + test("timestamp sec/nano") { + val posLong = Gen.chooseNum[Long](-31557014167219200L, 31556889864403199L) + val posInt = Gen.chooseNum(0, 1000000000 - 1) // NANOS_PER_SECOND + forAll(posLong, posInt) { (sec: Long, nano: Int) => + isValid(ValueFactory.newTimestamp(sec, nano), expected = ValueType.EXTENSION, isExtension = true, isTimestamp = true) + } + } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala index eeb663bc6..83cbde6bf 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala @@ -15,31 +15,34 @@ // package org.msgpack.value +import org.msgpack.core.MessagePackSpec.createMessagePackData + import java.math.BigInteger import org.msgpack.core._ -import org.scalacheck.Prop.{forAll, propBoolean} - -import scala.util.parsing.json.JSON +import org.scalacheck.Prop.propBoolean +import wvlet.airframe.json.JSON +import wvlet.airspec.AirSpec +import wvlet.airspec.spi.PropertyCheck -class ValueTest extends MessagePackSpec { - def checkSuccinctType(pack: MessagePacker => Unit, expectedAtMost: MessageFormat): Boolean = { +class ValueTest extends AirSpec with PropertyCheck { + private def checkSuccinctType(pack: MessagePacker => Unit, expectedAtMost: MessageFormat): Boolean = { val b = createMessagePackData(pack) val v1 = MessagePack.newDefaultUnpacker(b).unpackValue() val mf = v1.asIntegerValue().mostSuccinctMessageFormat() mf.getValueType shouldBe ValueType.INTEGER - mf.ordinal() shouldBe <=(expectedAtMost.ordinal()) + mf.ordinal() <= expectedAtMost.ordinal() shouldBe true val v2 = new Variable MessagePack.newDefaultUnpacker(b).unpackValue(v2) val mf2 = v2.asIntegerValue().mostSuccinctMessageFormat() mf2.getValueType shouldBe ValueType.INTEGER - mf2.ordinal() shouldBe <=(expectedAtMost.ordinal()) + mf2.ordinal() <= expectedAtMost.ordinal() shouldBe true true } - "Value" should { - "tell most succinct integer type" in { + test("Value") { + test("tell most succinct integer type") { forAll { (v: Byte) => checkSuccinctType(_.packByte(v), MessageFormat.INT8) } @@ -63,7 +66,7 @@ class ValueTest extends MessagePackSpec { } } - "produce json strings" in { + test("produce json strings") { import ValueFactory._ @@ -94,9 +97,9 @@ class ValueTest extends MessagePackSpec { .put(newString("address"), newArray(newString("xxx-xxxx"), newString("yyy-yyyy"))) .put(newString("name"), newString("mitsu")) .build() - val i1 = JSON.parseFull(m.toJson) - val i2 = JSON.parseFull(m.toString) // expect json value - val a1 = JSON.parseFull("""{"id":1001,"name":"mitsu","address":["xxx-xxxx","yyy-yyyy"]}""") + val i1 = JSON.parse(m.toJson) + val i2 = JSON.parse(m.toString) // expect json value + val a1 = JSON.parse("""{"id":1001,"name":"mitsu","address":["xxx-xxxx","yyy-yyyy"]}""") // Equals as JSON map i1 shouldBe a1 i2 shouldBe a1 @@ -108,7 +111,7 @@ class ValueTest extends MessagePackSpec { } - "check appropriate range for integers" in { + test("check appropriate range for integers") { import ValueFactory._ import java.lang.Byte import java.lang.Short diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala index 445eda32c..4627faba4 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala @@ -16,73 +16,70 @@ package org.msgpack.value import org.msgpack.core.MessagePack.Code._ -import org.msgpack.core.{MessageFormat, MessageFormatException, MessagePackSpec} +import org.msgpack.core.{MessageFormat, MessageFormatException} +import wvlet.airspec.AirSpec /** * Created on 2014/05/06. */ -class ValueTypeTest extends MessagePackSpec { +class ValueTypeTest extends AirSpec { - "ValueType" should { - - "lookup ValueType from a byte value" taggedAs ("code") in { - - def check(b: Byte, tpe: ValueType) { - MessageFormat.valueOf(b).getValueType shouldBe tpe - } + test("lookup ValueType from a byte value") { + def check(b: Byte, tpe: ValueType) { + MessageFormat.valueOf(b).getValueType shouldBe tpe + } - for (i <- 0 until 0x7f) { - check(i.toByte, ValueType.INTEGER) - } + for (i <- 0 until 0x7f) { + check(i.toByte, ValueType.INTEGER) + } - for (i <- 0x80 until 0x8f) { - check(i.toByte, ValueType.MAP) - } + for (i <- 0x80 until 0x8f) { + check(i.toByte, ValueType.MAP) + } - for (i <- 0x90 until 0x9f) { - check(i.toByte, ValueType.ARRAY) - } + for (i <- 0x90 until 0x9f) { + check(i.toByte, ValueType.ARRAY) + } - check(NIL, ValueType.NIL) + check(NIL, ValueType.NIL) - try { - MessageFormat.valueOf(NEVER_USED).getValueType - fail("NEVER_USED type should not have ValueType") - } catch { - case e: MessageFormatException => - // OK - } + try { + MessageFormat.valueOf(NEVER_USED).getValueType + fail("NEVER_USED type should not have ValueType") + } catch { + case e: MessageFormatException => + // OK + } - check(TRUE, ValueType.BOOLEAN) - check(FALSE, ValueType.BOOLEAN) + check(TRUE, ValueType.BOOLEAN) + check(FALSE, ValueType.BOOLEAN) - for (t <- Seq(BIN8, BIN16, BIN32)) { - check(t, ValueType.BINARY) - } + for (t <- Seq(BIN8, BIN16, BIN32)) { + check(t, ValueType.BINARY) + } - for (t <- Seq(FIXEXT1, FIXEXT2, FIXEXT4, FIXEXT8, FIXEXT16, EXT8, EXT16, EXT32)) { - check(t, ValueType.EXTENSION) - } + for (t <- Seq(FIXEXT1, FIXEXT2, FIXEXT4, FIXEXT8, FIXEXT16, EXT8, EXT16, EXT32)) { + check(t, ValueType.EXTENSION) + } - for (t <- Seq(INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64)) { - check(t, ValueType.INTEGER) - } + for (t <- Seq(INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64)) { + check(t, ValueType.INTEGER) + } - for (t <- Seq(STR8, STR16, STR32)) { - check(t, ValueType.STRING) - } + for (t <- Seq(STR8, STR16, STR32)) { + check(t, ValueType.STRING) + } - for (t <- Seq(FLOAT32, FLOAT64)) { - check(t, ValueType.FLOAT) - } + for (t <- Seq(FLOAT32, FLOAT64)) { + check(t, ValueType.FLOAT) + } - for (t <- Seq(ARRAY16, ARRAY32)) { - check(t, ValueType.ARRAY) - } + for (t <- Seq(ARRAY16, ARRAY32)) { + check(t, ValueType.ARRAY) + } - for (i <- 0xe0 until 0xff) { - check(i.toByte, ValueType.INTEGER) - } + for (i <- 0xe0 until 0xff) { + check(i.toByte, ValueType.INTEGER) } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala new file mode 100644 index 000000000..67ea2efef --- /dev/null +++ b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala @@ -0,0 +1,310 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.value + +import org.msgpack.core.{MessagePack, MessagePacker, MessageTypeCastException} +import wvlet.airspec.AirSpec +import wvlet.airspec.spi.PropertyCheck + +import java.time.Instant +import java.util +import scala.jdk.CollectionConverters._ + +/** + * + */ +class VariableTest extends AirSpec with PropertyCheck { + private def check(pack: MessagePacker => Unit, checker: Variable => Unit): Unit = { + val packer = MessagePack.newDefaultBufferPacker() + pack(packer) + val msgpack = packer.toByteArray + packer.close() + val v = new Variable() + val unpacker = MessagePack.newDefaultUnpacker(msgpack) + unpacker.unpackValue(v) + checker(v) + unpacker.close() + } + + /** + * Test Value -> MsgPack -> Value + */ + private def roundTrip(v: Value): Unit = { + val packer = MessagePack.newDefaultBufferPacker() + v.writeTo(packer) + val msgpack = packer.toByteArray + val unpacker = MessagePack.newDefaultUnpacker(msgpack) + val v1 = unpacker.unpackValue() + unpacker.close() + v shouldBe v1 + v.immutableValue() shouldBe v1 + } + + private def validateValue[V <: Value]( + v: V, + asNil: Boolean = false, + asBoolean: Boolean = false, + asInteger: Boolean = false, + asFloat: Boolean = false, + asBinary: Boolean = false, + asString: Boolean = false, + asArray: Boolean = false, + asMap: Boolean = false, + asExtension: Boolean = false, + asTimestamp: Boolean = false + ): V = { + v.isNilValue shouldBe asNil + v.isBooleanValue shouldBe asBoolean + v.isIntegerValue shouldBe asInteger + v.isNumberValue shouldBe asInteger | asFloat + v.isFloatValue shouldBe asFloat + v.isRawValue shouldBe asBinary | asString + v.isBinaryValue shouldBe asBinary + v.isStringValue shouldBe asString + v.isArrayValue shouldBe asArray + v.isMapValue shouldBe asMap + v.isExtensionValue shouldBe asExtension | asTimestamp + v.isTimestampValue shouldBe asTimestamp + + if (asNil) { + v.getValueType shouldBe ValueType.NIL + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asNilValue() + } + } + + if (asBoolean) { + v.getValueType shouldBe ValueType.BOOLEAN + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asBooleanValue() + } + } + + if (asInteger) { + v.getValueType shouldBe ValueType.INTEGER + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asIntegerValue() + } + } + + if (asFloat) { + v.getValueType shouldBe ValueType.FLOAT + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asFloatValue() + } + } + + if (asBinary | asString) { + v.asRawValue() + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asRawValue() + } + } + + if (asBinary) { + v.getValueType shouldBe ValueType.BINARY + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asBinaryValue() + } + } + + if (asString) { + v.getValueType shouldBe ValueType.STRING + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asStringValue() + } + } + + if (asArray) { + v.getValueType shouldBe ValueType.ARRAY + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asArrayValue() + } + } + + if (asMap) { + v.getValueType shouldBe ValueType.MAP + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asMapValue() + } + } + + if (asExtension) { + v.getValueType shouldBe ValueType.EXTENSION + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asExtensionValue() + } + } + + if (asTimestamp) { + v.getValueType shouldBe ValueType.EXTENSION + roundTrip(v) + } else { + intercept[MessageTypeCastException] { + v.asTimestampValue() + } + } + + v + } + + test("Variable") { + test("read nil") { + check( + _.packNil, + checker = { v => + val iv = validateValue(v.asNilValue(), asNil = true) + iv.toJson shouldBe "null" + } + ) + } + + test("read integers") { + forAll { i: Int => + check( + _.packInt(i), + checker = { v => + val iv = validateValue(v.asIntegerValue(), asInteger = true) + iv.asInt() shouldBe i + iv.asLong() shouldBe i.toLong + } + ) + } + } + + test("read double") { + forAll { x: Double => + check( + _.packDouble(x), + checker = { v => + val iv = validateValue(v.asFloatValue(), asFloat = true) + //iv.toDouble shouldBe v + //iv.toFloat shouldBe x.toFloat + } + ) + } + } + + test("read boolean") { + forAll { x: Boolean => + check( + _.packBoolean(x), + checker = { v => + val iv = validateValue(v.asBooleanValue(), asBoolean = true) + iv.getBoolean shouldBe x + } + ) + } + } + + test("read binary") { + forAll { x: Array[Byte] => + check( + { packer => + packer.packBinaryHeader(x.length); packer.addPayload(x) + }, + checker = { v => + val iv = validateValue(v.asBinaryValue(), asBinary = true) + util.Arrays.equals(iv.asByteArray(), x) + } + ) + } + } + + test("read string") { + forAll { x: String => + check( + _.packString(x), + checker = { v => + val iv = validateValue(v.asStringValue(), asString = true) + iv.asString() shouldBe x + } + ) + } + } + + test("read array") { + forAll { x: Seq[Int] => + check( + { packer => + packer.packArrayHeader(x.size) + x.foreach { packer.packInt(_) } + }, + checker = { v => + val iv = validateValue(v.asArrayValue(), asArray = true) + val lst = iv.list().asScala.map(_.asIntegerValue().toInt) + lst shouldBe x + } + ) + } + } + + test("read map") { + forAll { x: Seq[Int] => + // Generate map with unique keys + val map = x.zipWithIndex.map { case (x, i) => (s"key-${i}", x) } + check( + { packer => + packer.packMapHeader(map.size) + map.foreach { x => + packer.packString(x._1) + packer.packInt(x._2) + } + }, + checker = { v => + val iv = validateValue(v.asMapValue(), asMap = true) + val lst = iv.map().asScala.map(p => (p._1.asStringValue().asString(), p._2.asIntegerValue().asInt())).toSeq + lst.sortBy(_._1) shouldBe map.sortBy(_._1) + } + ) + } + } + + test("read timestamps") { + forAll { millis: Long => + val i = Instant.ofEpochMilli(millis) + check( + _.packTimestamp(i), + checker = { v => + val ts = validateValue(v.asTimestampValue(), asTimestamp = true) + ts.isTimestampValue shouldBe true + ts.toInstant shouldBe i + } + ) + } + } + } +} From 9b35aa7c210dc69a0a090521465986e38024885a Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 20 May 2021 05:32:19 +0200 Subject: [PATCH 181/417] Update airframe-json, airspec to 20.12.2 (#570) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index eae3cd51a..68dadb3d2 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "20.4.1" +val AIRFRAME_VERSION = "20.12.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 25e0df3e5f6260de0dc072f554b79d3a6e84e0db Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 20 May 2021 05:32:29 +0200 Subject: [PATCH 182/417] Update scala-collection-compat to 2.4.4 (#569) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 68dadb3d2..73fd815b8 100644 --- a/build.sbt +++ b/build.sbt @@ -85,7 +85,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.5.23" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.4.3" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.4.4" % "test" ) ) From 3d6bed23e3ae3791a58c3eb3559dff02f5ecdbcb Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 31 May 2021 18:40:13 +0200 Subject: [PATCH 183/417] Update scala-library to 2.12.14 (#574) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 73fd815b8..8e4fade0f 100644 --- a/build.sbt +++ b/build.sbt @@ -17,7 +17,7 @@ val buildSettings = Seq[Setting[_]]( organizationName := "MessagePack", organizationHomepage := Some(new URL("http://msgpack.org/")), description := "MessagePack for Java", - scalaVersion := "2.12.13", + scalaVersion := "2.12.14", Test / logBuffered := false, // msgpack-java should be a pure-java library, so remove Scala specific configurations autoScalaLibrary := false, From b64958f669a54698c259d05741ad97546be55130 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 7 Jun 2021 23:45:36 +0200 Subject: [PATCH 184/417] Update sbt to 1.5.3 (#575) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 182d2a9b8..a7dc35095 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.5.2 +sbt.version=1.5.3 From ef526f1de989c10568c7cc3351a7aedbfe1af983 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 8 Jun 2021 18:55:51 +0200 Subject: [PATCH 185/417] Update scala-library to 2.13.6 (#568) * Update scala-library to 2.13.6 * Update scala-library to 2.13.6 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 8e4fade0f..a215cadda 100644 --- a/build.sbt +++ b/build.sbt @@ -17,7 +17,7 @@ val buildSettings = Seq[Setting[_]]( organizationName := "MessagePack", organizationHomepage := Some(new URL("http://msgpack.org/")), description := "MessagePack for Java", - scalaVersion := "2.12.14", + scalaVersion := "2.13.6", Test / logBuffered := false, // msgpack-java should be a pure-java library, so remove Scala specific configurations autoScalaLibrary := false, From fc791f14170ebdc163af4c34625ba2921c74d37a Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 8 Jun 2021 19:05:17 +0200 Subject: [PATCH 186/417] Update airframe-json, airspec to 21.6.0 (#576) * Update airframe-json, airspec to 21.6.0 * Update scala-library to 2.13.6 (#568) * Update scala-library to 2.13.6 * Update scala-library to 2.13.6 * Fix test Co-authored-by: Taro L. Saito --- build.sbt | 2 +- .../src/test/scala/org/msgpack/core/MessagePackTest.scala | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index a215cadda..be51d781f 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "20.12.2" +val AIRFRAME_VERSION = "21.6.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index f60702ed8..2e96ca25c 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -377,8 +377,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { } test("report errors when packing/unpacking malformed strings") { - // TODO produce malformed utf-8 strings in Java8" - pending + pending("We need to produce malformed utf-8 strings in Java 8") // Create 100 malformed UTF8 Strings val r = new Random(0) val malformedStrings = Iterator From b8368dd6a1cbc9e3afe3fcf8aacceff1fde5c0fc Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 8 Jun 2021 10:27:53 -0700 Subject: [PATCH 187/417] Fix for Scala 2.13 syntax (#577) --- .../msgpack/core/InvalidDataReadTest.scala | 1 - .../org/msgpack/core/MessageFormatTest.scala | 6 +- .../org/msgpack/core/MessagePackTest.scala | 189 +++++++++++------- .../org/msgpack/core/MessagePackerTest.scala | 17 +- .../msgpack/core/MessageUnpackerTest.scala | 48 +++-- .../core/buffer/MessageBufferInputTest.scala | 10 +- .../core/buffer/MessageBufferTest.scala | 4 +- .../core/example/MessagePackExampleTest.scala | 1 - .../org/msgpack/value/ValueFactoryTest.scala | 31 +-- .../org/msgpack/value/ValueTypeTest.scala | 2 +- .../org/msgpack/value/VariableTest.scala | 1 - 11 files changed, 175 insertions(+), 135 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala index 4e39ff85c..6f0138385 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala @@ -4,7 +4,6 @@ import org.msgpack.core.MessagePackSpec.createMessagePackData import wvlet.airspec.AirSpec /** - * */ class InvalidDataReadTest extends AirSpec { diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala index 5f3447617..06a58e112 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala @@ -28,7 +28,7 @@ import scala.util.Random class MessageFormatTest extends AirSpec with Benchmark { test("MessageFormat") { test("cover all byte codes") { - def checkV(b: Byte, tpe: ValueType) { + def checkV(b: Byte, tpe: ValueType): Unit = { try MessageFormat.valueOf(b).getValueType shouldBe tpe catch { case e: AirSpecException => @@ -37,11 +37,11 @@ class MessageFormatTest extends AirSpec with Benchmark { } } - def checkF(b: Byte, f: MessageFormat) { + def checkF(b: Byte, f: MessageFormat): Unit = { MessageFormat.valueOf(b) shouldBe f } - def check(b: Byte, tpe: ValueType, f: MessageFormat) { + def check(b: Byte, tpe: ValueType, f: MessageFormat): Unit = { checkV(b, tpe) checkF(b, f) } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 2e96ca25c..c2d32eccb 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -82,7 +82,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { Code.isPosFixInt(i.toByte) shouldBe true } - for (i <- 0x80 until 0xFF) { + for (i <- 0x80 until 0xff) { Code.isPosFixInt(i.toByte) shouldBe false } } @@ -166,7 +166,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { Code.isNegFixInt(i.toByte) shouldBe false } - for (i <- 0xe0 until 0xFF) { + for (i <- 0xe0 until 0xff) { Code.isNegFixInt(i.toByte) shouldBe true } @@ -223,7 +223,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { fail("cannot not reach here") } - private def checkOverflow[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A) { + private def checkOverflow[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A): Unit = { try { checkException[A](v, pack, unpack) } catch { @@ -253,63 +253,80 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { forAll { (v: Double) => check(v, _.packDouble(v), _.unpackDouble) } - check(null, _.packNil, { unpacker => - unpacker.unpackNil(); null - }) + check( + null, + _.packNil, + { unpacker => + unpacker.unpackNil(); null + } + ) } test("skipping a nil value") { check(true, _.packNil, _.tryUnpackNil) - check(false, { packer => - packer.packString("val") - }, { unpacker => - unpacker.tryUnpackNil() - }) - check("val", { packer => - packer.packString("val") - }, { unpacker => - unpacker.tryUnpackNil(); unpacker.unpackString() - }) - check("val", { packer => - packer.packNil(); packer.packString("val") - }, { unpacker => - unpacker.tryUnpackNil(); unpacker.unpackString() - }) + check( + false, + { packer => + packer.packString("val") + }, + { unpacker => + unpacker.tryUnpackNil() + } + ) + check( + "val", + { packer => + packer.packString("val") + }, + { unpacker => + unpacker.tryUnpackNil(); unpacker.unpackString() + } + ) + check( + "val", + { packer => + packer.packNil(); packer.packString("val") + }, + { unpacker => + unpacker.tryUnpackNil(); unpacker.unpackString() + } + ) try { - checkException(null, { _ => - }, _.tryUnpackNil) + checkException(null, { _ => }, _.tryUnpackNil) } catch { case e: MessageInsufficientBufferException => // OK } } test("pack/unpack integer values") { - val sampleData = Seq[Long](Int.MinValue.toLong - - 10, - -65535, - -8191, - -1024, - -255, - -127, - -63, - -31, - -15, - -7, - -3, - -1, - 0, - 2, - 4, - 8, - 16, - 32, - 64, - 128, - 256, - 1024, - 8192, - 65536, - Int.MaxValue.toLong + 10) + val sampleData = Seq[Long]( + Int.MinValue.toLong - + 10, + -65535, + -8191, + -1024, + -255, + -127, + -63, + -31, + -15, + -7, + -3, + -1, + 0, + 2, + 4, + 8, + 16, + 32, + 64, + 128, + 256, + 1024, + 8192, + 65536, + Int.MaxValue.toLong + 10 + ) for (v <- sampleData) { check(v, _.packLong(v), _.unpackLong) @@ -399,10 +416,14 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { } try { - checkException(malformed, { packer => - packer.packRawStringHeader(malformedBytes.length) - packer.writePayload(malformedBytes) - }, _.unpackString()) + checkException( + malformed, + { packer => + packer.packRawStringHeader(malformedBytes.length) + packer.writePayload(malformedBytes) + }, + _.unpackString() + ) } catch { case e: MessageStringCodingException => // OK } @@ -421,10 +442,16 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { for (bytes <- Seq(unmappable)) { try { - checkException(bytes, { packer => - packer.packRawStringHeader(bytes.length) - packer.writePayload(bytes) - }, _.unpackString(), new PackerConfig(), unpackerConfig) + checkException( + bytes, + { packer => + packer.packRawStringHeader(bytes.length) + packer.writePayload(bytes) + }, + _.unpackString(), + new PackerConfig(), + unpackerConfig + ) } catch { case e: MessageStringCodingException => // OK } @@ -434,9 +461,11 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { test("pack/unpack binary") { forAll { (v: Array[Byte]) => check( - v, { packer => + v, + { packer => packer.packBinaryHeader(v.length); packer.writePayload(v) - }, { unpacker => + }, + { unpacker => val len = unpacker.unpackBinaryHeader() val out = new Array[Byte](len) unpacker.readPayload(out, 0, len) @@ -450,9 +479,11 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { val v = new Array[Byte](l) Random.nextBytes(v) check( - v, { packer => + v, + { packer => packer.packBinaryHeader(v.length); packer.writePayload(v) - }, { unpacker => + }, + { unpacker => val len = unpacker.unpackBinaryHeader() val out = new Array[Byte](len) unpacker.readPayload(out, 0, len) @@ -467,10 +498,12 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { test("pack/unpack arrays") { forAll { (v: Array[Int]) => check( - v, { packer => + v, + { packer => packer.packArrayHeader(v.length) v.map(packer.packInt(_)) - }, { unpacker => + }, + { unpacker => val len = unpacker.unpackArrayHeader() val out = new Array[Int](len) for (i <- 0 until v.length) { @@ -498,20 +531,22 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { val m = v.map(i => (i, i.toString)).toSeq check( - m, { packer => + m, + { packer => packer.packMapHeader(v.length) m.map { case (k: Int, v: String) => packer.packInt(k) packer.packString(v) } - }, { unpacker => + }, + { unpacker => val len = unpacker.unpackMapHeader() val b = Seq.newBuilder[(Int, String)] for (i <- 0 until len) { b += ((unpacker.unpackInt, unpacker.unpackString)) } - b.result + b.result() } ) } @@ -549,7 +584,8 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { val aMap = List(Map("f" -> "x")) check( - aMap, { packer => + aMap, + { packer => packer.packArrayHeader(aMap.size) for (m <- aMap) { packer.packMapHeader(m.size) @@ -558,10 +594,11 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { packer.packString(v) } } - }, { unpacker => + }, + { unpacker => val v = new Variable() unpacker.unpackValue(v) - import scala.collection.JavaConverters._ + import scala.jdk.CollectionConverters._ v.asArrayValue().asScala .map { m => val mv = m.asMapValue() @@ -605,12 +642,14 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { } // Corner-cases around uint32 boundaries - for (v <- Seq( - Instant.ofEpochSecond(Instant.now().getEpochSecond, 123456789L), // uint32 nanoseq (out of int32 range) - Instant.ofEpochSecond(-1302749144L, 0), // 1928-09-19T21:14:16Z - Instant.ofEpochSecond(-747359729L, 0), // 1946-04-27T00:04:31Z - Instant.ofEpochSecond(4257387427L, 0) // 2104-11-29T07:37:07Z - )) { + for ( + v <- Seq( + Instant.ofEpochSecond(Instant.now().getEpochSecond, 123456789L), // uint32 nanoseq (out of int32 range) + Instant.ofEpochSecond(-1302749144L, 0), // 1928-09-19T21:14:16Z + Instant.ofEpochSecond(-747359729L, 0), // 1946-04-27T00:04:31Z + Instant.ofEpochSecond(4257387427L, 0) // 2104-11-29T07:37:07Z + ) + ) { check(v, _.packTimestamp(v), _.unpackTimestamp()) } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index 096a811b4..dea3e4ead 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -25,17 +25,16 @@ import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream} import scala.util.Random /** - * */ class MessagePackerTest extends AirSpec with Benchmark { - private def verifyIntSeq(answer: Array[Int], packed: Array[Byte]) { + private def verifyIntSeq(answer: Array[Int], packed: Array[Byte]): Unit = { val unpacker = MessagePack.newDefaultUnpacker(packed) val b = Array.newBuilder[Int] while (unpacker.hasNext) { b += unpacker.unpackInt() } - val result = b.result + val result = b.result() result.size shouldBe answer.size result shouldBe answer } @@ -61,7 +60,7 @@ class MessagePackerTest extends AirSpec with Benchmark { test("MessagePacker") { test("reset the internal states") { - val intSeq = (0 until 100).map(i => Random.nextInt).toArray + val intSeq = (0 until 100).map(i => Random.nextInt()).toArray val b = new ByteArrayOutputStream val packer = MessagePack.newDefaultPacker(b) @@ -239,12 +238,12 @@ class MessagePackerTest extends AirSpec with Benchmark { val packerTotalWrittenBytes = withResource(MessagePack.newDefaultPacker(out)) { packer => packer - .packByte(0) // 1 - .packBoolean(true) // 1 - .packShort(12) // 1 - .packInt(1024) // 3 + .packByte(0) // 1 + .packBoolean(true) // 1 + .packShort(12) // 1 + .packInt(1024) // 3 .packLong(Long.MaxValue) // 5 - .packString("foobar") // 7 + .packString("foobar") // 7 .flush() packer.getTotalWrittenBytes diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 5ae597f27..720885c45 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -25,7 +25,7 @@ import wvlet.log.io.IOUtil.withResource import java.io._ import java.nio.ByteBuffer import java.util.Collections -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import scala.util.Random object MessageUnpackerTest { @@ -88,7 +88,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { arr } - private def write(packer: MessagePacker, r: Random) { + private def write(packer: MessagePacker, r: Random): Unit = { val tpeIndex = Iterator .continually(r.nextInt(MessageFormat.values().length)) .find(_ != MessageFormat.NEVER_USED.ordinal()) @@ -162,7 +162,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { arr } - private def readValue(unpacker: MessageUnpacker) { + private def readValue(unpacker: MessageUnpacker): Unit = { val f = unpacker.getNextFormat() f.getValueType match { case ValueType.ARRAY => @@ -183,7 +183,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { } } - private def createTempFile = { + private def createTempFile: File = { val f = File.createTempFile("msgpackTest", "msgpack") f.deleteOnExit val p = MessagePack.newDefaultPacker(new FileOutputStream(f)) @@ -192,7 +192,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { f } - private def checkFile(u: MessageUnpacker) = { + private def checkFile(u: MessageUnpacker): Boolean = { u.unpackInt shouldBe 99 u.hasNext shouldBe false } @@ -320,7 +320,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { } } - ib.result shouldBe intSeq.toSeq + ib.result() shouldBe intSeq.toSeq unpacker.getTotalReadBytes shouldBe testData2.length } } @@ -328,7 +328,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { test("read data at the buffer boundary") { trait SplitTest extends LogSupport { val data: Array[Byte] - def run { + def run: Unit = { for (unpacker <- unpackers(data)) { val numElems = { var c = 0 @@ -357,7 +357,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { } } - new SplitTest { val data = testData }.run + new SplitTest { val data = testData }.run new SplitTest { val data = testData3(30) }.run } @@ -411,7 +411,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { trait Fixture { val unpacker: MessageUnpacker - def run { + def run: Unit = { var count = 0 try { while (unpacker.hasNext) { @@ -475,7 +475,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { test("be faster than msgpack-v6 read value") { - def readValueV6(unpacker: org.msgpack.unpacker.MessagePackUnpacker) { + def readValueV6(unpacker: org.msgpack.unpacker.MessagePackUnpacker): Unit = { val vt = unpacker.getNextType() vt match { case ValueTypeV6.ARRAY => @@ -507,7 +507,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { val buf = new Array[Byte](8192) - def readValue(unpacker: MessageUnpacker) { + def readValue(unpacker: MessageUnpacker): Unit = { val f = unpacker.getNextFormat val vt = f.getValueType vt match { @@ -539,7 +539,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { } trait Fixture { val unpacker: MessageUnpacker - def run { + def run: Unit = { var count = 0 try { while (unpacker.hasNext) { @@ -617,7 +617,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { trait Fixture { val unpacker: MessageUnpacker val loop: Int - def run { + def run: Unit = { var i = 0 try { while (i < loop) { @@ -628,7 +628,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { } } finally unpacker.close() } - def runRef { + def runRef: Unit = { var i = 0 try { while (i < loop) { @@ -742,7 +742,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { unpacked += unpacker.unpackInt() } unpacker.close - unpacked.result shouldBe data + unpacked.result() shouldBe data val data2 = intSeq val b2 = createMessagePackData(packer => data2 foreach packer.packInt) @@ -753,7 +753,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { unpacked2 += unpacker.unpackInt() } unpacker.close - unpacked2.result shouldBe data2 + unpacked2.result() shouldBe data2 // reused the buffer input instance bi.reset(b2) @@ -763,7 +763,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { unpacked3 += unpacker.unpackInt() } unpacker.close - unpacked3.result shouldBe data2 + unpacked3.result() shouldBe data2 } } @@ -911,10 +911,13 @@ class MessageUnpackerTest extends AirSpec with Benchmark { test("read value length at buffer boundary") { val input = new SplitMessageBufferInput( - Array(Array[Byte](MessagePack.Code.STR16), - Array[Byte](0x00), - Array[Byte](0x05), // STR16 length at the boundary - "hello".getBytes(MessagePack.UTF8))) + Array( + Array[Byte](MessagePack.Code.STR16), + Array[Byte](0x00), + Array[Byte](0x05), // STR16 length at the boundary + "hello".getBytes(MessagePack.UTF8) + ) + ) readTest(input) val input2 = new SplitMessageBufferInput( @@ -924,7 +927,8 @@ class MessageUnpackerTest extends AirSpec with Benchmark { Array[Byte](0x00, 0x00), Array[Byte](0x05), // STR32 length at the boundary "hello".getBytes(MessagePack.UTF8) - )) + ) + ) readTest(input2) } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index 4cc4a98a7..dd1cdb974 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -32,18 +32,18 @@ class MessageBufferInputTest extends AirSpec { private val targetInputSize = Seq(0, 10, 500, 1000, 2000, 4000, 8000, 10000, 30000, 50000, 100000) - private def testData(size: Int) = { + private def testData(size: Int): Array[Byte] = { //debug(s"test data size: ${size}") val b = new Array[Byte](size) Random.nextBytes(b) b } - private def testDataSet = { + private def testDataSet: Seq[Array[Byte]] = { targetInputSize.map(testData) } - private def runTest(factory: Array[Byte] => MessageBufferInput) { + private def runTest(factory: Array[Byte] => MessageBufferInput): Unit = { for (b <- testDataSet) { checkInputData(b, factory(b)) } @@ -74,7 +74,7 @@ class MessageBufferInputTest extends AirSpec { } } - private def checkInputData(inputData: Array[Byte], in: MessageBufferInput) { + private def checkInputData(inputData: Array[Byte], in: MessageBufferInput): Unit = { test(s"When input data size = ${inputData.length}") { var cursor = 0 for (m <- Iterator.continually(in.next).takeWhile(_ != null)) { @@ -192,7 +192,7 @@ class MessageBufferInputTest extends AirSpec { try { executorService.execute(new Runnable { - override def run { + override def run: Unit = { val server_ch = server.accept val packer = MessagePack.newDefaultPacker(server_ch) packer.packString("0123456789") diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala index 4bb9c69da..4de059951 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala @@ -60,7 +60,7 @@ class MessageBufferTest extends AirSpec with Benchmark { val hb = ByteBuffer.allocate(M) val db = ByteBuffer.allocateDirect(M) - def bench(f: Int => Unit) { + def bench(f: Int => Unit): Unit = { var i = 0 while (i < N) { f((i * 4) % M) @@ -71,7 +71,7 @@ class MessageBufferTest extends AirSpec with Benchmark { val r = new Random(0) val rs = new Array[Int](N) (0 until N).map(i => rs(i) = r.nextInt(N)) - def randomBench(f: Int => Unit) { + def randomBench(f: Int => Unit): Unit = { var i = 0 while (i < N) { f((rs(i) * 4) % M) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala index 05dfa6e65..99876275d 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala @@ -18,7 +18,6 @@ package org.msgpack.core.example import wvlet.airspec.AirSpec /** - * */ class MessagePackExampleTest extends AirSpec { diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala index b667ddfcf..3fe2a07f8 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala @@ -20,24 +20,25 @@ import wvlet.airspec.AirSpec import wvlet.airspec.spi.PropertyCheck /** - * */ class ValueFactoryTest extends AirSpec with PropertyCheck { - private def isValid(v: Value, - expected: ValueType, - isNil: Boolean = false, - isBoolean: Boolean = false, - isInteger: Boolean = false, - isString: Boolean = false, - isFloat: Boolean = false, - isBinary: Boolean = false, - isArray: Boolean = false, - isMap: Boolean = false, - isExtension: Boolean = false, - isRaw: Boolean = false, - isNumber: Boolean = false, - isTimestamp: Boolean = false): Boolean = { + private def isValid( + v: Value, + expected: ValueType, + isNil: Boolean = false, + isBoolean: Boolean = false, + isInteger: Boolean = false, + isString: Boolean = false, + isFloat: Boolean = false, + isBinary: Boolean = false, + isArray: Boolean = false, + isMap: Boolean = false, + isExtension: Boolean = false, + isRaw: Boolean = false, + isNumber: Boolean = false, + isTimestamp: Boolean = false + ): Boolean = { v.isNilValue shouldBe isNil v.isBooleanValue shouldBe isBoolean v.isIntegerValue shouldBe isInteger diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala index 4627faba4..e8b04d5f6 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala @@ -25,7 +25,7 @@ import wvlet.airspec.AirSpec class ValueTypeTest extends AirSpec { test("lookup ValueType from a byte value") { - def check(b: Byte, tpe: ValueType) { + def check(b: Byte, tpe: ValueType): Unit = { MessageFormat.valueOf(b).getValueType shouldBe tpe } diff --git a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala index 67ea2efef..5d97d8712 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala @@ -24,7 +24,6 @@ import java.util import scala.jdk.CollectionConverters._ /** - * */ class VariableTest extends AirSpec with PropertyCheck { private def check(pack: MessagePacker => Unit, checker: Variable => Unit): Unit = { From cad4476044fd1b78336831868c6750593bf3d305 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 8 Jun 2021 19:28:11 +0200 Subject: [PATCH 188/417] Update akka-actor to 2.5.32 (#560) * Update akka-actor to 2.5.32 * Update akka-actor to 2.5.32 * Update akka-actor to 2.5.32 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index be51d781f..ce54abf22 100644 --- a/build.sbt +++ b/build.sbt @@ -84,7 +84,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka - "com.typesafe.akka" %% "akka-actor" % "2.5.23" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.5.32" % "test", "org.scala-lang.modules" %% "scala-collection-compat" % "2.4.4" % "test" ) ) From 5b5f8e6a9bb6c0d8b51a68185f11d09d8f3ba56e Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 8 Jun 2021 19:33:23 +0200 Subject: [PATCH 189/417] Update jackson-databind to 2.10.5.1 (#559) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ce54abf22..82d0c4077 100644 --- a/build.sbt +++ b/build.sbt @@ -102,7 +102,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From c5f98a238efbc3f81babf7aee977eac08b8c68fe Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 8 Jun 2021 22:09:05 +0200 Subject: [PATCH 190/417] Update akka-actor to 2.6.14 (#579) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 82d0c4077..92b431b31 100644 --- a/build.sbt +++ b/build.sbt @@ -84,7 +84,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka - "com.typesafe.akka" %% "akka-actor" % "2.5.32" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.6.14" % "test", "org.scala-lang.modules" %% "scala-collection-compat" % "2.4.4" % "test" ) ) From 651a2a02fd5f269d91183cf70e162dea7a5d9caa Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 8 Jun 2021 14:22:52 -0700 Subject: [PATCH 191/417] Add low-level APIs for unpacking Timestamp values (#580) --- .../org/msgpack/core/ExtensionTypeHeader.java | 5 +++++ .../java/org/msgpack/core/MessageUnpacker.java | 4 ++-- .../core/example/MessagePackExample.java | 16 ++++++++++++++-- .../org/msgpack/core/MessagePackTest.scala | 18 ++++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/ExtensionTypeHeader.java b/msgpack-core/src/main/java/org/msgpack/core/ExtensionTypeHeader.java index 73e92035a..c27287882 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/ExtensionTypeHeader.java +++ b/msgpack-core/src/main/java/org/msgpack/core/ExtensionTypeHeader.java @@ -59,6 +59,11 @@ public byte getType() return type; } + public boolean isTimestampType() + { + return type == MessagePack.Code.EXT_TIMESTAMP; + } + public int getLength() { return length; diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index b43204beb..c59b742ac 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -1284,9 +1284,9 @@ public Instant unpackTimestamp() } /** - * Internal method that can be used only when the extension type header is already read. + * Unpack timestamp that can be used after reading the extension type header with unpackExtensionTypeHeader. */ - private Instant unpackTimestamp(ExtensionTypeHeader ext) throws IOException + public Instant unpackTimestamp(ExtensionTypeHeader ext) throws IOException { if (ext.getType() != EXT_TIMESTAMP) { throw unexpectedExtension("Timestamp", EXT_TIMESTAMP, ext.getType()); diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java index 5feb15dbc..7764e2d25 100644 --- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java +++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java @@ -26,6 +26,7 @@ import org.msgpack.value.ExtensionValue; import org.msgpack.value.FloatValue; import org.msgpack.value.IntegerValue; +import org.msgpack.value.TimestampValue; import org.msgpack.value.Value; import java.io.File; @@ -33,6 +34,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.math.BigInteger; +import java.time.Instant; /** * This class describes the usage of MessagePack @@ -145,6 +147,9 @@ public static void packer() packer.packExtensionTypeHeader((byte) 1, 10); // type number [0, 127], data byte length packer.writePayload(extData); + // Pack timestamp + packer.packTimestamp(Instant.now()); + // Succinct syntax for packing packer .packInt(1) @@ -228,8 +233,15 @@ else if (iv.isInLongRange()) { break; case EXTENSION: ExtensionValue ev = v.asExtensionValue(); - byte extType = ev.getType(); - byte[] extValue = ev.getData(); + if (ev.isTimestampValue()) { + // Reading the value as a timestamp + TimestampValue ts = ev.asTimestampValue(); + Instant tsValue = ts.toInstant(); + } + else { + byte extType = ev.getType(); + byte[] extValue = ev.getData(); + } break; } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index c2d32eccb..4f6949bd3 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -662,6 +662,24 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { } } + test("pack/unpack timestamp through ExtValue") { + val posLong = Gen.chooseNum[Long](-31557014167219200L, 31556889864403199L) + forAll(posLong) { (millis: Long) => + val v = Instant.ofEpochMilli(millis) + check(v, { _.packTimestamp(millis) }, + { u => + val extHeader = u.unpackExtensionTypeHeader() + if(extHeader.isTimestampType) { + u.unpackTimestamp(extHeader) + } + else { + fail("Cannot reach here") + } + } + ) + } + } + test("MessagePack.PackerConfig") { test("should be immutable") { val a = new MessagePack.PackerConfig() From 741dfb506c9b0bade4e7f7bb35ecc75ef970a708 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 8 Jun 2021 14:39:22 -0700 Subject: [PATCH 192/417] Add release notes for 0.9.0 (#581) --- README.md | 7 +++++++ RELEASE_NOTES.md | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/README.md b/README.md index 1a7c1f439..c5af97cdf 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,13 @@ $ git tag v0.x.y $ git push origin v0.x.y ``` +To generate a release notes, you can use this command line: +``` +$ git log v(last version).. --oneline | cut -f 2- -d ' ' | perl -npe 's/(.*)\(\#([0-9]+)\)/* \1\[\#\2\]\(https:\/\/round-lake.dustinice.workers.dev:443\/http\/github.com\/msgpack\/msgpack-java\/pull\/\2\)/g' +``` + +#### Publishing to Sonatype from Local Machine + If you need to publish to Maven central using a local machine, you need to configure [sbt-sonatype](https://github.com/xerial/sbt-sonatype) plugin. First set Sonatype account information (user name and password) in the global sbt settings. To protect your password, never include this file in your project. ___$HOME/.sbt/(sbt-version)/sonatype.sbt___ diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e04b4d566..dc7d19dee 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,33 @@ # Release Notes +## 0.9.0 + +This version support reading and writing [Timestamp values](https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type). +Packer and unpacker interfaces added pack/unpackTimestamp methods. + +Timestamp value in MessagePack is an extension type value whose code is -1. If MessgageUnapcker.unpackValue method is used, +TimestampValue object can be retrieved automatically. If you are using low-level unpack methods (e.g., unpackInt, unpackExtension, etc.), +you need to read unpackExtensionHeader first, and if extHeader.isTimestampType is true, call unpackTimestamp(ext). + +When reading Timestamp values, [java.time.Instant](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/Instant.html) will be returned. +You can extract the unixtime with Instant.getEpochSecond(), unixtime with milliseconds resolution with Instant.toEpochMilli(), and nano-resolution time with Instant.getNano(). + +As TimestampValue is a sub class of ExtensionValue, your code traversing MessagePack data with MessageUnpacker.unpackValue should require no change. + + +* Added Timestamp support [#565](http://github.com/msgpack/msgpack-java/pull/565) and low-level APIs [#580](https://github.com/msgpack/msgpack-java/pull/580) for +reading timestamp values. + +Dependency updates: +* Update jackson-databind to 2.10.5.1 [#559](http://github.com/msgpack/msgpack-java/pull/559) + +Internal updates: +* Update akka-actor to 2.6.14 [#579](http://github.com/msgpack/msgpack-java/pull/579) +* Fix for Scala 2.13 syntax [#577](http://github.com/msgpack/msgpack-java/pull/577) +* Update airframe-json, airspec to 21.6.0 [#576](http://github.com/msgpack/msgpack-java/pull/576) +* Update scala-library to 2.13.6 [#568](http://github.com/msgpack/msgpack-java/pull/568) +* Update sbt to 1.5.3 [#575](http://github.com/msgpack/msgpack-java/pull/575) + ## 0.8.24 * Rebuild with JDK8 for Android compatibility [#567](https://github.com/msgpack/msgpack-java/pull/567) From 348fc220544c82b75e035e3ea33d5e7252da5445 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 8 Jun 2021 15:30:20 -0700 Subject: [PATCH 193/417] Update RELEASE_NOTES.md --- RELEASE_NOTES.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index dc7d19dee..4f00c472d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -5,15 +5,14 @@ This version support reading and writing [Timestamp values](https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type). Packer and unpacker interfaces added pack/unpackTimestamp methods. -Timestamp value in MessagePack is an extension type value whose code is -1. If MessgageUnapcker.unpackValue method is used, -TimestampValue object can be retrieved automatically. If you are using low-level unpack methods (e.g., unpackInt, unpackExtension, etc.), -you need to read unpackExtensionHeader first, and if extHeader.isTimestampType is true, call unpackTimestamp(ext). +Timestamp value in MessagePack is an extension type value whose code is -1. You can read TimestampValue object with MessgageUnapcker.unpackValue method. +If you are using low-level unpack methods (e.g., unpackInt, unpackExtension, etc.), +you need to read unpackExtensionHeader first, and if extHeader.isTimestampType() is true, call unpackTimestamp(extHeader). -When reading Timestamp values, [java.time.Instant](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/Instant.html) will be returned. -You can extract the unixtime with Instant.getEpochSecond(), unixtime with milliseconds resolution with Instant.toEpochMilli(), and nano-resolution time with Instant.getNano(). - -As TimestampValue is a sub class of ExtensionValue, your code traversing MessagePack data with MessageUnpacker.unpackValue should require no change. +Timestamp values are represented with [java.time.Instant](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/Instant.html) objects. +You can extract the unixtime value with Instant.getEpochSecond(), unixtime with milliseconds resolution with Instant.toEpochMilli(), and nano-resolution time with Instant.getNano(). +As TimestampValue is just a sub class of ExtensionValue, no change requierd in your code that are traversing MessagePack data with MessageUnpacker.unpackValue method. * Added Timestamp support [#565](http://github.com/msgpack/msgpack-java/pull/565) and low-level APIs [#580](https://github.com/msgpack/msgpack-java/pull/580) for reading timestamp values. From da453e18fd93894ae54318278324316c670a8dba Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 10 Jun 2021 17:28:55 +0200 Subject: [PATCH 194/417] Update akka-actor to 2.6.15 (#582) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 92b431b31..b61a98203 100644 --- a/build.sbt +++ b/build.sbt @@ -84,7 +84,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka - "com.typesafe.akka" %% "akka-actor" % "2.6.14" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.6.15" % "test", "org.scala-lang.modules" %% "scala-collection-compat" % "2.4.4" % "test" ) ) From 66c808d8f431edd463bd892c3054a790d65b0650 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 15 Jun 2021 05:52:53 +0200 Subject: [PATCH 195/417] Update sbt to 1.5.4 (#583) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index a7dc35095..14095e16e 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.5.3 +sbt.version=1.5.4 From 6af26dfdd7b2cfdfa810f3d6281351e27dd86095 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 6 Aug 2021 07:15:02 +0200 Subject: [PATCH 196/417] Update sbt to 1.5.5 (#588) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 14095e16e..1188d5f04 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.5.4 +sbt.version=1.5.5 From 030d4a09535e03eb97dd7d9fe670bf4a2517b53c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 20 Aug 2021 02:50:12 +0200 Subject: [PATCH 197/417] Update sbt-sonatype to 3.9.9 (#591) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index d0fd94755..9ccbb3e3e 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.9") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From 79542149643c701410b12d37725b29df07c0f887 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 20 Aug 2021 02:50:27 +0200 Subject: [PATCH 198/417] Update sbt-scalafmt to 2.4.3 (#586) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 9ccbb3e3e..c141f0978 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,7 +5,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.3") addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") scalacOptions ++= Seq("-deprecation", "-feature") From ba7b2c30e5d2a001aa2d46734ae72b17a2013fa6 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 20 Aug 2021 02:50:39 +0200 Subject: [PATCH 199/417] Update airframe-json, airspec to 21.8.1 (#592) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index b61a98203..4f2bf1237 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "21.6.0" +val AIRFRAME_VERSION = "21.8.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 9864b4336d0bfe0c13056a79221566f578c74b1b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 20 Aug 2021 02:50:48 +0200 Subject: [PATCH 200/417] Update scala-collection-compat to 2.5.0 (#587) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4f2bf1237..94b446702 100644 --- a/build.sbt +++ b/build.sbt @@ -85,7 +85,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.15" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.4.4" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.5.0" % "test" ) ) From 9943c1f3cdd7acd5d916dee985c30c41dd14fd0a Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 21 Aug 2021 19:23:13 +0200 Subject: [PATCH 201/417] Update akka-actor to 2.6.16 (#593) * Update akka-actor to 2.6.16 * Update akka-actor to 2.6.16 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 94b446702..812758d2c 100644 --- a/build.sbt +++ b/build.sbt @@ -84,7 +84,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka - "com.typesafe.akka" %% "akka-actor" % "2.6.15" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.6.16" % "test", "org.scala-lang.modules" %% "scala-collection-compat" % "2.5.0" % "test" ) ) From 5d54b75511082693cdb19f150df96436f0a5b8bd Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 25 Aug 2021 23:27:37 +0200 Subject: [PATCH 202/417] Update sbt-sonatype to 3.9.10 (#594) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index c141f0978..d7ec8ab8d 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.9") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.10") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From f842824260029a3f5f63498e2f9baff5b7b8f602 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sun, 5 Sep 2021 18:52:39 +0200 Subject: [PATCH 203/417] Update airframe-json, airspec to 21.9.0 (#596) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 812758d2c..a3a40b286 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "21.8.1" +val AIRFRAME_VERSION = "21.9.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From c32ad8808d38e0e524ac9fc5a818d2ee8b4d7ac2 Mon Sep 17 00:00:00 2001 From: szh Date: Sun, 19 Sep 2021 07:33:19 +0800 Subject: [PATCH 204/417] Specify the bufferSize of the ArrayBufferOutput (#597) Use the bufferSize of PackerConfig to specify the bufferSize of the ArrayBufferOutput in MessageBufferPacker. --- .../src/main/java/org/msgpack/core/MessageBufferPacker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java index 71edc21d2..0b4852251 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java @@ -34,7 +34,7 @@ public class MessageBufferPacker { protected MessageBufferPacker(MessagePack.PackerConfig config) { - this(new ArrayBufferOutput(), config); + this(new ArrayBufferOutput(config.getBufferSize()), config); } protected MessageBufferPacker(ArrayBufferOutput out, MessagePack.PackerConfig config) From ff1a16f6867eed1c20f205eab09f04478cefa7c5 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 19 Oct 2021 00:26:19 +0200 Subject: [PATCH 205/417] Update airframe-json, airspec to 21.10.0 (#601) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a3a40b286..8dfb65a11 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "21.9.0" +val AIRFRAME_VERSION = "21.10.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 62bd05c285850885b5f62184fdece70935fa8feb Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 21 Oct 2021 00:37:32 +0200 Subject: [PATCH 206/417] Update akka-actor to 2.6.17 (#602) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 8dfb65a11..a24118339 100644 --- a/build.sbt +++ b/build.sbt @@ -84,7 +84,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka - "com.typesafe.akka" %% "akka-actor" % "2.6.16" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.6.17" % "test", "org.scala-lang.modules" %% "scala-collection-compat" % "2.5.0" % "test" ) ) From 3dc0d551c61848b7cffdb1f0f41d6895d013ab80 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 28 Oct 2021 03:01:00 +0200 Subject: [PATCH 207/417] Update junit-interface to 0.13.2 (#603) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a24118339..0d0483224 100644 --- a/build.sbt +++ b/build.sbt @@ -46,7 +46,7 @@ val buildSettings = Seq[Setting[_]]( Test / compile := ((Test / compile) dependsOn (Test / jcheckStyle)).value ) -val junitInterface = "com.novocode" % "junit-interface" % "0.11" % "test" +val junitInterface = "com.github.sbt" % "junit-interface" % "0.13.2" % "test" // Project settings lazy val root = Project(id = "msgpack-java", base = file(".")) From 1b94b12d6e80c5ed23b26c2ef6134f9a1efda905 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 10 Dec 2021 07:23:50 +0100 Subject: [PATCH 208/417] Update sbt-scalafmt to 2.4.5 (#608) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index d7ec8ab8d..1609ca903 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,7 +5,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.3") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.5") addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") scalacOptions ++= Seq("-deprecation", "-feature") From 8b9eb8bd2979335b830a12f5a785bc62bfe4e4c9 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 10 Dec 2021 07:24:00 +0100 Subject: [PATCH 209/417] Update scala-collection-compat to 2.6.0 (#604) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0d0483224..f45b96544 100644 --- a/build.sbt +++ b/build.sbt @@ -85,7 +85,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.17" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.5.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.6.0" % "test" ) ) From 16caa63db905d6e053b327502d8ea8b020ab4604 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 10 Dec 2021 07:24:13 +0100 Subject: [PATCH 210/417] Update airframe-json, airspec to 21.12.0 (#609) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f45b96544..14aa94b48 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "21.10.0" +val AIRFRAME_VERSION = "21.12.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From da9a8bee12b9c4e853d465914069b1a6a57cdfd4 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Thu, 9 Dec 2021 22:27:08 -0800 Subject: [PATCH 211/417] Upgrade sbt to 1.5.6 (#610) --- project/build.properties | 2 +- sbt | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/project/build.properties b/project/build.properties index 1188d5f04..71aac7fe5 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.5.5 +sbt.version=1.5.6 diff --git a/sbt b/sbt index 1aac2d3f6..18c6b1125 100755 --- a/sbt +++ b/sbt @@ -34,11 +34,11 @@ set -o pipefail -declare -r sbt_release_version="1.5.1" -declare -r sbt_unreleased_version="1.5.1" +declare -r sbt_release_version="1.5.5" +declare -r sbt_unreleased_version="1.6.0-M1" -declare -r latest_213="2.13.5" -declare -r latest_212="2.12.13" +declare -r latest_213="2.13.7" +declare -r latest_212="2.12.15" declare -r latest_211="2.11.12" declare -r latest_210="2.10.7" declare -r latest_29="2.9.3" @@ -216,7 +216,8 @@ getJavaVersion() { # but on 9 and 10 it's 9.x.y and 10.x.y. if [[ "$str" =~ ^1\.([0-9]+)(\..*)?$ ]]; then echo "${BASH_REMATCH[1]}" - elif [[ "$str" =~ ^([0-9]+)(\..*)?$ ]]; then + # Fixes https://github.com/dwijnand/sbt-extras/issues/326 + elif [[ "$str" =~ ^([0-9]+)(\..*)?(-ea)?$ ]]; then echo "${BASH_REMATCH[1]}" elif [[ -n "$str" ]]; then echoerr "Can't parse java version from: $str" @@ -252,7 +253,9 @@ is_apple_silicon() { [[ "$(uname -s)" == "Darwin" && "$(uname -m)" == "arm64" ]] # MaxPermSize critical on pre-8 JVMs but incurs noisy warning on 8+ default_jvm_opts() { local -r v="$(java_version)" - if [[ $v -ge 10 ]]; then + if [[ $v -ge 17 ]]; then + echo "$default_jvm_opts_common" + elif [[ $v -ge 10 ]]; then if is_apple_silicon; then # As of Dec 2020, JVM for Apple Silicon (M1) doesn't support JVMCI echo "$default_jvm_opts_common" From fba05ce428aad317210066f1594f7b797f6d3412 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 15 Dec 2021 08:00:10 +0100 Subject: [PATCH 212/417] Update airframe-json, airspec to 21.12.1 (#611) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 14aa94b48..b8c4b9d5b 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "21.12.0" +val AIRFRAME_VERSION = "21.12.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From d72c6cd35d91d6f0ac730b428e97ff7a4b9bc4d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Peignier?= Date: Fri, 14 Jan 2022 15:12:11 -0800 Subject: [PATCH 213/417] Add an ObjectMapper shorthand --- msgpack-jackson/README.md | 24 +++++++++----- .../jackson/dataformat/MessagePackMapper.java | 33 +++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 38e2bf5b5..f1710ff24 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -58,11 +58,17 @@ Only thing you need to do is to instantiate `MessagePackFactory` and pass it to System.out.println(deserialized.getName()); // => komamitsu ``` +Or more easily: + +```java +ObjectMapper objectMapper = new MessagePackMapper(); +``` + ### Serialization/Deserialization of List ```java // Instantiate ObjectMapper for MessagePack - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + ObjectMapper objectMapper = new MessagePackMapper(); // Serialize a List to byte array List list = new ArrayList<>(); @@ -80,7 +86,7 @@ Only thing you need to do is to instantiate `MessagePackFactory` and pass it to ```java // Instantiate ObjectMapper for MessagePack - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + ObjectMapper objectMapper = MessagePackMapper(); // Serialize a Map to byte array Map map = new HashMap<>(); @@ -146,7 +152,7 @@ On the other hand, jackson-databind serializes and deserializes a POJO as a key- But if you want to make this library handle POJOs in the same way as msgpack-java:0.6 or earlier, you can use `JsonArrayFormat` like this: ```java - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + ObjectMapper objectMapper = new MessagePackMapper(); objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); ``` @@ -156,7 +162,7 @@ But if you want to make this library handle POJOs in the same way as msgpack-jav ```java OutputStream out = new FileOutputStream(tempFile); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + ObjectMapper objectMapper = new MessagePackMapper(); objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); objectMapper.writeValue(out, 1); @@ -181,7 +187,7 @@ But if you want to make this library handle POJOs in the same way as msgpack-jav packer.close(); FileInputStream in = new FileInputStream(tempFile); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + ObjectMapper objectMapper = new MessagePackMapper(); objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); System.out.println(objectMapper.readValue(in, Integer.class)); System.out.println(objectMapper.readValue(in, String.class)); @@ -194,7 +200,7 @@ Old msgpack-java (e.g 0.6.7) doesn't support MessagePack str8 type. When your ap ```java MessagePack.PackerConfig config = new MessagePack.PackerConfig().withStr8FormatSupport(false); - ObjectMapper mapperWithConfig = new ObjectMapper(new MessagePackFactory(config)); + ObjectMapper mapperWithConfig = new MessagePackMapper(new MessagePackFactory(config)); // This string is serialized as bin8 type byte[] resultWithoutStr8Format = mapperWithConfig.writeValueAsBytes(str8LengthString); ``` @@ -211,7 +217,7 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial intMap.put(42, "Hello"); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + ObjectMapper objectMapper = new MessagePackMapper(); byte[] bytes = objectMapper.writeValueAsBytes(intMap); Map deserialized = objectMapper.readValue(bytes, new TypeReference>() {}); @@ -407,7 +413,7 @@ When you serialize an object that has a nested object also serializing with Obje @Test public void testNestedSerialization() throws Exception { - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + ObjectMapper objectMapper = new MessagePackMapper(); objectMapper.writeValueAsBytes(new OuterClass()); } @@ -415,7 +421,7 @@ When you serialize an object that has a nested object also serializing with Obje { public String getInner() throws JsonProcessingException { - ObjectMapper m = new ObjectMapper(new MessagePackFactory()); + ObjectMapper m = new MessagePackMapper(); m.writeValueAsBytes(new InnerClass()); return "EFG"; } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java new file mode 100644 index 000000000..c929337fb --- /dev/null +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java @@ -0,0 +1,33 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.jackson.dataformat; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class MessagePackMapper extends ObjectMapper +{ + private static final long serialVersionUID = 3L; + + public MessagePackMapper() + { + this(new MessagePackFactory()); + } + + public MessagePackMapper(MessagePackFactory f) + { + super(f); + } +} From 2f715556a6e137d2af8b4ba079a29a41bbd4f2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Peignier?= Date: Fri, 14 Jan 2022 16:42:54 -0800 Subject: [PATCH 214/417] Add a similar Builder --- .../jackson/dataformat/MessagePackMapper.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java index c929337fb..3c3d228b0 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java @@ -16,11 +16,20 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.cfg.MapperBuilder; public class MessagePackMapper extends ObjectMapper { private static final long serialVersionUID = 3L; + public static class Builder extends MapperBuilder + { + public Builder(MessagePackMapper m) + { + super(m); + } + } + public MessagePackMapper() { this(new MessagePackFactory()); @@ -30,4 +39,14 @@ public MessagePackMapper(MessagePackFactory f) { super(f); } + + public static Builder builder() + { + return new Builder(new MessagePackMapper()); + } + + public static Builder builder(MessagePackFactory f) + { + return new Builder(new MessagePackMapper(f)); + } } From ceffe074a9145f8f306af07fb8e21b0e0e6651d9 Mon Sep 17 00:00:00 2001 From: okumin Date: Tue, 8 Mar 2022 02:49:38 +0900 Subject: [PATCH 215/417] Keep consistent read size after closing MessageUnpacker (#621) --- .../java/org/msgpack/core/MessageUnpacker.java | 1 + .../org/msgpack/core/MessageUnpackerTest.scala | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index c59b742ac..ff638b744 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -1735,6 +1735,7 @@ private int readNextLength32() public void close() throws IOException { + totalReadBytes += position; buffer = EMPTY_BUFFER; position = 0; in.close(); diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 720885c45..3ea5e911d 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -254,6 +254,9 @@ class MessageUnpackerTest extends AirSpec with Benchmark { } count shouldBe 6 unpacker.getTotalReadBytes shouldBe arr.length + + unpacker.close() + unpacker.getTotalReadBytes shouldBe arr.length } } @@ -268,6 +271,9 @@ class MessageUnpackerTest extends AirSpec with Benchmark { skipCount shouldBe 2 unpacker.getTotalReadBytes shouldBe testData.length + + unpacker.close() + unpacker.getTotalReadBytes shouldBe testData.length } } @@ -322,6 +328,9 @@ class MessageUnpackerTest extends AirSpec with Benchmark { ib.result() shouldBe intSeq.toSeq unpacker.getTotalReadBytes shouldBe testData2.length + + unpacker.close() + unpacker.getTotalReadBytes shouldBe testData2.length } } @@ -352,6 +361,9 @@ class MessageUnpackerTest extends AirSpec with Benchmark { } count shouldBe numElems unpacker.getTotalReadBytes shouldBe data.length + + unpacker.close() + unpacker.getTotalReadBytes shouldBe data.length } } } @@ -869,6 +881,9 @@ class MessageUnpackerTest extends AirSpec with Benchmark { unpacker.unpackInt shouldBe 1 unpacker.getTotalReadBytes shouldBe arr.length + + unpacker.close() + unpacker.getTotalReadBytes shouldBe arr.length } } } From 3670c640a91e70266f2cb568ec2bb5ebf459d198 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 7 Mar 2022 18:49:54 +0100 Subject: [PATCH 216/417] Update sbt to 1.5.8 (#615) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 71aac7fe5..c456baca7 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.5.6 +sbt.version=1.5.8 From ea5f407b851700fc400fb8c2b81dc81148eee168 Mon Sep 17 00:00:00 2001 From: zbuster05 <41530680+zbuster05@users.noreply.github.com> Date: Mon, 7 Mar 2022 09:50:44 -0800 Subject: [PATCH 217/417] Fixed examples relative link in README (#622) * Fixed examples relative link in README. On the message pack mirror of the readme, since this is relatively linked, it attempts to route to the location https://msgpack.org/msgpack/msgpack-java/blob/develop/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java which subsequently returns a 404. Statically linking the domain should fix this issue and look a lot more professional. * Fixed other instances --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c5af97cdf..4035fdc40 100644 --- a/README.md +++ b/README.md @@ -40,14 +40,14 @@ dependencies { } ``` -- [Usage examples](msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java) +- [Usage examples](https://github.com/msgpack/msgpack-java/blob/develop/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java) ### Integration with Jackson ObjectMapper (jackson-databind) msgpack-java supports serialization and deserialization of Java objects through [jackson-databind](https://github.com/FasterXML/jackson-databind). -For details, see [msgpack-jackson/README.md](msgpack-jackson/README.md). The template-based serialization mechanism used in v06 is deprecated. +For details, see [msgpack-jackson/README.md](https://github.com/msgpack/msgpack-java/blob/develop/msgpack-jackson/README.md). The template-based serialization mechanism used in v06 is deprecated. -- [Release Notes](RELEASE_NOTES.md) +- [Release Notes](https://github.com/msgpack/msgpack-java/blob/develop/RELEASE_NOTES.md) ## For MessagePack Developers [![Travis CI](https://travis-ci.org/msgpack/msgpack-java.svg?branch=v07-develop)](https://travis-ci.org/msgpack/msgpack-java) From 3442714f66e7c671598cc354ac140afe4bdd30c3 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 7 Mar 2022 18:50:58 +0100 Subject: [PATCH 218/417] Update sbt-scalafmt to 2.4.6 (#616) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 1609ca903..59821f87e 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,7 +5,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.5") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") scalacOptions ++= Seq("-deprecation", "-feature") From a8f05e6b1336ae0decd14dd38ff4246c453f6b56 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 7 Mar 2022 18:51:11 +0100 Subject: [PATCH 219/417] Update junit-interface to 0.13.3 (#617) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index b8c4b9d5b..2b49fcbf9 100644 --- a/build.sbt +++ b/build.sbt @@ -46,7 +46,7 @@ val buildSettings = Seq[Setting[_]]( Test / compile := ((Test / compile) dependsOn (Test / jcheckStyle)).value ) -val junitInterface = "com.github.sbt" % "junit-interface" % "0.13.2" % "test" +val junitInterface = "com.github.sbt" % "junit-interface" % "0.13.3" % "test" // Project settings lazy val root = Project(id = "msgpack-java", base = file(".")) From 14624bd413e826b8fc70f179ab4d7dc603155df0 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 7 Mar 2022 18:51:33 +0100 Subject: [PATCH 220/417] Update airframe-json, airspec to 22.2.0 (#626) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 2b49fcbf9..19d73c857 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "21.12.1" +val AIRFRAME_VERSION = "22.2.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 3272530d19a6f944b9f03a1ad3dc49ad2e34f0aa Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 7 Mar 2022 18:53:19 +0100 Subject: [PATCH 221/417] Update akka-actor to 2.6.18 (#614) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 19d73c857..f17edd64c 100644 --- a/build.sbt +++ b/build.sbt @@ -84,7 +84,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka - "com.typesafe.akka" %% "akka-actor" % "2.6.17" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.6.18" % "test", "org.scala-lang.modules" %% "scala-collection-compat" % "2.6.0" % "test" ) ) From d0f47d4823c76d2e7aa5f9c43d5743777524df90 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 7 Mar 2022 10:22:41 -0800 Subject: [PATCH 222/417] 0.9.1 release notes --- RELEASE_NOTES.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4f00c472d..a8e81de55 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,26 @@ # Release Notes +## 0.9.1 + +Bug fixes and improvements: + +- Keep consistent read size after closing MessageUnpacker (#621) @okumin +- Fixed examples relative link in README (#622) @zbuster05 +- Add an ObjectMapper shorthand @cyberdelia (#620) +- Specify the bufferSize of the ArrayBufferOutput (#597) @szh + +Internal updates: + +- Update akka-actor to 2.6.18 (#614) @Scala Steward +- Update airframe-json, airspec to 22.2.0 (#626) @Scala Steward +- Update junit-interface to 0.13.3 (#617) @Scala Steward +- Update sbt-scalafmt to 2.4.6 (#616) @Scala Steward +- Upgrade sbt to 1.5.6 (#610) @Taro L. Saito +- Update scala-collection-compat to 2.6.0 (#604) @Scala Steward + +Known issues: +- Unpack method doesn't work in JDK17 https://github.com/msgpack/msgpack-java/issues/600 + ## 0.9.0 This version support reading and writing [Timestamp values](https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type). From 5adf9790f5c57e07d76f4c2b3ebdf07274798caa Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 11 Mar 2022 01:14:55 +0100 Subject: [PATCH 223/417] Update sbt to 1.6.2 (#630) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index c456baca7..022b635bb 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.5.8 +sbt.version=1.6.2 From 4d2acc775414250e7258a0ca926ed98a3e4316a8 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 25 May 2022 08:21:48 +0200 Subject: [PATCH 224/417] Update airframe-json, airspec to 22.5.0 (#643) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f17edd64c..da190027d 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.2.0" +val AIRFRAME_VERSION = "22.5.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From f21c8867ff59dd80f1bbb7b6af1bb364e6aafac0 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 25 May 2022 08:21:57 +0200 Subject: [PATCH 225/417] Update sbt-sonatype to 3.9.13 (#644) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 59821f87e..4b437b7cc 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.10") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.13") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From af42f3f766b237098e1ebf6d13493edcf57c3cea Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 25 May 2022 08:22:27 +0200 Subject: [PATCH 226/417] Update scala-collection-compat to 2.7.0 (#632) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index da190027d..f0ec7f961 100644 --- a/build.sbt +++ b/build.sbt @@ -85,7 +85,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.18" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.6.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.7.0" % "test" ) ) From 294c7cc2b63ab637a6a5afa42aeff05ffb11c2c6 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 25 May 2022 08:22:36 +0200 Subject: [PATCH 227/417] Update scalacheck to 1.16.0 (#636) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f0ec7f961..5d01030ec 100644 --- a/build.sbt +++ b/build.sbt @@ -80,7 +80,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.15.4" % "test", + "org.scalacheck" %% "scalacheck" % "1.16.0" % "test", // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka From b07e5f4f349d53a2244f1a02b32558a033326d37 Mon Sep 17 00:00:00 2001 From: xerial-bot Date: Fri, 3 Jun 2022 13:24:38 -0700 Subject: [PATCH 228/417] Update airframe-json, airspec to 22.6.1 (#649) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 5d01030ec..5d29df7be 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.5.0" +val AIRFRAME_VERSION = "22.6.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 7ba38b10ca56236d64c9f1718df69895e0a8c410 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 3 Jun 2022 22:24:56 +0200 Subject: [PATCH 229/417] Update akka-actor to 2.6.19 (#631) * Update akka-actor to 2.6.19 * Revert commit(s) 8decc5c2 * Update akka-actor to 2.6.19 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 5d29df7be..25bc87bba 100644 --- a/build.sbt +++ b/build.sbt @@ -84,7 +84,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka - "com.typesafe.akka" %% "akka-actor" % "2.6.18" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.6.19" % "test", "org.scala-lang.modules" %% "scala-collection-compat" % "2.7.0" % "test" ) ) From 4469bf69fa3d62494441ec10146d3445367b3c39 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 5 Jun 2022 21:31:33 +0900 Subject: [PATCH 230/417] Use jackson-databind 2.13.3 for CVE-2020-36518 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 25bc87bba..990aed1b9 100644 --- a/build.sbt +++ b/build.sbt @@ -102,7 +102,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.3", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From dadb7551ae84aa0698525d9d1e2fb9857efbf13d Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Tue, 7 Jun 2022 22:35:00 +0900 Subject: [PATCH 231/417] Fix testComplexTypeKey() --- .../jackson/dataformat/MessagePackGeneratorTest.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index e2c202bc3..9c66fa055 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -663,7 +663,9 @@ public void testNonStringKey() ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); if (mapHolder instanceof NonStringKeyMapHolderWithoutAnnotation) { - objectMapper.setSerializerFactory(new MessagePackSerializerFactory()); + SimpleModule mod = new SimpleModule("test"); + mod.addKeySerializer(TinyPojo.class, new MessagePackKeySerializer()); + objectMapper.registerModule(mod); } byte[] bytes = objectMapper.writeValueAsBytes(mapHolder); @@ -709,7 +711,9 @@ public void testComplexTypeKey() map.put(pojo, 42); ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - objectMapper.setSerializerFactory(new MessagePackSerializerFactory()); + SimpleModule mod = new SimpleModule("test"); + mod.addKeySerializer(TinyPojo.class, new MessagePackKeySerializer()); + objectMapper.registerModule(mod); byte[] bytes = objectMapper.writeValueAsBytes(map); MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes); @@ -731,7 +735,9 @@ public void testComplexTypeKeyWithV06Format() ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); - objectMapper.setSerializerFactory(new MessagePackSerializerFactory()); + SimpleModule mod = new SimpleModule("test"); + mod.addKeySerializer(TinyPojo.class, new MessagePackKeySerializer()); + objectMapper.registerModule(mod); byte[] bytes = objectMapper.writeValueAsBytes(map); MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes); From 61c6910bc070479d8bd537011abf4812d869ada5 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 8 Jun 2022 23:51:43 +0900 Subject: [PATCH 232/417] Fix test --- .../msgpack/jackson/dataformat/MessagePackGeneratorTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index 9c66fa055..931a33f57 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -664,7 +664,7 @@ public void testNonStringKey() ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); if (mapHolder instanceof NonStringKeyMapHolderWithoutAnnotation) { SimpleModule mod = new SimpleModule("test"); - mod.addKeySerializer(TinyPojo.class, new MessagePackKeySerializer()); + mod.addKeySerializer(Object.class, new MessagePackKeySerializer()); objectMapper.registerModule(mod); } From 4c5d180dc29efb81f305f65e7299072d5c33a5d5 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 12 Jun 2022 17:21:23 +0900 Subject: [PATCH 233/417] Add how to internally represent BigDecimal as str to the doc --- msgpack-jackson/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index f1710ff24..d3c779861 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -224,6 +224,22 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial System.out.println(deserialized); // => {42=Hello} ``` +### Serialize and deserialize BigDecimal as str type internally in MessagePack format + +`jackson-dataformat-msgpack` represents BigDecimal values as float type in MessagePack format by default. When you want to handle BigDeciaml values as str type with arbitrary precision in MessagePack format, you can use `com.fasterxml.jackson.databind.cfg.MutableConfigOverride#setFormat` like this: + +```java + ObjectMapper mapper = new ObjectMapper(new MessagePackFactory()); + mapper.configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); + + Pojo obj = new Pojo(); + obj.value = new BigDecimal("1234567890.98765432100"); + + byte[] converted = mapper.writeValueAsBytes(obj); + + System.out.println(mapper.readValue(converted, Pojo.class)); // => Pojo{value=1234567890.98765432100} +``` + ### Deserialize extension types with ExtensionTypeCustomDeserializers `ExtensionTypeCustomDeserializers` helps you to deserialize extension types easily. From b7ba3973c8e96cd739d73331066b4496bc2c3ee1 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 18 Jun 2022 14:19:48 +0900 Subject: [PATCH 234/417] Update RELEASE_NOTES for 0.9.2 --- RELEASE_NOTES.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index a8e81de55..c3d625902 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,18 @@ # Release Notes +## 0.9.2 + +Internal updates: + +* Update jackson-databind to 2.13.3 [#650](http://github.com/msgpack/msgpack-java/pull/650) +* Update akka-actor to 2.6.19 [#631](http://github.com/msgpack/msgpack-java/pull/631) +* Update airframe-json, airspec to 22.6.1 [#649](http://github.com/msgpack/msgpack-java/pull/649) +* Update scalacheck to 1.16.0 [#636](http://github.com/msgpack/msgpack-java/pull/636) +* Update scala-collection-compat to 2.7.0 [#632](http://github.com/msgpack/msgpack-java/pull/632) +* Update sbt-sonatype to 3.9.13 [#644](http://github.com/msgpack/msgpack-java/pull/644) +* Update airframe-json, airspec to 22.5.0 [#643](http://github.com/msgpack/msgpack-java/pull/643) +* Update sbt to 1.6.2 [#630](http://github.com/msgpack/msgpack-java/pull/630) + ## 0.9.1 Bug fixes and improvements: From 1346a031cf483b0650f08c2270e78c73c584a122 Mon Sep 17 00:00:00 2001 From: xerial-bot Date: Mon, 27 Jun 2022 23:56:29 -0700 Subject: [PATCH 235/417] Update airframe-json, airspec to 22.6.4 (#659) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 990aed1b9..274545e2f 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.6.1" +val AIRFRAME_VERSION = "22.6.4" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From d665284264cbcf11917e2659d886bd881b098bdf Mon Sep 17 00:00:00 2001 From: Torsten Mehnert <92546601+tmehnert@users.noreply.github.com> Date: Tue, 28 Jun 2022 09:05:48 +0200 Subject: [PATCH 236/417] Use SPDX-ID in license name (#653) Change the license name to the SPDX-ID equivalent. See: https://spdx.org/licenses/ --- NOTICE | 2 +- sonatype.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NOTICE b/NOTICE index bc6328dba..93b2e28bd 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ This product includes the software developed by third-party: - * Google Guava https://code.google.com/p/guava-libraries/ (APL2) + * Google Guava https://code.google.com/p/guava-libraries/ (Apache-2.0) * sbt-extras: https://github.com/paulp/sbt-extras (BSD) (LICENSE.sbt-extras.txt) diff --git a/sonatype.sbt b/sonatype.sbt index f016335a0..3fcb592f9 100644 --- a/sonatype.sbt +++ b/sonatype.sbt @@ -2,7 +2,7 @@ import xerial.sbt.Sonatype._ ThisBuild / sonatypeProfileName := "org.msgpack" ThisBuild / homepage := Some(url("https://msgpack.org/")) -ThisBuild / licenses := Seq("APL2" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")) +ThisBuild / licenses := Seq("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")) ThisBuild / scmInfo := Some( ScmInfo( url("https://github.com/msgpack/msgpack-java"), From 117f1612fc3c08741a8acb159e52aa5d29c50988 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Jun 2022 22:09:48 +0900 Subject: [PATCH 237/417] Support JDK17 (#660) * Reproduce #600 (JDK17 error) * Add workaround for Java17 * Add a helpful error message * Add note on JDK17 --- .github/workflows/CI.yml | 28 ++++++++++-- README.md | 9 ++++ build.sbt | 7 +++ .../core/buffer/DirectBufferAccess.java | 44 ++++++++++++------- .../core/buffer/DirectBufferAccessTest.scala | 29 ++++++++++++ 5 files changed, 96 insertions(+), 21 deletions(-) create mode 100644 msgpack-core/src/test/scala/org/msgpack/core/buffer/DirectBufferAccessTest.scala diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f289bc708..f845825e6 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -26,14 +26,33 @@ jobs: - uses: actions/checkout@v2 - name: jcheckstyle run: ./sbt jcheckStyle + test_jdk17: + name: Test JDK17 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: '17' + - uses: actions/cache@v2 + with: + path: ~/.cache + key: ${{ runner.os }}-jdk11-${{ hashFiles('**/*.sbt') }} + restore-keys: ${{ runner.os }}-jdk17- + - name: Test + run: ./sbt test + - name: Universal Buffer Test + run: ./sbt test -J-Dmsgpack.universal-buffer=true test_jdk11: name: Test JDK11 runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: olafurpg/setup-scala@v10 + - uses: actions/setup-java@v3 with: - java-version: adopt@1.11 + distribution: 'zulu' + java-version: '11' - uses: actions/cache@v2 with: path: ~/.cache @@ -48,9 +67,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: olafurpg/setup-scala@v10 + - uses: actions/setup-java@v3 with: - java-version: adopt@1.8 + distribution: 'zulu' + java-version: '8' - uses: actions/cache@v2 with: path: ~/.cache diff --git a/README.md b/README.md index 4035fdc40..7723eb6ea 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,15 @@ dependencies { - [Usage examples](https://github.com/msgpack/msgpack-java/blob/develop/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java) +### Java 17 Support + +For using DirectByteBuffer (off-heap memory access methods) in JDK17, you need to specify two JVM options: +``` +--add-opens=java.base/java.nio=ALL-UNNAMED +--add-opens=java.base/sun.nio.ch=ALL-UNNAMED +``` + + ### Integration with Jackson ObjectMapper (jackson-databind) msgpack-java supports serialization and deserialization of Java objects through [jackson-databind](https://github.com/FasterXML/jackson-databind). diff --git a/build.sbt b/build.sbt index 274545e2f..0154bf5a8 100644 --- a/build.sbt +++ b/build.sbt @@ -74,6 +74,13 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack.value.impl" ), testFrameworks += new TestFramework("wvlet.airspec.Framework"), + Test / javaOptions ++= Seq( + // --add-opens is not available in JDK8 + "-XX:+IgnoreUnrecognizedVMOptions", + "--add-opens=java.base/java.nio=ALL-UNNAMED", + "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED" + ), + Test / fork := true, libraryDependencies ++= Seq( // msgpack-core should have no external dependencies junitInterface, diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java index cde2e6eca..f54c50b9a 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java @@ -18,11 +18,13 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.security.AccessController; import java.security.PrivilegedAction; import sun.misc.Unsafe; +import sun.nio.ch.DirectBuffer; /** * Wraps the difference of access methods to DirectBuffers between Android and others. @@ -30,7 +32,8 @@ class DirectBufferAccess { private DirectBufferAccess() - {} + { + } enum DirectBufferConstructorType { @@ -40,7 +43,6 @@ enum DirectBufferConstructorType ARGS_MB_INT_INT } - static Method mGetAddress; // For Java <=8, gets a sun.misc.Cleaner static Method mCleaner; static Method mClean; @@ -95,10 +97,19 @@ enum DirectBufferConstructorType if (byteBufferConstructor == null) { throw new RuntimeException("Constructor of DirectByteBuffer is not found"); } - byteBufferConstructor.setAccessible(true); - mGetAddress = directByteBufferClass.getDeclaredMethod("address"); - mGetAddress.setAccessible(true); + try { + byteBufferConstructor.setAccessible(true); + } + catch (RuntimeException e) { + // This is a Java9+ exception, so we need to detect it without importing it for Java8 support + if ("java.lang.reflect.InaccessibleObjectException".equals(e.getClass().getName())) { + byteBufferConstructor = null; + } + else { + throw e; + } + } if (MessageBuffer.javaVersion <= 8) { setupCleanerJava6(direct); @@ -160,6 +171,7 @@ public Object run() /** * Checks if we have a usable {@link DirectByteBuffer#cleaner}. + * * @param direct a direct buffer * @return the method or an error */ @@ -184,6 +196,7 @@ private static Object getCleanerMethod(ByteBuffer direct) /** * Checks if we have a usable {@link sun.misc.Cleaner#clean}. + * * @param direct a direct buffer * @param mCleaner the {@link DirectByteBuffer#cleaner} method * @return the method or null @@ -210,6 +223,7 @@ private static Object getCleanMethod(ByteBuffer direct, Method mCleaner) /** * Checks if we have a usable {@link Unsafe#invokeCleaner}. + * * @param direct a direct buffer * @return the method or an error */ @@ -218,7 +232,7 @@ private static Object getInvokeCleanerMethod(ByteBuffer direct) try { // See https://bugs.openjdk.java.net/browse/JDK-8171377 Method m = MessageBuffer.unsafe.getClass().getDeclaredMethod( - "invokeCleaner", ByteBuffer.class); + "invokeCleaner", ByteBuffer.class); m.invoke(MessageBuffer.unsafe, direct); return m; } @@ -233,17 +247,9 @@ private static Object getInvokeCleanerMethod(ByteBuffer direct) } } - static long getAddress(Object base) + static long getAddress(Buffer buffer) { - try { - return (Long) mGetAddress.invoke(base); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - catch (InvocationTargetException e) { - throw new RuntimeException(e); - } + return ((DirectBuffer) buffer).address(); } static void clean(Object base) @@ -253,7 +259,7 @@ static void clean(Object base) Object cleaner = mCleaner.invoke(base); mClean.invoke(cleaner); } - else { + else { mInvokeCleaner.invoke(MessageBuffer.unsafe, base); } } @@ -269,6 +275,10 @@ static boolean isDirectByteBufferInstance(Object s) static ByteBuffer newByteBuffer(long address, int index, int length, ByteBuffer reference) { + if (byteBufferConstructor == null) { + throw new IllegalStateException("Can't create a new DirectByteBuffer. In JDK17+, two JVM options needs to be set: " + + "--add-opens=java.base/java.nio=ALL-UNNAMED and --add-opens=java.base/sun.nio.ch=ALL-UNNAMED"); + } try { switch (directBufferConstructorType) { case ARGS_LONG_INT_REF: diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/DirectBufferAccessTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/DirectBufferAccessTest.scala new file mode 100644 index 000000000..40f4c7708 --- /dev/null +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/DirectBufferAccessTest.scala @@ -0,0 +1,29 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.core.buffer + +import wvlet.airspec.AirSpec + +import java.nio.ByteBuffer + +class DirectBufferAccessTest extends AirSpec { + + test("instantiate DirectBufferAccess") { + val bb = ByteBuffer.allocateDirect(1) + val addr = DirectBufferAccess.getAddress(bb) + + } +} From 36f601a044f3ca325ecd87d5a2e2ee091dc59714 Mon Sep 17 00:00:00 2001 From: xerial-bot Date: Tue, 28 Jun 2022 06:10:53 -0700 Subject: [PATCH 238/417] Update akka-actor to 2.6.19 (#647) From d502fa122d8072886e8b73936e3d2634b25d8350 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 28 Jun 2022 22:19:36 +0900 Subject: [PATCH 239/417] 0.9.3 release notes --- RELEASE_NOTES.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c3d625902..367ab9172 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,21 @@ # Release Notes +## 0.9.3 + +This version supports JDK17 [#660](http://github.com/msgpack/msgpack-java/pull/660). + +Important: If you need to use DirectByteBuffer (raw memory access) in JDK17 or later, specify two JVM options to allow accessing +native memory: +``` +--add-opens=java.base/java.nio=ALL-UNNAMED +--add-opens=java.base/sun.nio.ch=ALL-UNNAMED +``` +Internal updates: + +* Use SPDX-ID in license name [#653](http://github.com/msgpack/msgpack-java/pull/653) +* Update airframe-json, airspec to 22.6.4 [#659](http://github.com/msgpack/msgpack-java/pull/659) +* Update akka-actor to 2.6.19 [#647](http://github.com/msgpack/msgpack-java/pull/647) + ## 0.9.2 Internal updates: From 192457c6b731efc4bc61432aa0579fa66dd2b5fe Mon Sep 17 00:00:00 2001 From: xerial-bot Date: Sat, 9 Jul 2022 03:23:27 -0700 Subject: [PATCH 240/417] Update scala-collection-compat to 2.8.0 (#663) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0154bf5a8..95effdb37 100644 --- a/build.sbt +++ b/build.sbt @@ -92,7 +92,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.19" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.7.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.8.0" % "test" ) ) From 7108f4db3dfcb44e9315297ce0202d25a74d3200 Mon Sep 17 00:00:00 2001 From: xerial-bot Date: Sat, 9 Jul 2022 03:23:35 -0700 Subject: [PATCH 241/417] Update airframe-json, airspec to 22.7.1 (#662) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 95effdb37..05a104bf3 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.6.4" +val AIRFRAME_VERSION = "22.7.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 5ead37e9c558f3a12d729cfdb6086417c3e837f3 Mon Sep 17 00:00:00 2001 From: xerial-bot Date: Wed, 13 Jul 2022 17:13:08 -0700 Subject: [PATCH 242/417] Update sbt to 1.7.1 (#666) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 022b635bb..38c0109bf 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.6.2 +sbt.version=1.7.1 From ee40181bef0dd9dea9ab6d03054328167b2b4bd5 Mon Sep 17 00:00:00 2001 From: xerial-bot Date: Wed, 13 Jul 2022 17:13:22 -0700 Subject: [PATCH 243/417] Update airframe-json, airspec to 22.7.2 (#668) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 05a104bf3..3dcd3bcac 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.7.1" +val AIRFRAME_VERSION = "22.7.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 64bf2e25bb6a6f72793a755e83539de98a1f7a3c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 18 Jul 2022 08:16:54 +0200 Subject: [PATCH 244/417] Update sbt to 1.7.1 (#669) From bc0d03c3c7c77d67ef8e20ae99db1bb78f97d5fc Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 14 Sep 2022 20:16:21 +0900 Subject: [PATCH 245/417] Support timestamp extension in jackson-dataformat-msgpack (#677) * Support JDK8 to handle Instant * Add TimestampExtensionModule * Add TimestampExtensionModuleTest * Add a few more tests * Use msgpack-core's serde for timestamp internally * Add a test for 96-bit format * Revert "Support JDK8 to handle Instant" This reverts commit 33cdf2de163fa2a892a8dab904e1d6bed1f30c6f. * Take care of "No newline at end of file" * Fix format * Handle checkstyle error "Utility classes should not have a public or default constructor" * Clean up * Add some test for serializing * Add how to use TimestampExtensionModule in the doc --- msgpack-jackson/README.md | 20 +- .../dataformat/TimestampExtensionModule.java | 82 +++++++ .../TimestampExtensionModuleTest.java | 218 ++++++++++++++++++ 3 files changed, 319 insertions(+), 1 deletion(-) create mode 100755 msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/TimestampExtensionModule.java create mode 100755 msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/TimestampExtensionModuleTest.java diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index d3c779861..7e8597815 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -240,9 +240,27 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial System.out.println(mapper.readValue(converted, Pojo.class)); // => Pojo{value=1234567890.98765432100} ``` +### Serialize and deserialize Instant instances as MessagePack extension type + +`timestamp` extension type is defined in MessagePack as type:-1. Registering `TimestampExtensionModule.INSTANCE` module enables automatic serialization and deserialization of java.time.Instant to/from the MessagePack extension type. + +```java + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()) + .registerModule(TimestampExtensionModule.INSTANCE); + Pojo pojo = new Pojo(); + // The type of `timestamp` variable is Instant + pojo.timestamp = Instant.now(); + byte[] bytes = objectMapper.writeValueAsBytes(pojo); + + // The Instant instance is serialized as MessagePack extension type (type: -1) + + Pojo deserialized = objectMapper.readValue(bytes, Pojo.class); + System.out.println(deserialized); // "2022-09-14T08:47:24.922Z" +``` + ### Deserialize extension types with ExtensionTypeCustomDeserializers -`ExtensionTypeCustomDeserializers` helps you to deserialize extension types easily. +`ExtensionTypeCustomDeserializers` helps you to deserialize your own custom extension types easily. #### Deserialize extension type value directly diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/TimestampExtensionModule.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/TimestampExtensionModule.java new file mode 100755 index 000000000..2216d2769 --- /dev/null +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/TimestampExtensionModule.java @@ -0,0 +1,82 @@ +package org.msgpack.jackson.dataformat; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.msgpack.core.ExtensionTypeHeader; +import org.msgpack.core.MessagePack; +import org.msgpack.core.MessagePacker; +import org.msgpack.core.MessageUnpacker; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.time.Instant; + +public class TimestampExtensionModule +{ + public static final byte EXT_TYPE = -1; + public static final SimpleModule INSTANCE = new SimpleModule("msgpack-ext-timestamp"); + + static { + INSTANCE.addSerializer(Instant.class, new InstantSerializer(Instant.class)); + INSTANCE.addDeserializer(Instant.class, new InstantDeserializer(Instant.class)); + } + + private static class InstantSerializer extends StdSerializer + { + protected InstantSerializer(Class t) + { + super(t); + } + + @Override + public void serialize(Instant value, JsonGenerator gen, SerializerProvider provider) + throws IOException + { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + // MEMO: Reusing these MessagePacker and MessageUnpacker instances would improve the performance + try (MessagePacker packer = MessagePack.newDefaultPacker(os)) { + packer.packTimestamp(value); + } + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(os.toByteArray())) { + ExtensionTypeHeader header = unpacker.unpackExtensionTypeHeader(); + byte[] bytes = unpacker.readPayload(header.getLength()); + + MessagePackExtensionType extensionType = new MessagePackExtensionType(EXT_TYPE, bytes); + gen.writeObject(extensionType); + } + } + } + + private static class InstantDeserializer extends StdDeserializer + { + protected InstantDeserializer(Class vc) + { + super(vc); + } + + @Override + public Instant deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException + { + MessagePackExtensionType ext = p.readValueAs(MessagePackExtensionType.class); + if (ext.getType() != EXT_TYPE) { + throw new RuntimeException( + String.format("Unexpected extension type (0x%X) for Instant object", ext.getType())); + } + + // MEMO: Reusing this MessageUnpacker instance would improve the performance + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(ext.getData())) { + return unpacker.unpackTimestamp(new ExtensionTypeHeader(EXT_TYPE, ext.getData().length)); + } + } + } + + private TimestampExtensionModule() + { + } +} diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/TimestampExtensionModuleTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/TimestampExtensionModuleTest.java new file mode 100755 index 000000000..05851dbc2 --- /dev/null +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/TimestampExtensionModuleTest.java @@ -0,0 +1,218 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.jackson.dataformat; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Before; +import org.junit.Test; +import org.msgpack.core.MessagePack; +import org.msgpack.core.MessagePacker; +import org.msgpack.core.MessageUnpacker; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.time.Instant; + +import static org.junit.Assert.assertEquals; + +public class TimestampExtensionModuleTest +{ + private final ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + private final SingleInstant singleInstant = new SingleInstant(); + private final TripleInstants tripleInstants = new TripleInstants(); + + private static class SingleInstant + { + public Instant instant; + } + + private static class TripleInstants + { + public Instant a; + public Instant b; + public Instant c; + } + + @Before + public void setUp() + throws Exception + { + objectMapper.registerModule(TimestampExtensionModule.INSTANCE); + } + + @Test + public void testSingleInstantPojo() + throws IOException + { + singleInstant.instant = Instant.now(); + byte[] bytes = objectMapper.writeValueAsBytes(singleInstant); + SingleInstant deserialized = objectMapper.readValue(bytes, SingleInstant.class); + assertEquals(singleInstant.instant, deserialized.instant); + } + + @Test + public void testTripleInstantsPojo() + throws IOException + { + Instant now = Instant.now(); + tripleInstants.a = now.minusSeconds(1); + tripleInstants.b = now; + tripleInstants.c = now.plusSeconds(1); + byte[] bytes = objectMapper.writeValueAsBytes(tripleInstants); + TripleInstants deserialized = objectMapper.readValue(bytes, TripleInstants.class); + assertEquals(now.minusSeconds(1), deserialized.a); + assertEquals(now, deserialized.b); + assertEquals(now.plusSeconds(1), deserialized.c); + } + + @Test + public void serialize32BitFormat() + throws IOException + { + singleInstant.instant = Instant.ofEpochSecond(Instant.now().getEpochSecond()); + + byte[] bytes = objectMapper.writeValueAsBytes(singleInstant); + + // Check the size of serialized data first + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes)) { + unpacker.unpackMapHeader(); + assertEquals("instant", unpacker.unpackString()); + assertEquals(4, unpacker.unpackExtensionTypeHeader().getLength()); + } + + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes)) { + unpacker.unpackMapHeader(); + unpacker.unpackString(); + assertEquals(singleInstant.instant, unpacker.unpackTimestamp()); + } + } + + @Test + public void serialize64BitFormat() + throws IOException + { + singleInstant.instant = Instant.ofEpochSecond(Instant.now().getEpochSecond(), 1234); + + byte[] bytes = objectMapper.writeValueAsBytes(singleInstant); + + // Check the size of serialized data first + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes)) { + unpacker.unpackMapHeader(); + assertEquals("instant", unpacker.unpackString()); + assertEquals(8, unpacker.unpackExtensionTypeHeader().getLength()); + } + + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes)) { + unpacker.unpackMapHeader(); + unpacker.unpackString(); + assertEquals(singleInstant.instant, unpacker.unpackTimestamp()); + } + } + + @Test + public void serialize96BitFormat() + throws IOException + { + singleInstant.instant = Instant.ofEpochSecond(19880866800L /* 2600-01-01 */, 1234); + + byte[] bytes = objectMapper.writeValueAsBytes(singleInstant); + + // Check the size of serialized data first + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes)) { + unpacker.unpackMapHeader(); + assertEquals("instant", unpacker.unpackString()); + assertEquals(12, unpacker.unpackExtensionTypeHeader().getLength()); + } + + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes)) { + unpacker.unpackMapHeader(); + unpacker.unpackString(); + assertEquals(singleInstant.instant, unpacker.unpackTimestamp()); + } + } + + @Test + public void deserialize32BitFormat() + throws IOException + { + Instant instant = Instant.ofEpochSecond(Instant.now().getEpochSecond()); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try (MessagePacker packer = MessagePack.newDefaultPacker(os)) { + packer.packMapHeader(1) + .packString("instant") + .packTimestamp(instant); + } + + byte[] bytes = os.toByteArray(); + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes)) { + unpacker.unpackMapHeader(); + unpacker.unpackString(); + assertEquals(4, unpacker.unpackExtensionTypeHeader().getLength()); + } + + SingleInstant deserialized = objectMapper.readValue(bytes, SingleInstant.class); + assertEquals(instant, deserialized.instant); + } + + @Test + public void deserialize64BitFormat() + throws IOException + { + Instant instant = Instant.ofEpochSecond(Instant.now().getEpochSecond(), 1234); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try (MessagePacker packer = MessagePack.newDefaultPacker(os)) { + packer.packMapHeader(1) + .packString("instant") + .packTimestamp(instant); + } + + byte[] bytes = os.toByteArray(); + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes)) { + unpacker.unpackMapHeader(); + unpacker.unpackString(); + assertEquals(8, unpacker.unpackExtensionTypeHeader().getLength()); + } + + SingleInstant deserialized = objectMapper.readValue(bytes, SingleInstant.class); + assertEquals(instant, deserialized.instant); + } + + @Test + public void deserialize96BitFormat() + throws IOException + { + Instant instant = Instant.ofEpochSecond(19880866800L /* 2600-01-01 */, 1234); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try (MessagePacker packer = MessagePack.newDefaultPacker(os)) { + packer.packMapHeader(1) + .packString("instant") + .packTimestamp(instant); + } + + byte[] bytes = os.toByteArray(); + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes)) { + unpacker.unpackMapHeader(); + unpacker.unpackString(); + assertEquals(12, unpacker.unpackExtensionTypeHeader().getLength()); + } + + SingleInstant deserialized = objectMapper.readValue(bytes, SingleInstant.class); + assertEquals(instant, deserialized.instant); + } +} From 48f67c6358953f67f6faf7f159f2dc488f1fc768 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 14 Sep 2022 18:43:45 +0200 Subject: [PATCH 246/417] Update airframe-json, airspec to 22.7.3 (#671) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3dcd3bcac..be91cf63b 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.7.2" +val AIRFRAME_VERSION = "22.7.3" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From d9379269c4e2188bf6a82b21121cf305f28c1d5a Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 14 Sep 2022 18:43:55 +0200 Subject: [PATCH 247/417] Update scala-collection-compat to 2.8.1 (#673) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index be91cf63b..52655492e 100644 --- a/build.sbt +++ b/build.sbt @@ -92,7 +92,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.19" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.8.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.8.1" % "test" ) ) From 112962c0a5a91b8c20b9ff0640a6b42c97b4db46 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 17 Sep 2022 02:05:57 +0200 Subject: [PATCH 248/417] Update airframe-json, airspec to 22.9.0 (#678) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 52655492e..7ae88df51 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.7.3" +val AIRFRAME_VERSION = "22.9.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 965564dc4548151f9572ab8d3fe4f477f8294a26 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 17 Sep 2022 02:06:09 +0200 Subject: [PATCH 249/417] Update akka-actor to 2.6.20 (#676) * Update akka-actor to 2.6.20 * Revert commit(s) 7d76a574 * Update akka-actor to 2.6.20 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 7ae88df51..b4992f3fd 100644 --- a/build.sbt +++ b/build.sbt @@ -91,7 +91,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka - "com.typesafe.akka" %% "akka-actor" % "2.6.19" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", "org.scala-lang.modules" %% "scala-collection-compat" % "2.8.1" % "test" ) ) From 44c939b9403cfcc88ce83143e025f6d256189944 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 17 Sep 2022 02:06:27 +0200 Subject: [PATCH 250/417] Update jackson-databind to 2.13.4 (#675) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index b4992f3fd..ce3ab0a7d 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.3", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 3c7ab6fb7dfc2ace9d53fb98e8018397f43a57fb Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 2 Nov 2022 07:27:15 +0100 Subject: [PATCH 251/417] Update airframe-json, airspec to 22.9.2 (#680) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ce3ab0a7d..0a14f8e32 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.9.0" +val AIRFRAME_VERSION = "22.9.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From e05285cf03a8d74b1c8db0cea7722b0d16826365 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 12 Nov 2022 00:16:38 +0100 Subject: [PATCH 252/417] Update sbt-sonatype to 3.9.14 (#686) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 4b437b7cc..1c9c463f7 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.13") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.14") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From 5aabe40da9ad368de0dd4a56c79d1f05ea929ee2 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 12 Nov 2022 00:17:01 +0100 Subject: [PATCH 253/417] Update airframe-json, airspec to 22.9.3 (#685) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0a14f8e32..570baaae0 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.9.2" +val AIRFRAME_VERSION = "22.9.3" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From e5763b2985a03c8468d94ca74458facdab5d69e1 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 14 Nov 2022 01:46:14 +0100 Subject: [PATCH 254/417] Update sbt-pgp to 2.2.0 (#683) * Update sbt-pgp to 2.2.0 * Revert commit(s) d0535a53 * Update sbt-pgp to 2.2.0 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 1c9c463f7..862592e61 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.14") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") From f1ac3dd322a03516e3dcdc6cbec7686e14b1c8f2 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 14 Nov 2022 01:46:23 +0100 Subject: [PATCH 255/417] Update scalacheck to 1.17.0 (#679) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 570baaae0..4a41598cc 100644 --- a/build.sbt +++ b/build.sbt @@ -87,7 +87,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.16.0" % "test", + "org.scalacheck" %% "scalacheck" % "1.17.0" % "test", // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka From a846ca11726cb7f688671fe4682e9bf87ae280f1 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 21 Jan 2023 07:47:06 +0100 Subject: [PATCH 256/417] Update sbt-sonatype to 3.9.15 (#696) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 862592e61..91d167e00 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.14") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.15") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From 5235a8304efb12c7d39ec97329474687be192edc Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 21 Jan 2023 07:47:23 +0100 Subject: [PATCH 257/417] Update scala-collection-compat to 2.9.0 (#697) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4a41598cc..3919448aa 100644 --- a/build.sbt +++ b/build.sbt @@ -92,7 +92,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.8.1" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.9.0" % "test" ) ) From b45c90e37e1701f9be800f98b0eab08e30249bb1 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 21 Jan 2023 07:47:32 +0100 Subject: [PATCH 258/417] Update sbt to 1.7.3 (#684) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 38c0109bf..b986067ee 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.7.1 +sbt.version=1.7.3 From d066051af1c47b58a3cf87cb52712d9a22e50ba7 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 21 Jan 2023 08:26:36 +0100 Subject: [PATCH 259/417] Update sbt-scalafmt to 2.5.0 (#689) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 91d167e00..7cb596d4c 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,7 +5,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.0") //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0") addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") scalacOptions ++= Seq("-deprecation", "-feature") From 00fc660637b811669a1e266c45cd2eda92bdade0 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 22 Jan 2023 01:31:38 +0900 Subject: [PATCH 260/417] Small improvement of msgpack-jackson bench (#705) Small improvment of msgpack-jackson bench --- .github/workflows/CI.yml | 1 + .../benchmark/MessagePackDataformatHugeDataBenchmarkTest.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f845825e6..d53a68bfc 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,6 +17,7 @@ on: - '**.java' - '**.sbt' - '.github/workflows/**.yml' + workflow_dispatch: jobs: code_format: diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java index b3a159111..fea34fd8b 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java @@ -30,7 +30,7 @@ public class MessagePackDataformatHugeDataBenchmarkTest { - private static final int ELM_NUM = 100000; + private static final int ELM_NUM = 1000000; private static final int COUNT = 6; private static final int WARMUP_COUNT = 4; private final ObjectMapper origObjectMapper = new ObjectMapper(); From ef8ad71af83b4241db30fcee9f12425c38d0f5ab Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 25 Jan 2023 09:56:15 +0100 Subject: [PATCH 261/417] Update sbt to 1.8.2 (#706) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index b986067ee..6cd347fab 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.7.3 +sbt.version=1.8.2 From 41cee04c2fe7558d985113756f0ab33da701add3 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 25 Jan 2023 09:56:27 +0100 Subject: [PATCH 262/417] Update airframe-json, airspec to 22.12.6 (#703) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3919448aa..c4f5ab2bd 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.9.3" +val AIRFRAME_VERSION = "22.12.6" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 45f287e5d4deefa604c253f68f75fc54390bb2d0 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 4 Feb 2023 01:22:49 +0100 Subject: [PATCH 263/417] Update sbt-sonatype to 3.9.17 (#710) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 7cb596d4c..6caa6bcb9 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.15") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.17") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From c83aa6ab83c3cf6a36c5c8af10e5756c02c7f39d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 4 Feb 2023 01:22:57 +0100 Subject: [PATCH 264/417] Update airframe-json, airspec to 23.1.4 (#708) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c4f5ab2bd..c67f74821 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "22.12.6" +val AIRFRAME_VERSION = "23.1.4" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From c796b29b5b0df7a1e2abebc0b80002273c25909e Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 4 Feb 2023 01:23:09 +0100 Subject: [PATCH 265/417] Update jackson-databind to 2.13.5 (#707) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c67f74821..462e8acf7 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.5", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 04d03d883ffbb6c7a277bf2552de5aa93465da11 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 4 Feb 2023 19:41:55 +0100 Subject: [PATCH 266/417] Update airframe-json, airspec to 23.2.0 (#712) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 462e8acf7..30c56e35e 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.1.4" +val AIRFRAME_VERSION = "23.2.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 211d349c7db614b7f1a011bc86dbce035bc82f24 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 4 Feb 2023 19:42:03 +0100 Subject: [PATCH 267/417] Update sbt-pgp to 2.2.1 (#698) * Update sbt-pgp to 2.2.1 * Revert commit(s) bae49c71 * Update sbt-pgp to 2.2.1 --------- Co-authored-by: Taro L. Saito --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 project/plugins.sbt diff --git a/project/plugins.sbt b/project/plugins.sbt old mode 100755 new mode 100644 index 6caa6bcb9..b2de1be91 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.17") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.0") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") From 6ba76dd3cf16c54540c3e24071ea6d72c8105d85 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 4 Feb 2023 19:44:20 +0100 Subject: [PATCH 268/417] Update jackson-databind to 2.14.2 (#711) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 30c56e35e..c5c7ac78b 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.5", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.14.2", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 8e3bc5117a00e851bac457e828102739742d3df7 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 6 Feb 2023 20:01:57 -0800 Subject: [PATCH 269/417] Introduce release drafter (#713) * Introduce release drafter * Target develop/main branches * Update README.md * Update README.md --- .github/release-drafter.yml | 55 +++++++++++++++++++++++++++ .github/workflows/release-drafter.yml | 32 ++++++++++++++++ README.md | 9 +---- 3 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 .github/release-drafter.yml create mode 100644 .github/workflows/release-drafter.yml diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 000000000..86a397680 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,55 @@ +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: '🔥 Breaking Changes' + labels: + - 'breaking' + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'bug' + - title: '👋 Deprecated' + labels: + - 'deprecation' + - title: '🔗 Dependency Updates' + labels: + - 'library-update' + - 'dependencies' + - title: '🛠 Internal Updates' + labels: + - 'internal' + - 'kaizen' + - 'test-library-update' + - 'sbt-plugin-update' + - title: '📚 Docs' + labels: + - 'doc' +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' + +template: | + ## What's Changed + + $CHANGES + + **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION + + +autolabeler: + - label: 'doc' + files: + - '*.md' + - label: 'feature' + title: + - '/(support|add)/i' + - label: 'bug' + title: + - '/fix/i' + - label: 'internal' + title: + - '/internal/i' + - label: 'deprecation' + title: + - '/deprecate/i' diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 000000000..6a48ed0ae --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,32 @@ +name: Release Drafter + +on: + push: + branches: + - develop + - main + # pull_request event is required only for autolabeler + pull_request: + # Only following types are handled by the action, but one can default to all as well + types: [opened, reopened, synchronize] + # pull_request_target event is required for autolabeler to support PRs from forks + pull_request_target: + types: [opened, reopened, synchronize] + +permissions: + contents: read + +jobs: + update_release_draft: + permissions: + # write permission is required to create a github release + contents: write + # write permission is required for autolabeler + # otherwise, read permission is required at least + pull-requests: write + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 7723eb6ea..8cad43c6f 100644 --- a/README.md +++ b/README.md @@ -82,10 +82,8 @@ Here is a list of sbt commands for daily development: > ~testOnly *MessagePackTest -- (pattern) # Run tests matching the pattern > project msgpack-core # Focus on a specific project > package # Create a jar file in the target folder of each project -> findbugs # Produce findbugs report in target/findbugs -> jacoco:cover # Report the code coverage of tests to target/jacoco folder > jcheckStyle # Run check style -> ;scalafmt;test:scalafmt;scalafmtSbt # Reformat Scala codes +> scalafmtAll # Reformat code ``` ### Publishing @@ -105,10 +103,7 @@ $ git tag v0.x.y $ git push origin v0.x.y ``` -To generate a release notes, you can use this command line: -``` -$ git log v(last version).. --oneline | cut -f 2- -d ' ' | perl -npe 's/(.*)\(\#([0-9]+)\)/* \1\[\#\2\]\(https:\/\/round-lake.dustinice.workers.dev:443\/http\/github.com\/msgpack\/msgpack-java\/pull\/\2\)/g' -``` +A draft of the next release note will be updated automatically at the [GitHub Releases](https://github.com/msgpack/msgpack-java/releases) page. For each PR merged, [release-drafter](https://github.com/release-drafter/release-drafter) will modify the release note draft. When you create a new release tag, edit and publish the draft of the release note. If necessary, adjust the version number and target tag. #### Publishing to Sonatype from Local Machine From 85c5392b6c49c2b71064e5fb2cd2cd448c01908b Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 6 Feb 2023 21:51:08 -0800 Subject: [PATCH 270/417] Update RELEASE_NOTES.md --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 367ab9172..3f8d8d9dd 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,7 @@ # Release Notes +The latest release notes will be available from the [GitHub release page](https://github.com/msgpack/msgpack-java/releases) + ## 0.9.3 This version supports JDK17 [#660](http://github.com/msgpack/msgpack-java/pull/660). From e7418c69e4899eaca8b5397b96c09ab18301bfef Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 6 Feb 2023 23:03:58 -0800 Subject: [PATCH 271/417] Classify PRs based on Scala-Steward PR body message --- .github/release-drafter.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 86a397680..79b084d76 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -53,3 +53,9 @@ autolabeler: - label: 'deprecation' title: - '/deprecate/i' + - label: 'library-update' + body: + - '/library-update/' + - label: 'test-library-update' + body: + - '/test-library-update/' From 7779615cf1b36486ab2f9cf4b05557ed8e8484ad Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 6 Feb 2023 23:07:14 -0800 Subject: [PATCH 272/417] Mark test library/sbt plugin updates as internal --- .github/release-drafter.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 79b084d76..2e6420f9f 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -56,6 +56,7 @@ autolabeler: - label: 'library-update' body: - '/library-update/' - - label: 'test-library-update' + - label: 'internal' body: - '/test-library-update/' + - '/sbt-plugin-update/' From 3381322f6c163154e927207509be11adfb755de0 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 6 Feb 2023 23:21:47 -0800 Subject: [PATCH 273/417] update sbt script (#714) --- sbt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbt b/sbt index 18c6b1125..0c5112ba7 100755 --- a/sbt +++ b/sbt @@ -34,11 +34,11 @@ set -o pipefail -declare -r sbt_release_version="1.5.5" -declare -r sbt_unreleased_version="1.6.0-M1" +declare -r sbt_release_version="1.8.2" +declare -r sbt_unreleased_version="1.8.2" -declare -r latest_213="2.13.7" -declare -r latest_212="2.12.15" +declare -r latest_213="2.13.10" +declare -r latest_212="2.12.17" declare -r latest_211="2.11.12" declare -r latest_210="2.10.7" declare -r latest_29="2.9.3" From 78080d18ffa29ff06d8d6160a3e7bf360d7bb859 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 27 Feb 2023 02:50:28 +0100 Subject: [PATCH 274/417] Update airframe-json, airspec to 23.2.5 (#717) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c5c7ac78b..286710037 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.2.0" +val AIRFRAME_VERSION = "23.2.5" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From e423757f3b7d7e1c2853e6624bf0fc410beb4ae1 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 10 Mar 2023 18:37:51 +0100 Subject: [PATCH 275/417] Update sbt-sonatype to 3.9.18 (#719) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index b2de1be91..1bcb3851a 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.17") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.18") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From 93d4bc0e1e6d375a5c2fb949c3a329d092ecf1e8 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 10 Mar 2023 18:38:03 +0100 Subject: [PATCH 276/417] Update airframe-json, airspec to 23.3.0 (#718) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 286710037..8dc03cadc 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.2.5" +val AIRFRAME_VERSION = "23.3.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 4bb8a03b00795ae74397261d53abeca9d02c3e30 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 29 Apr 2023 18:46:23 +0200 Subject: [PATCH 277/417] Update airframe-json, airspec to 23.3.4 (#723) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 8dc03cadc..e992a4d67 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.3.0" +val AIRFRAME_VERSION = "23.3.4" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 4853f0459b310e2520dcdffb93487368ee1d577f Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 29 Apr 2023 18:46:41 +0200 Subject: [PATCH 278/417] Update scala-collection-compat to 2.10.0 (#726) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index e992a4d67..fd414fac7 100644 --- a/build.sbt +++ b/build.sbt @@ -92,7 +92,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.9.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.10.0" % "test" ) ) From 6512662dbe15645bbb3567a9d115a82af73486ae Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 5 May 2023 18:24:36 +0200 Subject: [PATCH 279/417] Update airframe-json, airspec to 23.5.0 (#728) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index fd414fac7..9029b82ea 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.3.4" +val AIRFRAME_VERSION = "23.5.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From ce92979ec2be89a49969a89904884c399c18b67d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 5 May 2023 18:24:45 +0200 Subject: [PATCH 280/417] Update sbt-sonatype to 3.9.19 (#729) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 1bcb3851a..fa10c6648 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.18") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.19") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From 4d24d82b044f2f9506cf9b2a1bde0a571253ed64 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 11 May 2023 11:43:31 +0200 Subject: [PATCH 281/417] Update sbt-sonatype to 3.9.20 (#732) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index fa10c6648..f79c91e8c 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.19") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.20") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From f351e3fb934883f50002592b5f1a44e15df232df Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 11 May 2023 11:43:40 +0200 Subject: [PATCH 282/417] Update airframe-json, airspec to 23.5.2 (#731) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9029b82ea..b35f90be4 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.5.0" +val AIRFRAME_VERSION = "23.5.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 1e5483ffd7e7e791229e9956a36d797bbb01de4d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 22 May 2023 19:05:48 +0200 Subject: [PATCH 283/417] Update jackson-databind to 2.14.3 (#730) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index b35f90be4..7df0944be 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.14.2", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.14.3", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 727bdf9b84fcdc6d02545439c2a596ef15ea44be Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 31 May 2023 23:36:11 +0200 Subject: [PATCH 284/417] Update sbt-sonatype to 3.9.21 (#737) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index f79c91e8c..af8455607 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.20") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.21") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From dd6accbbf98708a557926223a7ed38e44856e345 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 31 May 2023 23:36:19 +0200 Subject: [PATCH 285/417] Update sbt to 1.8.3 (#735) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 6cd347fab..5041518d6 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.8.2 +sbt.version=1.8.3 From 24a89ca2d919707ed92ef8fcdc35facd912f3a80 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 31 May 2023 23:36:27 +0200 Subject: [PATCH 286/417] Update sbt-dynver to 5.0.1 (#733) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index af8455607..2e2e48063 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -6,6 +6,6 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0") -addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") +addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") scalacOptions ++= Seq("-deprecation", "-feature") From 2ffd012ed28e78d394d38896bee73171f7ed9505 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 31 May 2023 23:36:37 +0200 Subject: [PATCH 287/417] Update airframe-json, airspec to 23.5.6 (#736) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 7df0944be..19c1a11f3 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.5.2" +val AIRFRAME_VERSION = "23.5.6" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From a40cfd11279f4d466ba6500e6c72e83a7a9ecd86 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 3 Jun 2023 00:18:49 +0200 Subject: [PATCH 288/417] Update sbt to 1.9.0 (#738) * Update sbt to 1.9.0 * Run CI on sbt upgrade --------- Co-authored-by: Taro L. Saito --- .github/workflows/CI.yml | 2 ++ project/build.properties | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d53a68bfc..3c8d09e6e 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -7,6 +7,7 @@ on: - '**.java' - '**.sbt' - '.github/workflows/**.yml' + - 'project/build.properties' push: branches: - master @@ -17,6 +18,7 @@ on: - '**.java' - '**.sbt' - '.github/workflows/**.yml' + - 'project/build.properties' workflow_dispatch: jobs: diff --git a/project/build.properties b/project/build.properties index 5041518d6..018929602 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.8.3 +sbt.version=1.9.0 From caba23895f08df87afe6f63f4d9d0909a516e3b0 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 28 Jun 2023 00:14:38 +0200 Subject: [PATCH 289/417] Update airframe-json, airspec to 23.5.7 (#739) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 19c1a11f3..d5260290a 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.5.6" +val AIRFRAME_VERSION = "23.5.7" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From b2181d8eba51f6534adb91d73cef8fdc8a16e97d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 28 Jun 2023 00:14:47 +0200 Subject: [PATCH 290/417] Update scala-collection-compat to 2.11.0 (#740) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index d5260290a..73d64eda3 100644 --- a/build.sbt +++ b/build.sbt @@ -92,7 +92,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.10.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.11.0" % "test" ) ) From 4b3895488c1263bf91489748bdceac0069bca85e Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 28 Jun 2023 00:18:37 +0200 Subject: [PATCH 291/417] Update jackson-databind to 2.15.2 (#734) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 73d64eda3..ca8f9cf65 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.14.3", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.15.2", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 95863661a5d48052a9c8ffbeae70dcd286c09941 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Mon, 10 Jul 2023 22:24:59 +0900 Subject: [PATCH 292/417] Add `MessagePackMapper#handleBigDecimalAsString` (#745) --- msgpack-jackson/README.md | 32 +++++++++----- .../jackson/dataformat/MessagePackMapper.java | 9 ++++ .../dataformat/MessagePackMapperTest.java | 44 +++++++++++++++++++ 3 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index 7e8597815..e91c6f8b0 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -61,7 +61,13 @@ Only thing you need to do is to instantiate `MessagePackFactory` and pass it to Or more easily: ```java -ObjectMapper objectMapper = new MessagePackMapper(); + ObjectMapper objectMapper = new MessagePackMapper(); +``` + +We strongly recommend to call `MessagePackMapper#handleBigDecimalAsString()` if you serialize and/or deserialize BigDecimal values. See [Serialize and deserialize BigDecimal as str type internally in MessagePack format](#serialize-and-deserialize-bigdecimal-as-str-type-internally-in-messagepack-format) for details. + +```java + ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString(); ``` ### Serialization/Deserialization of List @@ -226,26 +232,33 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial ### Serialize and deserialize BigDecimal as str type internally in MessagePack format -`jackson-dataformat-msgpack` represents BigDecimal values as float type in MessagePack format by default. When you want to handle BigDeciaml values as str type with arbitrary precision in MessagePack format, you can use `com.fasterxml.jackson.databind.cfg.MutableConfigOverride#setFormat` like this: +`jackson-dataformat-msgpack` represents BigDecimal values as float type in MessagePack format by default for backward compatibility. But the default behavior could fail when handling too large value for `double` type. So we strongly recommend to call `MessagePackMapper#handleBigDecimalAsString()` to internally handle BigDecimal values as String. ```java - ObjectMapper mapper = new ObjectMapper(new MessagePackFactory()); - mapper.configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); + ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString(); Pojo obj = new Pojo(); + // This value is too large to be serialized as double obj.value = new BigDecimal("1234567890.98765432100"); - byte[] converted = mapper.writeValueAsBytes(obj); + byte[] converted = objectMapper.writeValueAsBytes(obj); + + System.out.println(objectMapper.readValue(converted, Pojo.class)); // => Pojo{value=1234567890.98765432100} +``` +`MessagePackMapper#handleBigDecimalAsString()` is equivalent to the following configuration. - System.out.println(mapper.readValue(converted, Pojo.class)); // => Pojo{value=1234567890.98765432100} +```java + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); ``` + ### Serialize and deserialize Instant instances as MessagePack extension type `timestamp` extension type is defined in MessagePack as type:-1. Registering `TimestampExtensionModule.INSTANCE` module enables automatic serialization and deserialization of java.time.Instant to/from the MessagePack extension type. ```java - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()) + ObjectMapper objectMapper = new MessagePackMapper() .registerModule(TimestampExtensionModule.INSTANCE); Pojo pojo = new Pojo(); // The type of `timestamp` variable is Instant @@ -287,8 +300,8 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial return "Java"; } return "Not Java"; - } - ); + }); + ObjectMapper objectMapper = new ObjectMapper( new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers)); @@ -476,4 +489,3 @@ There are a few options to fix this issue, but they introduce performance degred ObjectMapper objectMapper = new ObjectMapper( new MessagePackFactory().setReuseResourceInGenerator(false)); ``` - diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java index 3c3d228b0..52af03728 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java @@ -15,9 +15,12 @@ // package org.msgpack.jackson.dataformat; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.cfg.MapperBuilder; +import java.math.BigDecimal; + public class MessagePackMapper extends ObjectMapper { private static final long serialVersionUID = 3L; @@ -40,6 +43,12 @@ public MessagePackMapper(MessagePackFactory f) super(f); } + public MessagePackMapper handleBigDecimalAsString() + { + configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); + return this; + } + public static Builder builder() { return new Builder(new MessagePackMapper()); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java new file mode 100644 index 000000000..6dfd41cf2 --- /dev/null +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java @@ -0,0 +1,44 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.jackson.dataformat; + +import org.junit.Test; + +import java.io.IOException; +import java.math.BigDecimal; + +import static org.junit.Assert.assertEquals; + +public class MessagePackMapperTest +{ + static class Pojo + { + public BigDecimal value; + } + + @Test + public void handleBigDecimalAsString() throws IOException + { + MessagePackMapper mapper = new MessagePackMapper().handleBigDecimalAsString(); + Pojo obj = new Pojo(); + obj.value = new BigDecimal("1234567890.98765432100"); + + byte[] converted = mapper.writeValueAsBytes(obj); + + Pojo deserialized = mapper.readValue(converted, Pojo.class); + assertEquals(obj.value, deserialized.value); + } +} From 60f5aa62ea3e22b1c7964b0221c26e601d956537 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 10 Jul 2023 19:01:01 +0200 Subject: [PATCH 293/417] Update sbt to 1.9.1 (#741) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 018929602..ffd11bcc2 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.0 +sbt.version=1.9.1 From 629c6f4b5e00a9ebc13fc87160361154211b6ed4 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 12 Jul 2023 16:58:15 +0200 Subject: [PATCH 294/417] Update sbt to 1.9.2 (#746) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index ffd11bcc2..7a2f2cd1b 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.1 +sbt.version=1.9.2 From 596b6faea3053c77099b2c02470f8d73ca8cb0c1 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 12 Jul 2023 16:58:24 +0200 Subject: [PATCH 295/417] Update airframe-json, airspec to 23.7.1 (#744) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ca8f9cf65..c3b3e1ce2 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.5.7" +val AIRFRAME_VERSION = "23.7.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From b3f5e806581ee7208e54cb8db328fe066ebdd927 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 17 Jul 2023 19:14:57 +0200 Subject: [PATCH 296/417] Update airframe-json, airspec to 23.7.2 (#748) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c3b3e1ce2..58aee8571 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.7.1" +val AIRFRAME_VERSION = "23.7.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 2465fd311a6905be459975664e5ca123d921d089 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 25 Jul 2023 00:17:58 +0200 Subject: [PATCH 297/417] Update sbt to 1.9.3 (#750) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 7a2f2cd1b..91550e820 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.2 +sbt.version=1.9.3 From 3085cc16dabbd13bedcb7d8820af255b606c1470 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 31 Jul 2023 10:08:18 -0700 Subject: [PATCH 298/417] core (fix): Fix MessageUnpacker.unpackValue to check the custom stringSizeLimit (#753) * core (fix): Fix MessageUnpacker.unpackValue to check the custom stringSizeLimit * Cover unpackVariable(var) --- .../org/msgpack/core/MessageUnpacker.java | 6 +++ .../org/msgpack/core/StringLimitTest.scala | 37 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 msgpack-core/src/test/scala/org/msgpack/core/StringLimitTest.scala diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index ff638b744..8da8d7947 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -624,6 +624,9 @@ public ImmutableValue unpackValue() return ValueFactory.newFloat(unpackDouble()); case STRING: { int length = unpackRawStringHeader(); + if (length > stringSizeLimit) { + throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, length), length); + } return ValueFactory.newString(readPayload(length), true); } case BINARY: { @@ -689,6 +692,9 @@ public Variable unpackValue(Variable var) return var; case STRING: { int length = unpackRawStringHeader(); + if (length > stringSizeLimit) { + throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, length), length); + } var.setStringValue(readPayload(length)); return var; } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/StringLimitTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/StringLimitTest.scala new file mode 100644 index 000000000..96319a7f2 --- /dev/null +++ b/msgpack-core/src/test/scala/org/msgpack/core/StringLimitTest.scala @@ -0,0 +1,37 @@ +package org.msgpack.core + +import org.msgpack.core.MessagePack.UnpackerConfig +import org.msgpack.value.Variable +import wvlet.airspec.AirSpec + +class StringLimitTest extends AirSpec { + + test("throws an exception when the string size exceeds a limit") { + val customLimit = 100 + val packer = MessagePack.newDefaultBufferPacker() + packer.packString("a" * (customLimit + 1)) + val msgpack = packer.toByteArray + + test("unpackString") { + val unpacker = new UnpackerConfig().withStringSizeLimit(customLimit).newUnpacker(msgpack) + intercept[MessageSizeException] { + unpacker.unpackString() + } + } + + test("unpackValue") { + val unpacker = new UnpackerConfig().withStringSizeLimit(customLimit).newUnpacker(msgpack) + intercept[MessageSizeException] { + unpacker.unpackValue() + } + } + + test("unpackValue(var)") { + val unpacker = new UnpackerConfig().withStringSizeLimit(customLimit).newUnpacker(msgpack) + intercept[MessageSizeException] { + val v = new Variable() + unpacker.unpackValue(v) + } + } + } +} From eaab10600a5e5e2a7e8d26e1a4eee02703c6506e Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 2 Aug 2023 19:43:02 +0200 Subject: [PATCH 299/417] Update airframe-json, airspec to 23.7.4 (#752) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 58aee8571..ba7275732 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.7.2" +val AIRFRAME_VERSION = "23.7.4" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From cdfe139e2b0c81c22fe7cb95562480afbb52b708 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 7 Aug 2023 08:01:27 +0200 Subject: [PATCH 300/417] Update airframe-json, airspec to 23.8.0 (#754) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ba7275732..faa64554f 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.7.4" +val AIRFRAME_VERSION = "23.8.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 1e0eaff64319c74c6c0eb814eab93456bd695e16 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sun, 6 Aug 2023 23:18:01 -0700 Subject: [PATCH 301/417] Switch the default branch from develop to main (#755) * Switch the default branch from develop to main * Revert unnecessary changes --- .github/release-drafter.yml | 4 ++-- .github/workflows/CI.yml | 2 -- .github/workflows/release-drafter.yml | 3 +-- .github/workflows/snapshot.yml | 1 - 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 2e6420f9f..fb21a72b5 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -43,10 +43,10 @@ autolabeler: - '*.md' - label: 'feature' title: - - '/(support|add)/i' + - '/(feature|support)/i' - label: 'bug' title: - - '/fix/i' + - '/(fix|bug)/i' - label: 'internal' title: - '/internal/i' diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3c8d09e6e..743526545 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -10,8 +10,6 @@ on: - 'project/build.properties' push: branches: - - master - - develop - main paths: - '**.scala' diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 6a48ed0ae..3e173377e 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -3,7 +3,6 @@ name: Release Drafter on: push: branches: - - develop - main # pull_request event is required only for autolabeler pull_request: @@ -12,7 +11,7 @@ on: # pull_request_target event is required for autolabeler to support PRs from forks pull_request_target: types: [opened, reopened, synchronize] - + permissions: contents: read diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 1fde65f15..e244adfd8 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -3,7 +3,6 @@ name: Snapshot Release on: push: branches: - - develop - main paths: - '**.scala' From 8f7bc87461fe9653c141a6f2a44e973199d3b4e6 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 7 Aug 2023 20:25:30 +0200 Subject: [PATCH 302/417] Update airframe-json, airspec to 23.8.1 (#756) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index faa64554f..310ebe557 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.8.0" +val AIRFRAME_VERSION = "23.8.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 72eb1bcc4d1f9ee5ccadf3915b56b1e7de0c0849 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 12 Sep 2023 08:54:37 +0200 Subject: [PATCH 303/417] Update sbt to 1.9.4 (#759) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 91550e820..0425ccf89 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.3 +sbt.version=1.9.4 From 511c4d4b625acb044db17aa33c894ada5efdb9fa Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 12 Sep 2023 08:54:49 +0200 Subject: [PATCH 304/417] Update airframe-json, airspec to 23.8.6 (#760) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 310ebe557..8f83f27db 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.8.1" +val AIRFRAME_VERSION = "23.8.6" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From e6d016a63aa44428bd53dbaae7df6a791c575138 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 21 Sep 2023 01:00:13 +0200 Subject: [PATCH 305/417] Update sbt to 1.9.6 (#763) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 0425ccf89..07960c018 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.4 +sbt.version=1.9.6 From 6ea9d91eaa1249dd15ab827881a03b0bbbb34ec2 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 21 Sep 2023 01:00:24 +0200 Subject: [PATCH 306/417] Update airframe-json, airspec to 23.9.1 (#762) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 8f83f27db..32c971725 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.8.6" +val AIRFRAME_VERSION = "23.9.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From c79ef243674b4b7465dae4cb7519a80d81121d5d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 21 Sep 2023 01:00:32 +0200 Subject: [PATCH 307/417] Update sbt-scalafmt to 2.5.2 (#761) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 2e2e48063..dd508b3b0 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,7 +5,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") scalacOptions ++= Seq("-deprecation", "-feature") From c2c3a8f303eaf91572cee7592eb3d664e33f0cae Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 24 Sep 2023 09:36:13 +0900 Subject: [PATCH 308/417] Correct MessageUnpacker javadoc (#764) --- .../src/main/java/org/msgpack/core/MessageUnpacker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 8da8d7947..5a9a1a631 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -342,7 +342,7 @@ private static int utf8MultibyteCharacterSize(byte firstByte) } /** - * Returns true true if this unpacker has more elements. + * Returns true if this unpacker has more elements. * When this returns true, subsequent call to {@link #getNextFormat()} returns an * MessageFormat instance. If false, next {@link #getNextFormat()} call will throw an MessageInsufficientBufferException. * @@ -759,7 +759,7 @@ public void unpackNil() /** * Peeks a Nil byte and reads it if next byte is a nil value. * - * The difference from {@link unpackNil} is that unpackNil throws an exception if the next byte is not nil value + * The difference from {@link #unpackNil()} is that unpackNil throws an exception if the next byte is not nil value * while this tryUnpackNil method returns false without changing position. * * @return true if a nil value is read From ba1beabb4566a233e999d34b09c580feeab12a58 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 23 Sep 2023 20:53:46 -0700 Subject: [PATCH 309/417] feature: Support JDK21 (and drop JDK7 support) (#765) * feature: Support JDK21 * JDK21 doesn't support -source 1.7 option any more * Upgrade to Scala 2.13.12, which supports JDK21 * Use DirectByteBuffer(long, long) in JDK21 --- .github/workflows/CI.yml | 20 ++++++++- build.sbt | 8 ++-- .../core/buffer/DirectBufferAccess.java | 44 ++++++++++++------- 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 743526545..57cc4eec4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -27,6 +27,24 @@ jobs: - uses: actions/checkout@v2 - name: jcheckstyle run: ./sbt jcheckStyle + test_jdk21: + name: Test JDK21 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: '21' + - uses: actions/cache@v2 + with: + path: ~/.cache + key: ${{ runner.os }}-jdk21-${{ hashFiles('**/*.sbt') }} + restore-keys: ${{ runner.os }}-jdk21- + - name: Test + run: ./sbt test + - name: Universal Buffer Test + run: ./sbt test -J-Dmsgpack.universal-buffer=true test_jdk17: name: Test JDK17 runs-on: ubuntu-latest @@ -39,7 +57,7 @@ jobs: - uses: actions/cache@v2 with: path: ~/.cache - key: ${{ runner.os }}-jdk11-${{ hashFiles('**/*.sbt') }} + key: ${{ runner.os }}-jdk17-${{ hashFiles('**/*.sbt') }} restore-keys: ${{ runner.os }}-jdk17- - name: Test run: ./sbt test diff --git a/build.sbt b/build.sbt index 32c971725..3aa3c9c72 100644 --- a/build.sbt +++ b/build.sbt @@ -17,7 +17,7 @@ val buildSettings = Seq[Setting[_]]( organizationName := "MessagePack", organizationHomepage := Some(new URL("http://msgpack.org/")), description := "MessagePack for Java", - scalaVersion := "2.13.6", + scalaVersion := "2.13.12", Test / logBuffered := false, // msgpack-java should be a pure-java library, so remove Scala specific configurations autoScalaLibrary := false, @@ -26,11 +26,11 @@ val buildSettings = Seq[Setting[_]]( // JVM options for building scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-feature"), Test / javaOptions ++= Seq("-ea"), - javacOptions ++= Seq("-source", "1.7", "-target", "1.7"), + javacOptions ++= Seq("-source", "1.8", "-target", "1.8"), Compile / compile / javacOptions ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation"), // Use lenient validation mode when generating Javadoc (for Java8) doc / javacOptions := { - val opts = Seq("-source", "1.7") + val opts = Seq("-source", "1.8") if (scala.util.Properties.isJavaAtLeast("1.8")) { opts ++ Seq("-Xdoclint:none") } else { @@ -92,7 +92,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.11.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.11.0" % "test" ) ) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java index f54c50b9a..7b5ea461d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/DirectBufferAccess.java @@ -37,6 +37,7 @@ private DirectBufferAccess() enum DirectBufferConstructorType { + ARGS_LONG_LONG, ARGS_LONG_INT_REF, ARGS_LONG_INT, ARGS_INT_INT, @@ -64,28 +65,35 @@ enum DirectBufferConstructorType DirectBufferConstructorType constructorType = null; Method mbWrap = null; try { - // TODO We should use MethodHandle for Java7, which can avoid the cost of boxing with JIT optimization - directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, int.class, Object.class); - constructorType = DirectBufferConstructorType.ARGS_LONG_INT_REF; + // JDK21 DirectByteBuffer(long, long) + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, long.class); + constructorType = DirectBufferConstructorType.ARGS_LONG_LONG; } - catch (NoSuchMethodException e0) { + catch (NoSuchMethodException e00) { try { - // https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/nio/DirectByteBuffer.java - // DirectByteBuffer(long address, int capacity) - directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, int.class); - constructorType = DirectBufferConstructorType.ARGS_LONG_INT; + // TODO We should use MethodHandle for Java7, which can avoid the cost of boxing with JIT optimization + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, int.class, Object.class); + constructorType = DirectBufferConstructorType.ARGS_LONG_INT_REF; } - catch (NoSuchMethodException e1) { + catch (NoSuchMethodException e0) { try { - directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(int.class, int.class); - constructorType = DirectBufferConstructorType.ARGS_INT_INT; + // https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/nio/DirectByteBuffer.java + // DirectByteBuffer(long address, int capacity) + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(long.class, int.class); + constructorType = DirectBufferConstructorType.ARGS_LONG_INT; } - catch (NoSuchMethodException e2) { - Class aClass = Class.forName("java.nio.MemoryBlock"); - mbWrap = aClass.getDeclaredMethod("wrapFromJni", int.class, long.class); - mbWrap.setAccessible(true); - directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(aClass, int.class, int.class); - constructorType = DirectBufferConstructorType.ARGS_MB_INT_INT; + catch (NoSuchMethodException e1) { + try { + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(int.class, int.class); + constructorType = DirectBufferConstructorType.ARGS_INT_INT; + } + catch (NoSuchMethodException e2) { + Class aClass = Class.forName("java.nio.MemoryBlock"); + mbWrap = aClass.getDeclaredMethod("wrapFromJni", int.class, long.class); + mbWrap.setAccessible(true); + directByteBufferConstructor = directByteBufferClass.getDeclaredConstructor(aClass, int.class, int.class); + constructorType = DirectBufferConstructorType.ARGS_MB_INT_INT; + } } } } @@ -281,6 +289,8 @@ static ByteBuffer newByteBuffer(long address, int index, int length, ByteBuffer } try { switch (directBufferConstructorType) { + case ARGS_LONG_LONG: + return (ByteBuffer) byteBufferConstructor.newInstance(address + index, (long) length); case ARGS_LONG_INT_REF: return (ByteBuffer) byteBufferConstructor.newInstance(address + index, length, reference); case ARGS_LONG_INT: From 3929eb362df2b55e70bd23548bfaa34f2774d18b Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 23 Sep 2023 20:54:10 -0700 Subject: [PATCH 310/417] internal: Automatically generate release notes (#766) --- .github/release.yml | 31 +++++++++++++++++++++++++++ .github/workflows/release-drafter.yml | 6 +----- .github/workflows/release-note.yml | 18 ++++++++++++++++ README.md | 4 ++-- 4 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 .github/release.yml create mode 100644 .github/workflows/release-note.yml diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000..973c3db68 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,31 @@ +changelog: + categories: + - title: '🔥 Breaking Changes' + labels: + - 'breaking' + - title: '👋 Deprecated' + labels: + - 'deprecation' + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'bug' + - title: '🔗 Dependency Updates' + labels: + - 'library-update' + - 'dependencies' + - title: '🛠 Internal Updates' + labels: + - 'internal' + - 'kaizen' + - 'test-library-update' + - 'sbt-plugin-update' + - title: '📚 Docs' + labels: + - 'doc' + - title: Other Changes + labels: + - "*" diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 3e173377e..42d3901da 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -1,9 +1,6 @@ name: Release Drafter on: - push: - branches: - - main # pull_request event is required only for autolabeler pull_request: # Only following types are handled by the action, but one can default to all as well @@ -18,8 +15,7 @@ permissions: jobs: update_release_draft: permissions: - # write permission is required to create a github release - contents: write + contents: read # write permission is required for autolabeler # otherwise, read permission is required at least pull-requests: write diff --git a/.github/workflows/release-note.yml b/.github/workflows/release-note.yml new file mode 100644 index 000000000..ac290e4c6 --- /dev/null +++ b/.github/workflows/release-note.yml @@ -0,0 +1,18 @@ +name: Release Note + +on: + push: + tags: + - v* + workflow_dispatch: + +jobs: + release: + name: Create a new release note + runs-on: ubuntu-latest + steps: + - name: Create a release note + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "$GITHUB_REF_NAME" --repo="$GITHUB_REPOSITORY" --generate-notes diff --git a/README.md b/README.md index 8cad43c6f..34a3f277a 100644 --- a/README.md +++ b/README.md @@ -96,14 +96,14 @@ Here is a list of sbt commands for daily development: ### Publish to Sonatype (Maven Central) -To publish a new version, you only need to add a new git tag and push it to GitHub. GitHub Action will deploy a new release version to Maven Central (Sonatype). +To publish a new version, add a new git tag and push it to GitHub. GitHub Action will deploy a new release version to Maven Central (Sonatype). ```scala $ git tag v0.x.y $ git push origin v0.x.y ``` -A draft of the next release note will be updated automatically at the [GitHub Releases](https://github.com/msgpack/msgpack-java/releases) page. For each PR merged, [release-drafter](https://github.com/release-drafter/release-drafter) will modify the release note draft. When you create a new release tag, edit and publish the draft of the release note. If necessary, adjust the version number and target tag. +A new release note will be generated automatically at the [GitHub Releases](https://github.com/msgpack/msgpack-java/releases) page. #### Publishing to Sonatype from Local Machine From ce4410df705018b7e2e1e2667b4e71906c0b727b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 25 Sep 2023 18:23:41 +0200 Subject: [PATCH 311/417] Update airframe-json, airspec to 23.9.2 (#767) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3aa3c9c72..071467547 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.9.1" +val AIRFRAME_VERSION = "23.9.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 8d514ba31f050d4a1a11d4b6df9f303833c864d5 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 1 Oct 2023 10:45:56 +0900 Subject: [PATCH 312/417] Add MessagePackMapper#handleBigIntegerAndBigDecimalAsString (#768) * Add MessagePackMapper#handleBigIntegerAndBigDecimalAsString * Rename unit test method names --- msgpack-jackson/README.md | 11 +-- .../jackson/dataformat/MessagePackMapper.java | 12 +++ .../dataformat/MessagePackMapperTest.java | 81 +++++++++++++++++-- 3 files changed, 92 insertions(+), 12 deletions(-) diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index e91c6f8b0..0156453ea 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -64,10 +64,10 @@ Or more easily: ObjectMapper objectMapper = new MessagePackMapper(); ``` -We strongly recommend to call `MessagePackMapper#handleBigDecimalAsString()` if you serialize and/or deserialize BigDecimal values. See [Serialize and deserialize BigDecimal as str type internally in MessagePack format](#serialize-and-deserialize-bigdecimal-as-str-type-internally-in-messagepack-format) for details. +We strongly recommend to call `MessagePackMapper#handleBigIntegerAndBigDecimalAsString()` if you serialize and/or deserialize BigInteger/BigDecimal values. See [Serialize and deserialize BigDecimal as str type internally in MessagePack format](#serialize-and-deserialize-bigdecimal-as-str-type-internally-in-messagepack-format) for details. ```java - ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString(); + ObjectMapper objectMapper = new MessagePackMapper().handleBigIntegerAndBigDecimalAsString(); ``` ### Serialization/Deserialization of List @@ -232,10 +232,10 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial ### Serialize and deserialize BigDecimal as str type internally in MessagePack format -`jackson-dataformat-msgpack` represents BigDecimal values as float type in MessagePack format by default for backward compatibility. But the default behavior could fail when handling too large value for `double` type. So we strongly recommend to call `MessagePackMapper#handleBigDecimalAsString()` to internally handle BigDecimal values as String. +`jackson-dataformat-msgpack` represents BigDecimal values as float type in MessagePack format by default for backward compatibility. But the default behavior could fail when handling too large value for `double` type. So we strongly recommend to call `MessagePackMapper#handleBigIntegerAndBigDecimalAsString()` to internally handle BigDecimal values as String. ```java - ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString(); + ObjectMapper objectMapper = new MessagePackMapper().handleBigIntegerAndBigDecimalAsString(); Pojo obj = new Pojo(); // This value is too large to be serialized as double @@ -245,10 +245,11 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial System.out.println(objectMapper.readValue(converted, Pojo.class)); // => Pojo{value=1234567890.98765432100} ``` -`MessagePackMapper#handleBigDecimalAsString()` is equivalent to the following configuration. +`MessagePackMapper#handleBigIntegerAndDecimalAsString()` is equivalent to the following configuration. ```java ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.configOverride(BigInteger.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); objectMapper.configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); ``` diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java index 52af03728..144c8d1a5 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.cfg.MapperBuilder; import java.math.BigDecimal; +import java.math.BigInteger; public class MessagePackMapper extends ObjectMapper { @@ -43,12 +44,23 @@ public MessagePackMapper(MessagePackFactory f) super(f); } + public MessagePackMapper handleBigIntegerAsString() + { + configOverride(BigInteger.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); + return this; + } + public MessagePackMapper handleBigDecimalAsString() { configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); return this; } + public MessagePackMapper handleBigIntegerAndBigDecimalAsString() + { + return handleBigIntegerAsString().handleBigDecimalAsString(); + } + public static Builder builder() { return new Builder(new MessagePackMapper()); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java index 6dfd41cf2..68721fce8 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java @@ -15,30 +15,97 @@ // package org.msgpack.jackson.dataformat; +import com.fasterxml.jackson.core.JsonProcessingException; import org.junit.Test; import java.io.IOException; import java.math.BigDecimal; +import java.math.BigInteger; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; public class MessagePackMapperTest { - static class Pojo + static class PojoWithBigInteger + { + public BigInteger value; + } + + static class PojoWithBigDecimal { public BigDecimal value; } - @Test - public void handleBigDecimalAsString() throws IOException + private void shouldFailToHandleBigInteger(MessagePackMapper messagePackMapper) throws JsonProcessingException + { + PojoWithBigInteger obj = new PojoWithBigInteger(); + obj.value = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(10)); + + try { + messagePackMapper.writeValueAsBytes(obj); + fail(); + } + catch (IllegalArgumentException e) { + // Expected + } + } + + private void shouldSuccessToHandleBigInteger(MessagePackMapper messagePackMapper) throws IOException { - MessagePackMapper mapper = new MessagePackMapper().handleBigDecimalAsString(); - Pojo obj = new Pojo(); + PojoWithBigInteger obj = new PojoWithBigInteger(); + obj.value = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(10)); + + byte[] converted = messagePackMapper.writeValueAsBytes(obj); + + PojoWithBigInteger deserialized = messagePackMapper.readValue(converted, PojoWithBigInteger.class); + assertEquals(obj.value, deserialized.value); + } + + private void shouldFailToHandleBigDecimal(MessagePackMapper messagePackMapper) throws JsonProcessingException + { + PojoWithBigDecimal obj = new PojoWithBigDecimal(); obj.value = new BigDecimal("1234567890.98765432100"); - byte[] converted = mapper.writeValueAsBytes(obj); + try { + messagePackMapper.writeValueAsBytes(obj); + fail(); + } + catch (IllegalArgumentException e) { + // Expected + } + } - Pojo deserialized = mapper.readValue(converted, Pojo.class); + private void shouldSuccessToHandleBigDecimal(MessagePackMapper messagePackMapper) throws IOException + { + PojoWithBigDecimal obj = new PojoWithBigDecimal(); + obj.value = new BigDecimal("1234567890.98765432100"); + + byte[] converted = messagePackMapper.writeValueAsBytes(obj); + + PojoWithBigDecimal deserialized = messagePackMapper.readValue(converted, PojoWithBigDecimal.class); assertEquals(obj.value, deserialized.value); } + + @Test + public void handleBigIntegerAsString() throws IOException + { + shouldFailToHandleBigInteger(new MessagePackMapper()); + shouldSuccessToHandleBigInteger(new MessagePackMapper().handleBigIntegerAsString()); + } + + @Test + public void handleBigDecimalAsString() throws IOException + { + shouldFailToHandleBigDecimal(new MessagePackMapper()); + shouldSuccessToHandleBigDecimal(new MessagePackMapper().handleBigDecimalAsString()); + } + + @Test + public void handleBigIntegerAndBigDecimalAsString() throws IOException + { + MessagePackMapper messagePackMapper = new MessagePackMapper().handleBigIntegerAndBigDecimalAsString(); + shouldSuccessToHandleBigInteger(messagePackMapper); + shouldSuccessToHandleBigDecimal(messagePackMapper); + } } From f9ca6d45fa75b916e450925faeb78341d0a4c6c1 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 4 Oct 2023 01:34:37 +0200 Subject: [PATCH 313/417] Update airframe-json, airspec to 23.9.3 (#769) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 071467547..29b1b6fe8 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.9.2" +val AIRFRAME_VERSION = "23.9.3" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From bb16a9287f22474ada0d1f468c34a332908a2571 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:01:59 +0200 Subject: [PATCH 314/417] Update airframe-json, airspec to 23.10.0 (#772) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 29b1b6fe8..939ba2a38 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.9.3" +val AIRFRAME_VERSION = "23.10.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 89391fcbd0a9a3d7fd5d7bc6c93880260a02c4fc Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Fri, 20 Oct 2023 04:02:22 +0900 Subject: [PATCH 315/417] use `setup-java` instead of deprecated `olafurpg/setup-scala` (#770) use setup-java instead of deprecated olafurpg/setup-scala --- .github/workflows/release.yml | 5 +++-- .github/workflows/snapshot.yml | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d105d9d1b..1f04d480d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,10 +17,11 @@ jobs: # Fetch all tags so that sbt-dynver can find the previous release version - run: git fetch --tags -f # Install OpenJDK 8 - - uses: olafurpg/setup-scala@v10 + - uses: actions/setup-java@v3 with: # We need to use JDK8 for Android compatibility https://github.com/msgpack/msgpack-java/issues/516 - java-version: adopt@1.8 + java-version: 8 + distribution: adopt - name: Setup GPG env: PGP_SECRET: ${{ secrets.PGP_SECRET }} diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index e244adfd8..779f3878a 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -21,9 +21,10 @@ jobs: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version - run: git fetch --tags - - uses: olafurpg/setup-scala@v10 + - uses: actions/setup-java@v3 with: - java-version: adopt@1.11 + java-version: 11 + distribution: adopt - name: Publish snapshots env: SONATYPE_USERNAME: '${{ secrets.SONATYPE_USER }}' From 8b1cbfb3676f55198a2aa7ccd1458828cbc8ae2c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:02:49 +0200 Subject: [PATCH 316/417] Update sbt-osgi to 0.9.7 (#773) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index dd508b3b0..e0d542720 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.7") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") From f3ecdb0582a8782432c28f0f6a9d6cf52000439d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:03:00 +0200 Subject: [PATCH 317/417] Update jackson-databind to 2.15.3 (#771) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 939ba2a38..cd65409f6 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.15.2", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.15.3", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 85ffcca77adfcb90250f8a5b46dc4a0e1671e711 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 24 Oct 2023 06:03:09 +0200 Subject: [PATCH 318/417] Update sbt-osgi to 0.9.8 (#774) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index e0d542720..326aaa787 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.7") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.8") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") From 25be735d83bb2855cdc4537860c476dec9ead851 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 27 Oct 2023 00:21:22 +0200 Subject: [PATCH 319/417] Update sbt to 1.9.7 (#775) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 07960c018..d92825599 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.6 +sbt.version=1.9.7 From d9ed10348a388c0b8e86f65536c9334c989a2e0f Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Sat, 28 Oct 2023 05:45:33 +0900 Subject: [PATCH 320/417] (internal): Add `dependabot.yml` for GitHub Actions update (#776) add dependabot.yml --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..5ace4600a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" From b35e7ee6eb56f18dcb8f9a50f473b3d808af47de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Oct 2023 15:01:52 -0700 Subject: [PATCH 321/417] Bump actions/checkout from 2 to 4 (#777) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 10 +++++----- .github/workflows/release.yml | 2 +- .github/workflows/snapshot.yml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 57cc4eec4..44e8ff079 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -24,14 +24,14 @@ jobs: name: Code Format runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: jcheckstyle run: ./sbt jcheckStyle test_jdk21: name: Test JDK21 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: 'zulu' @@ -49,7 +49,7 @@ jobs: name: Test JDK17 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: 'zulu' @@ -67,7 +67,7 @@ jobs: name: Test JDK11 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: 'zulu' @@ -85,7 +85,7 @@ jobs: name: Test JDK8 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: 'zulu' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1f04d480d..0060b06f2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: name: Release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 779f3878a..e24088f78 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -16,7 +16,7 @@ jobs: name: Publish snapshots runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version From 7826391dfdbfd18fdaa523c933e43a7c44f3716a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Oct 2023 15:02:04 -0700 Subject: [PATCH 322/417] Bump actions/cache from 2 to 3 (#778) Bumps [actions/cache](https://github.com/actions/cache) from 2 to 3. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 44e8ff079..6a18e4868 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -36,7 +36,7 @@ jobs: with: distribution: 'zulu' java-version: '21' - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ~/.cache key: ${{ runner.os }}-jdk21-${{ hashFiles('**/*.sbt') }} @@ -54,7 +54,7 @@ jobs: with: distribution: 'zulu' java-version: '17' - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ~/.cache key: ${{ runner.os }}-jdk17-${{ hashFiles('**/*.sbt') }} @@ -72,7 +72,7 @@ jobs: with: distribution: 'zulu' java-version: '11' - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ~/.cache key: ${{ runner.os }}-jdk11-${{ hashFiles('**/*.sbt') }} @@ -90,7 +90,7 @@ jobs: with: distribution: 'zulu' java-version: '8' - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ~/.cache key: ${{ runner.os }}-jdk8-${{ hashFiles('**/*.sbt') }} From 6c8d683c9203e58f118a4a04eb954f58921d27f6 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 16 Nov 2023 06:09:11 +0100 Subject: [PATCH 323/417] Update airframe-json, airspec to 23.11.3 (#781) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index cd65409f6..dc5a2c23e 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.10.0" +val AIRFRAME_VERSION = "23.11.3" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 8d6ab473a1db518d458d8f6e653db06ee0d4f886 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 16 Nov 2023 06:09:24 +0100 Subject: [PATCH 324/417] Update sbt-osgi to 0.9.9 (#779) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 326aaa787..9ab759bd9 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.8") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.9") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") From 87cac7173f3ef410b14362a6bf3a43a3ac3cdece Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 18 Nov 2023 23:38:57 +0100 Subject: [PATCH 325/417] Update sbt-sonatype to 3.10.0 (#783) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 9ab759bd9..ba0a0c263 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.21") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From 938a43755643e1c6159aac1b9523c7e00fa70250 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 15:19:46 -0800 Subject: [PATCH 326/417] Bump actions/setup-java from 3 to 4 (#784) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 8 ++++---- .github/workflows/release.yml | 2 +- .github/workflows/snapshot.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6a18e4868..7732559af 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: '21' @@ -50,7 +50,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: '17' @@ -68,7 +68,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: '11' @@ -86,7 +86,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: '8' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0060b06f2..b214d8ecd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: # Fetch all tags so that sbt-dynver can find the previous release version - run: git fetch --tags -f # Install OpenJDK 8 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: # We need to use JDK8 for Android compatibility https://github.com/msgpack/msgpack-java/issues/516 java-version: 8 diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index e24088f78..cbce4c148 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -21,7 +21,7 @@ jobs: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version - run: git fetch --tags - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: java-version: 11 distribution: adopt From 41168e92efa8623e3e7e518bb72d4ae8978f9a27 Mon Sep 17 00:00:00 2001 From: Fang Zheng Date: Tue, 9 Jan 2024 15:22:34 -0800 Subject: [PATCH 327/417] Fix fixint test in MessagePackTest. (#785) --- .../src/test/scala/org/msgpack/core/MessagePackTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 4f6949bd3..c2993f96a 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -78,7 +78,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { test("detect fixint values") { - for (i <- 0 until 0x79) { + for (i <- 0 until 0x7f) { Code.isPosFixInt(i.toByte) shouldBe true } From cc2ce77c70df9210c41269deaf43f041768e0541 Mon Sep 17 00:00:00 2001 From: Fang Zheng Date: Tue, 9 Jan 2024 15:24:29 -0800 Subject: [PATCH 328/417] internal: Remove dead code in MessagePacker. (#787) --- .../src/main/java/org/msgpack/core/MessagePacker.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 4cf789d9f..72c26ecac 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -774,10 +774,6 @@ else if (s.length() < (1 << 16)) { position += written; } else { - if (written >= (1L << 32)) { // this check does nothing because (1L << 32) is larger than Integer.MAX_VALUE - // this must not happen because s.length() is less than 2^16 and (2^16) * UTF_8_MAX_CHAR_SIZE is less than 2^32 - throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); - } // move 2 bytes backward to expand 3-byte header region to 5 bytes buffer.putMessageBuffer(position + 5, buffer, position + 3, written); // write 3-byte header header From 532199e454ec912082cecb08d3cf08cf0a277d74 Mon Sep 17 00:00:00 2001 From: Fang Zheng Date: Tue, 9 Jan 2024 15:35:11 -0800 Subject: [PATCH 329/417] Fix bug in ImmutableTimestampValueImpl. (#786) * Fix bug in ImmutableTimestampValueImpl. * Fix code style --------- Co-authored-by: Taro L. Saito --- .../org/msgpack/value/impl/ImmutableTimestampValueImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java index 227c85d0b..1891d9a7f 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java +++ b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java @@ -93,7 +93,7 @@ public byte[] getData() long sec = getEpochSecond(); int nsec = getNano(); if (sec >>> 34 == 0) { - long data64 = (nsec << 34) | sec; + long data64 = ((long) nsec << 34) | sec; if ((data64 & 0xffffffff00000000L) == 0L) { bytes = new byte[4]; MessageBuffer.wrap(bytes).putInt(0, (int) sec); From 69354a047e789c9bf5f24dcb4ace4875d0569e9b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 13 Jan 2024 01:34:40 +0100 Subject: [PATCH 330/417] Update sbt to 1.9.8 (#790) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index d92825599..e5ca1ff51 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.7 +sbt.version=1.9.8 From dc7d6031aaa603db3f622c54da7a8feb6fb256c2 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 13 Jan 2024 01:34:49 +0100 Subject: [PATCH 331/417] Update sbt-osgi to 0.9.10 (#789) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index ba0a0c263..7f5180882 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.9") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.10") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") From cedc35ceaef2ae0ea67a9a9df3747c4d18d70a3e Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 13 Jan 2024 01:34:57 +0100 Subject: [PATCH 332/417] Update airframe-json, airspec to 23.12.1 (#791) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index dc5a2c23e..77dd06dd2 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.11.3" +val AIRFRAME_VERSION = "23.12.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From a1a61f855b46e60e6fa3de7c6ffec7e7f03eb666 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sun, 14 Jan 2024 22:27:46 +0100 Subject: [PATCH 333/417] Update airframe-json, airspec to 24.1.0 (#792) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 77dd06dd2..9716d20c2 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.12.1" +val AIRFRAME_VERSION = "24.1.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 42daf717347d774b478a8ab0950c7f8a4c816534 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 18 Jan 2024 19:22:18 +0100 Subject: [PATCH 334/417] Update airframe-json, airspec to 24.1.1 (#793) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9716d20c2..4ad39cd84 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.1.0" +val AIRFRAME_VERSION = "24.1.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 4bdaf8e35f130e561ca964b578bbe696c4d1dd9f Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 18 Jan 2024 19:23:33 +0100 Subject: [PATCH 335/417] Update jackson-databind to 2.16.1 (#788) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4ad39cd84..3bfc9133f 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.15.3", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.16.1", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 480fd736bac5b02657c566af2d32a0674c64d370 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 21 Jan 2024 14:49:03 +0900 Subject: [PATCH 336/417] Fix ClassCastException when array values is set as List (#794) --- msgpack-core/src/main/java/org/msgpack/value/Variable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/value/Variable.java b/msgpack-core/src/main/java/org/msgpack/value/Variable.java index ae88170c7..85d2fb3b0 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/Variable.java +++ b/msgpack-core/src/main/java/org/msgpack/value/Variable.java @@ -817,7 +817,7 @@ public Variable setArrayValue(List v) { this.type = Type.LIST; this.accessor = arrayAccessor; - this.objectValue = v.toArray(); + this.objectValue = v.toArray(new Value[v.size()]); return this; } From a2ff390cea9f0e92dc0805ebeff05b9e70b264ba Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 24 Jan 2024 19:12:21 +0100 Subject: [PATCH 337/417] Update sbt-osgi to 0.9.11 (#796) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 7f5180882..33b8bfb57 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.10") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.11") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") From 964800ec3abc4f2f64b0598083cbf0ef51c0a3a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:12:30 -0800 Subject: [PATCH 338/417] Bump actions/cache from 3 to 4 (#795) Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7732559af..7ff24e9b5 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -36,7 +36,7 @@ jobs: with: distribution: 'zulu' java-version: '21' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache key: ${{ runner.os }}-jdk21-${{ hashFiles('**/*.sbt') }} @@ -54,7 +54,7 @@ jobs: with: distribution: 'zulu' java-version: '17' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache key: ${{ runner.os }}-jdk17-${{ hashFiles('**/*.sbt') }} @@ -72,7 +72,7 @@ jobs: with: distribution: 'zulu' java-version: '11' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache key: ${{ runner.os }}-jdk11-${{ hashFiles('**/*.sbt') }} @@ -90,7 +90,7 @@ jobs: with: distribution: 'zulu' java-version: '8' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache key: ${{ runner.os }}-jdk8-${{ hashFiles('**/*.sbt') }} From a1796398f331a8f94316a3ab9e52e0869d3ddb62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 16:34:11 -0800 Subject: [PATCH 339/417] Bump release-drafter/release-drafter from 5 to 6 (#798) Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5 to 6. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/v5...v6) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 42d3901da..f77373a9b 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -22,6 +22,6 @@ jobs: runs-on: ubuntu-latest steps: # Drafts your next Release notes as Pull Requests are merged into "master" - - uses: release-drafter/release-drafter@v5 + - uses: release-drafter/release-drafter@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From fd386138fec6f2a469516dcb2b113dc66e6247e8 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 6 Feb 2024 01:34:21 +0100 Subject: [PATCH 340/417] Update sbt-osgi to 0.10.0 (#797) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 33b8bfb57..aa41287b9 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.11") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") From 750a07c73329f9ab1e1b6d55c6b199093df9be0b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:21:12 +0100 Subject: [PATCH 341/417] Update airframe-json, airspec to 24.1.2 (#801) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3bfc9133f..e4bf7dadc 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.1.1" +val AIRFRAME_VERSION = "24.1.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From b917abce56c83beca17a28e6a9f005206b4a9a48 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 6 Mar 2024 06:11:47 +0100 Subject: [PATCH 342/417] Update sbt to 1.9.9 (#803) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e5ca1ff51..b089b60c7 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.8 +sbt.version=1.9.9 From 55d774a0976ce7bad569deabdb88c62b336880fb Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 6 Mar 2024 06:12:06 +0100 Subject: [PATCH 343/417] Update airframe-json, airspec to 24.3.0 (#807) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index e4bf7dadc..69cac77a8 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.1.2" +val AIRFRAME_VERSION = "24.3.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 690f5effcb731353a28b34cdd441eddd1931564e Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:23:06 +0200 Subject: [PATCH 344/417] Update airframe-json, airspec to 24.4.2 (#817) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 69cac77a8..35eb55648 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.3.0" +val AIRFRAME_VERSION = "24.4.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 5f273cf4f6ff1ec327701fef613dabc968230ac7 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:23:16 +0200 Subject: [PATCH 345/417] Update scalacheck to 1.17.1 (#815) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 35eb55648..4987196b7 100644 --- a/build.sbt +++ b/build.sbt @@ -87,7 +87,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.17.0" % "test", + "org.scalacheck" %% "scalacheck" % "1.17.1" % "test", // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka From d13e6b10e648fbe41bf3f6aa555aa11fb7168a9a Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:23:25 +0200 Subject: [PATCH 346/417] Update scala-collection-compat to 2.12.0 (#814) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4987196b7..c63a53fad 100644 --- a/build.sbt +++ b/build.sbt @@ -92,7 +92,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.11.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.12.0" % "test" ) ) From 6d0516ec9e53d269f1f208d5af99f439bfda8e5f Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 25 Apr 2024 19:56:54 +0200 Subject: [PATCH 347/417] Update airframe-json, airspec to 24.4.3 (#820) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c63a53fad..a1c02e10f 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.4.2" +val AIRFRAME_VERSION = "24.4.3" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 577c474a9d069ce855772a13c56a7c8b3bbe2d5c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 25 Apr 2024 19:57:01 +0200 Subject: [PATCH 348/417] Update scalacheck to 1.18.0 (#819) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a1c02e10f..fa2cb7821 100644 --- a/build.sbt +++ b/build.sbt @@ -87,7 +87,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.17.1" % "test", + "org.scalacheck" %% "scalacheck" % "1.18.0" % "test", // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka From 141f66dd615e797c96113169371d1767b251a0ae Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 25 Apr 2024 19:57:20 +0200 Subject: [PATCH 349/417] Update jackson-databind to 2.16.2 (#811) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index fa2cb7821..6042dbcdc 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.16.1", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.16.2", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), From 29a44afbc1cbbe7be771897f322cb0b5649dee0b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 8 May 2024 02:46:22 +0200 Subject: [PATCH 350/417] Update sbt to 1.10.0 (#823) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index b089b60c7..16c8f5b8d 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.9 +sbt.version=1.10.0 From 50cf4098c398026a5afe8fd11f43f96f3756cf91 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 8 May 2024 02:46:33 +0200 Subject: [PATCH 351/417] Update airframe-json, airspec to 24.5.0 (#824) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 6042dbcdc..a456a4892 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.4.3" +val AIRFRAME_VERSION = "24.5.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From fedf7ac8c57f4e73b74d30980472a468bbc0a715 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:01:42 +0200 Subject: [PATCH 352/417] Update airframe-json, airspec to 24.5.2 (#826) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a456a4892..0c9f08987 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.5.0" +val AIRFRAME_VERSION = "24.5.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From a3590929a04c91b93db1c9be51589b3ca5275e69 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 9 Jul 2024 20:31:44 +0200 Subject: [PATCH 353/417] Update airframe-json, airspec to 24.7.0 (#829) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0c9f08987..5ecd8cdcf 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.5.2" +val AIRFRAME_VERSION = "24.7.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From abdab0deae9d0c52742f7271a85db53c8dc382ef Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 16 Jul 2024 19:42:36 +0200 Subject: [PATCH 354/417] Update sbt to 1.10.1 (#831) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 16c8f5b8d..74d800f21 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.0 +sbt.version=1.10.1 From ba386c3a7c4ad1e973510a44d6c6a2652675d331 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 22 Jul 2024 20:03:33 +0200 Subject: [PATCH 355/417] Update airframe-json, airspec to 24.7.1 (#832) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 5ecd8cdcf..4087d23bd 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.7.0" +val AIRFRAME_VERSION = "24.7.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 72ead7ea34e0171de1c82d43b3faeeb33ca999fc Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 12 Sep 2024 19:55:52 +0200 Subject: [PATCH 356/417] Update airframe-json, airspec to 24.9.0 (#837) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4087d23bd..b57a6e10c 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.7.1" +val AIRFRAME_VERSION = "24.9.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 4fb85a52caf17703053351e786fc688d4cad6aca Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:33:40 +0200 Subject: [PATCH 357/417] Update sbt to 1.10.2 (#839) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 74d800f21..a1ff42a65 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.1 +sbt.version=1.10.2 From 1b51be899ad61b1a1e7cae9d8ae9ca478274b99b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:33:49 +0200 Subject: [PATCH 358/417] Update scalacheck to 1.18.1 (#840) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index b57a6e10c..a102c0c44 100644 --- a/build.sbt +++ b/build.sbt @@ -87,7 +87,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.18.0" % "test", + "org.scalacheck" %% "scalacheck" % "1.18.1" % "test", // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka From 6b26ad66c869493b960a8ab7a28571068ac982f2 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 8 Oct 2024 02:21:04 +0200 Subject: [PATCH 359/417] Update airframe-json, airspec to 24.9.3 (#844) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a102c0c44..f76b603a5 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.9.0" +val AIRFRAME_VERSION = "24.9.3" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 76bc7d0caac175cf55db47c2a76c2b0af9689283 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 8 Oct 2024 02:23:43 +0200 Subject: [PATCH 360/417] Update sbt-pgp to 2.3.0 (#845) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index aa41287b9..5d631aaee 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") From c48f6594accf3467ce1e97f42a16dd788733ae01 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 10 Oct 2024 21:45:04 +0200 Subject: [PATCH 361/417] Update sbt-sonatype to 3.12.0 (#846) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 5d631aaee..34401fa57 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.0") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From 933b0f2b717f7835095fef2a8b499ed42409ea98 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:53:06 +0100 Subject: [PATCH 362/417] Update sbt, scripted-plugin to 1.10.4 (#852) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index a1ff42a65..3769c4af5 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.2 +sbt.version=1.10.4 From 093837ea3f96ec12a0c0475b67f83c4a7c929d7d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:53:19 +0100 Subject: [PATCH 363/417] Update airframe-json, airspec to 24.10.0 (#850) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f76b603a5..c94b9c3ab 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.9.3" +val AIRFRAME_VERSION = "24.10.0" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 067e0d9b05905805dc65f19cbb6c6da7dae7bbb0 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:53:28 +0100 Subject: [PATCH 364/417] Update sbt-sonatype to 3.12.2 (#847) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 34401fa57..3df907dc3 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.0") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.2") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter From b6bae5b101ba021f2a139d8dbb60160a75822d7c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:53:38 +0100 Subject: [PATCH 365/417] Update sbt-dynver to 5.1.0 (#848) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 3df907dc3..912d52f15 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -6,6 +6,6 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") -addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") +addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.0") scalacOptions ++= Seq("-deprecation", "-feature") From ba0c44fe09313431db0c08fd8f98496cbed3aae7 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Tue, 5 Nov 2024 04:56:37 +0900 Subject: [PATCH 366/417] internal: Avoid deprecated `java.net.URL` constructor (#853) avoid deprecated java.net.URL constructor --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c94b9c3ab..ff396aa20 100644 --- a/build.sbt +++ b/build.sbt @@ -15,7 +15,7 @@ ThisBuild / dynverSeparator := "-" val buildSettings = Seq[Setting[_]]( organization := "org.msgpack", organizationName := "MessagePack", - organizationHomepage := Some(new URL("http://msgpack.org/")), + organizationHomepage := Some(url("http://msgpack.org/")), description := "MessagePack for Java", scalaVersion := "2.13.12", Test / logBuffered := false, From 84fd19761feeb5ec073ed238fb00498bd04994bd Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:16:37 +0100 Subject: [PATCH 367/417] Update sbt, scripted-plugin to 1.10.5 (#854) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 3769c4af5..30c85e4f4 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.4 +sbt.version=1.10.5 From 5161c53c1d3d7760bff84287ecae98c72b9190ea Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sat, 30 Nov 2024 16:35:36 +0900 Subject: [PATCH 368/417] Bump the version of `jackson-databind` (#858) --- build.sbt | 2 +- .../jackson/dataformat/JsonArrayFormat.java | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/build.sbt b/build.sbt index ff396aa20..4a4b23015 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.16.2", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.18.2", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java index 9711e1b88..39155030e 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.introspect.Annotated; -import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; @@ -33,21 +32,4 @@ public JsonFormat.Value findFormat(Annotated ann) return ARRAY_FORMAT; } - - /** - * Defines that unknown properties will be ignored, and won't fail the un-marshalling process. - * Happens in case of de-serialization of a payload that contains more properties than the actual - * value type - */ - @Override - public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) - { - // If the entity contains JsonIgnoreProperties annotation, give it higher priority. - final Boolean precedenceIgnoreUnknownProperties = super.findIgnoreUnknownProperties(ac); - if (precedenceIgnoreUnknownProperties != null) { - return precedenceIgnoreUnknownProperties; - } - - return true; - } } From 33ba1ea6260230a5d46ccd2fe1f64071733eee30 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:05:02 +0100 Subject: [PATCH 369/417] Update sbt-pgp to 2.3.1 (#862) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 912d52f15..e702479f5 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.2") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") From c7907ad886cbf734ae18131ac0553d51baf5965b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:05:11 +0100 Subject: [PATCH 370/417] Update airframe-json, airspec to 24.12.1 (#860) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4a4b23015..ff74b9551 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.10.0" +val AIRFRAME_VERSION = "24.12.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From d2b328e105b567d394d4e58b8d87fdad392db874 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 11 Dec 2024 19:05:21 +0100 Subject: [PATCH 371/417] Update sbt, scripted-plugin to 1.10.6 (#859) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 30c85e4f4..e0a0e7d10 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.5 +sbt.version=1.10.6 From e03d60d0808a021273bdab3a43e59330f6eb8e5c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:32:44 +0100 Subject: [PATCH 372/417] Update airframe-json, airspec to 24.12.2 (#863) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ff74b9551..31280a694 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.12.1" +val AIRFRAME_VERSION = "24.12.2" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 56c0e5ac95c8037958b29eaf53fe591978e20c7d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:23:58 +0100 Subject: [PATCH 373/417] Update sbt, scripted-plugin to 1.10.7 (#865) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e0a0e7d10..8fc29878c 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.6 +sbt.version=1.10.7 From 59219838ffb6236eca84601dad1dd267541c070b Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 5 Jan 2025 19:48:24 +0900 Subject: [PATCH 374/417] Improve the performance of `jackson-dataformat-msgpack` (#866) * Improve the perf of msgpack-jackson * Refactoring --- .../ExtensionTypeCustomDeserializers.java | 10 +- .../msgpack/jackson/dataformat/JavaInfo.java | 41 ++ .../dataformat/MessagePackExtensionType.java | 5 +- .../dataformat/MessagePackFactory.java | 20 +- .../dataformat/MessagePackGenerator.java | 646 +++++++++++------- .../dataformat/MessagePackKeySerializer.java | 3 +- .../jackson/dataformat/MessagePackParser.java | 277 +++----- .../dataformat/MessagePackReadContext.java | 269 ++++++++ .../MessagePackSerializedString.java | 8 +- .../MessagePackDataformatForPojoTest.java | 36 +- .../MessagePackDataformatTestBase.java | 44 +- .../dataformat/MessagePackGeneratorTest.java | 49 +- ...essagePackDataformatPojoBenchmarkTest.java | 28 +- 13 files changed, 946 insertions(+), 490 deletions(-) create mode 100644 msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JavaInfo.java create mode 100644 msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackReadContext.java diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java index ae2e63537..aa5879755 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/ExtensionTypeCustomDeserializers.java @@ -35,15 +35,7 @@ public ExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers src) public void addCustomDeser(byte type, final Deser deser) { - deserTable.put(type, new Deser() - { - @Override - public Object deserialize(byte[] data) - throws IOException - { - return deser.deserialize(data); - } - }); + deserTable.put(type, deser); } public Deser getDeser(byte type) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JavaInfo.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JavaInfo.java new file mode 100644 index 000000000..f5fda8c28 --- /dev/null +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JavaInfo.java @@ -0,0 +1,41 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.jackson.dataformat; + +import java.lang.reflect.Field; +import java.util.function.Supplier; + +public final class JavaInfo +{ + static final Supplier STRING_VALUE_FIELD_IS_CHARS; + static { + boolean stringValueFieldIsChars = false; + try { + Field stringValueField = String.class.getDeclaredField("value"); + stringValueFieldIsChars = stringValueField.getType() == char[].class; + } + catch (NoSuchFieldException ignored) { + } + if (stringValueFieldIsChars) { + STRING_VALUE_FIELD_IS_CHARS = () -> true; + } + else { + STRING_VALUE_FIELD_IS_CHARS = () -> false; + } + } + + private JavaInfo() {} +} diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java index 00b4f7de8..e11c2cd02 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java @@ -1,7 +1,6 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; @@ -52,7 +51,7 @@ public boolean equals(Object o) @Override public int hashCode() { - int result = (int) type; + int result = type; result = 31 * result + Arrays.hashCode(data); return result; } @@ -61,7 +60,7 @@ public static class Serializer extends JsonSerializer { @Override public void serialize(MessagePackExtensionType value, JsonGenerator gen, SerializerProvider serializers) - throws IOException, JsonProcessingException + throws IOException { if (gen instanceof MessagePackGenerator) { MessagePackGenerator msgpackGenerator = (MessagePackGenerator) gen; diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index 1e7acc5e2..bb5064f1f 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -18,7 +18,6 @@ import com.fasterxml.jackson.core.JsonEncoding; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.io.IOContext; import org.msgpack.core.MessagePack; @@ -97,14 +96,13 @@ public JsonGenerator createGenerator(File f, JsonEncoding enc) @Override public JsonGenerator createGenerator(Writer w) - throws IOException { throw new UnsupportedOperationException(); } @Override public JsonParser createParser(byte[] data) - throws IOException, JsonParseException + throws IOException { IOContext ioContext = _createContext(data, false); return _createParser(data, 0, data.length, ioContext); @@ -112,7 +110,7 @@ public JsonParser createParser(byte[] data) @Override public JsonParser createParser(InputStream in) - throws IOException, JsonParseException + throws IOException { IOContext ioContext = _createContext(in, false); return _createParser(in, ioContext); @@ -131,7 +129,7 @@ protected MessagePackParser _createParser(InputStream in, IOContext ctxt) @Override protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) - throws IOException, JsonParseException + throws IOException { if (offset != 0 || len != data.length) { data = Arrays.copyOfRange(data, offset, offset + len); @@ -155,12 +153,6 @@ MessagePack.PackerConfig getPackerConfig() return packerConfig; } - @VisibleForTesting - boolean isReuseResourceInGenerator() - { - return reuseResourceInGenerator; - } - @VisibleForTesting boolean isReuseResourceInParser() { @@ -178,4 +170,10 @@ public String getFormatName() { return "msgpack"; } + + @Override + public boolean canHandleBinaryNatively() + { + return true; + } } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index 96aa6a063..11aba6e59 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -16,14 +16,14 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.core.Base64Variant; -import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.base.GeneratorBase; import com.fasterxml.jackson.core.io.SerializedString; -import com.fasterxml.jackson.core.json.JsonWriteContext; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; +import org.msgpack.core.annotations.Nullable; +import org.msgpack.core.buffer.MessageBufferOutput; import org.msgpack.core.buffer.OutputStreamBufferOutput; import java.io.ByteArrayOutputStream; @@ -33,73 +33,170 @@ import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; +import static org.msgpack.jackson.dataformat.JavaInfo.STRING_VALUE_FIELD_IS_CHARS; + public class MessagePackGenerator extends GeneratorBase { - private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + private static final int IN_ROOT = 0; + private static final int IN_OBJECT = 1; + private static final int IN_ARRAY = 2; private final MessagePacker messagePacker; - private static ThreadLocal messageBufferOutputHolder = new ThreadLocal(); + private static final ThreadLocal messageBufferOutputHolder = new ThreadLocal<>(); private final OutputStream output; private final MessagePack.PackerConfig packerConfig; - private LinkedList stack; - private StackItem rootStackItem; - private abstract static class StackItem + private int currentParentElementIndex = -1; + private int currentState = IN_ROOT; + private final List nodes; + private boolean isElementsClosed = false; + + private static final class AsciiCharString + { + public final byte[] bytes; + + public AsciiCharString(byte[] bytes) + { + this.bytes = bytes; + } + } + + private abstract static class Node + { + // Root containers have -1. + final int parentIndex; + + public Node(int parentIndex) + { + this.parentIndex = parentIndex; + } + + abstract void incrementChildCount(); + + abstract int currentStateAsParent(); + } + + private abstract static class NodeContainer extends Node { - protected List objectKeys = new ArrayList(); - protected List objectValues = new ArrayList(); + // Only for containers. + int childCount; + + public NodeContainer(int parentIndex) + { + super(parentIndex); + } + + @Override + void incrementChildCount() + { + childCount++; + } + } - abstract void addKey(Object key); + private static final class NodeArray extends NodeContainer + { + public NodeArray(int parentIndex) + { + super(parentIndex); + } - void addValue(Object value) + @Override + int currentStateAsParent() { - objectValues.add(value); + return IN_ARRAY; } + } - abstract List getKeys(); + private static final class NodeObject extends NodeContainer + { + public NodeObject(int parentIndex) + { + super(parentIndex); + } - List getValues() + @Override + int currentStateAsParent() { - return objectValues; + return IN_OBJECT; } } - private static class StackItemForObject - extends StackItem + private static final class NodeEntryInArray extends Node { + final Object value; + + public NodeEntryInArray(int parentIndex, Object value) + { + super(parentIndex); + this.value = value; + } + @Override - void addKey(Object key) + void incrementChildCount() { - objectKeys.add(key); + throw new UnsupportedOperationException(); } @Override - List getKeys() + int currentStateAsParent() { - return objectKeys; + throw new UnsupportedOperationException(); } } - private static class StackItemForArray - extends StackItem + private static final class NodeEntryInObject extends Node { + final Object key; + // Lazily initialized. + Object value; + + public NodeEntryInObject(int parentIndex, Object key) + { + super(parentIndex); + this.key = key; + } + @Override - void addKey(Object key) + void incrementChildCount() { - throw new IllegalStateException("This method shouldn't be called"); + assert value instanceof NodeContainer; + ((NodeContainer) value).childCount++; } @Override - List getKeys() + int currentStateAsParent() { - throw new IllegalStateException("This method shouldn't be called"); + if (value instanceof NodeObject) { + return IN_OBJECT; + } + else if (value instanceof NodeArray) { + return IN_ARRAY; + } + else { + throw new AssertionError(); + } } } + // This is an internal constructor for nested serialization. + private MessagePackGenerator( + int features, + ObjectCodec codec, + OutputStream out, + MessagePack.PackerConfig packerConfig) + { + super(features, codec); + this.output = out; + this.messagePacker = packerConfig.newPacker(out); + this.packerConfig = packerConfig; + this.nodes = new ArrayList<>(); + } + public MessagePackGenerator( int features, ObjectCodec codec, @@ -110,7 +207,16 @@ public MessagePackGenerator( { super(features, codec); this.output = out; + this.messagePacker = packerConfig.newPacker(getMessageBufferOutputForOutputStream(out, reuseResourceInGenerator)); + this.packerConfig = packerConfig; + this.nodes = new ArrayList<>(); + } + private MessageBufferOutput getMessageBufferOutputForOutputStream( + OutputStream out, + boolean reuseResourceInGenerator) + throws IOException + { OutputStreamBufferOutput messageBufferOutput; if (reuseResourceInGenerator) { messageBufferOutput = messageBufferOutputHolder.get(); @@ -125,91 +231,106 @@ public MessagePackGenerator( else { messageBufferOutput = new OutputStreamBufferOutput(out); } - this.messagePacker = packerConfig.newPacker(messageBufferOutput); - - this.packerConfig = packerConfig; + return messageBufferOutput; + } - this.stack = new LinkedList(); + private String currentStateStr() + { + switch (currentState) { + case IN_OBJECT: + return "IN_OBJECT"; + case IN_ARRAY: + return "IN_ARRAY"; + default: + return "IN_ROOT"; + } } @Override public void writeStartArray() - throws IOException, JsonGenerationException { - _writeContext = _writeContext.createChildArrayContext(); - stack.push(new StackItemForArray()); + if (currentState == IN_OBJECT) { + Node node = nodes.get(nodes.size() - 1); + assert node instanceof NodeEntryInObject; + NodeEntryInObject nodeEntryInObject = (NodeEntryInObject) node; + nodeEntryInObject.value = new NodeArray(currentParentElementIndex); + } + else { + nodes.add(new NodeArray(currentParentElementIndex)); + } + currentParentElementIndex = nodes.size() - 1; + currentState = IN_ARRAY; } @Override public void writeEndArray() - throws IOException, JsonGenerationException + throws IOException { - if (!_writeContext.inArray()) { - _reportError("Current context not an array but " + _writeContext.getTypeDesc()); + if (currentState != IN_ARRAY) { + _reportError("Current context not an array but " + currentStateStr()); } - - getStackTopForArray(); - - _writeContext = _writeContext.getParent(); - - popStackAndStoreTheItemAsValue(); + endCurrentContainer(); } @Override public void writeStartObject() - throws IOException, JsonGenerationException { - _writeContext = _writeContext.createChildObjectContext(); - stack.push(new StackItemForObject()); + if (currentState == IN_OBJECT) { + Node node = nodes.get(nodes.size() - 1); + assert node instanceof NodeEntryInObject; + NodeEntryInObject nodeEntryInObject = (NodeEntryInObject) node; + nodeEntryInObject.value = new NodeObject(currentParentElementIndex); + } + else { + nodes.add(new NodeObject(currentParentElementIndex)); + } + currentParentElementIndex = nodes.size() - 1; + currentState = IN_OBJECT; } @Override public void writeEndObject() - throws IOException, JsonGenerationException + throws IOException { - if (!_writeContext.inObject()) { - _reportError("Current context not an object but " + _writeContext.getTypeDesc()); + if (currentState != IN_OBJECT) { + _reportError("Current context not an object but " + currentStateStr()); } + endCurrentContainer(); + } - StackItemForObject stackTop = getStackTopForObject(); - - if (stackTop.getKeys().size() != stackTop.getValues().size()) { - throw new IllegalStateException( - String.format( - "objectKeys.size() and objectValues.size() is not same: depth=%d, key=%d, value=%d", - stack.size(), stackTop.getKeys().size(), stackTop.getValues().size())); + private void endCurrentContainer() + { + Node parent = nodes.get(currentParentElementIndex); + if (currentParentElementIndex == 0) { + isElementsClosed = true; + currentParentElementIndex = parent.parentIndex; + return; } - _writeContext = _writeContext.getParent(); - popStackAndStoreTheItemAsValue(); + currentParentElementIndex = parent.parentIndex; + assert currentParentElementIndex >= 0; + Node currentParent = nodes.get(currentParentElementIndex); + currentParent.incrementChildCount(); + currentState = currentParent.currentStateAsParent(); } - private void pack(Object v) + private void packNonContainer(Object v) throws IOException { MessagePacker messagePacker = getMessagePacker(); - if (v == null) { - messagePacker.packNil(); + if (v instanceof String) { + messagePacker.packString((String) v); + } + else if (v instanceof AsciiCharString) { + byte[] bytes = ((AsciiCharString) v).bytes; + messagePacker.packRawStringHeader(bytes.length); + messagePacker.writePayload(bytes); } else if (v instanceof Integer) { messagePacker.packInt((Integer) v); } - else if (v instanceof ByteBuffer) { - ByteBuffer bb = (ByteBuffer) v; - int len = bb.remaining(); - if (bb.hasArray()) { - messagePacker.packBinaryHeader(len); - messagePacker.writePayload(bb.array(), bb.arrayOffset(), len); - } - else { - byte[] data = new byte[len]; - bb.get(data); - messagePacker.packBinaryHeader(len); - messagePacker.addPayload(data); - } - } - else if (v instanceof String) { - messagePacker.packString((String) v); + else if (v == null) { + messagePacker.packNil(); } else if (v instanceof Float) { messagePacker.packFloat((Float) v); @@ -217,12 +338,6 @@ else if (v instanceof Float) { else if (v instanceof Long) { messagePacker.packLong((Long) v); } - else if (v instanceof StackItemForObject) { - packObject((StackItemForObject) v); - } - else if (v instanceof StackItemForArray) { - packArray((StackItemForArray) v); - } else if (v instanceof Double) { messagePacker.packDouble((Double) v); } @@ -235,6 +350,20 @@ else if (v instanceof BigDecimal) { else if (v instanceof Boolean) { messagePacker.packBoolean((Boolean) v); } + else if (v instanceof ByteBuffer) { + ByteBuffer bb = (ByteBuffer) v; + int len = bb.remaining(); + if (bb.hasArray()) { + messagePacker.packBinaryHeader(len); + messagePacker.writePayload(bb.array(), bb.arrayOffset(), len); + } + else { + byte[] data = new byte[len]; + bb.get(data); + messagePacker.packBinaryHeader(len); + messagePacker.addPayload(data); + } + } else if (v instanceof MessagePackExtensionType) { MessagePackExtensionType extensionType = (MessagePackExtensionType) v; byte[] extData = extensionType.getData(); @@ -244,7 +373,7 @@ else if (v instanceof MessagePackExtensionType) { else { messagePacker.flush(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - MessagePackGenerator messagePackGenerator = new MessagePackGenerator(getFeatureMask(), getCodec(), outputStream, packerConfig, false); + MessagePackGenerator messagePackGenerator = new MessagePackGenerator(getFeatureMask(), getCodec(), outputStream, packerConfig); getCodec().writeValue(messagePackGenerator, v); output.write(outputStream.toByteArray()); } @@ -260,10 +389,7 @@ private void packBigDecimal(BigDecimal decimal) BigInteger integer = decimal.toBigIntegerExact(); messagePacker.packBigInteger(integer); } - catch (ArithmeticException e) { - failedToPackAsBI = true; - } - catch (IllegalArgumentException e) { + catch (ArithmeticException | IllegalArgumentException e) { failedToPackAsBI = true; } @@ -278,200 +404,297 @@ private void packBigDecimal(BigDecimal decimal) } } - private void packObject(StackItemForObject stackItem) + private void packObject(NodeObject container) throws IOException { - List keys = stackItem.getKeys(); - List values = stackItem.getValues(); + MessagePacker messagePacker = getMessagePacker(); + messagePacker.packMapHeader(container.childCount); + } + private void packArray(NodeArray container) + throws IOException + { MessagePacker messagePacker = getMessagePacker(); - messagePacker.packMapHeader(keys.size()); + messagePacker.packArrayHeader(container.childCount); + } - for (int i = 0; i < keys.size(); i++) { - pack(keys.get(i)); - pack(values.get(i)); + private void addKeyNode(Object key) + { + if (currentState != IN_OBJECT) { + throw new IllegalStateException(); } + Node node = new NodeEntryInObject(currentParentElementIndex, key); + nodes.add(node); } - private void packArray(StackItemForArray stackItem) - throws IOException + private void addValueNode(Object value) throws IOException { - List values = stackItem.getValues(); + switch (currentState) { + case IN_OBJECT: { + Node node = nodes.get(nodes.size() - 1); + assert node instanceof NodeEntryInObject; + NodeEntryInObject nodeEntryInObject = (NodeEntryInObject) node; + nodeEntryInObject.value = value; + nodes.get(node.parentIndex).incrementChildCount(); + break; + } + case IN_ARRAY: { + Node node = new NodeEntryInArray(currentParentElementIndex, value); + nodes.add(node); + nodes.get(node.parentIndex).incrementChildCount(); + break; + } + default: + packNonContainer(value); + flushMessagePacker(); + break; + } + } - MessagePacker messagePacker = getMessagePacker(); - messagePacker.packArrayHeader(values.size()); + @Nullable + private byte[] getBytesIfAscii(char[] chars, int offset, int len) + { + byte[] bytes = new byte[len]; + for (int i = offset; i < offset + len; i++) { + char c = chars[i]; + if (c >= 0x80) { + return null; + } + bytes[i] = (byte) c; + } + return bytes; + } - for (int i = 0; i < values.size(); i++) { - Object v = values.get(i); - pack(v); + private boolean areAllAsciiBytes(byte[] bytes, int offset, int len) + { + for (int i = offset; i < offset + len; i++) { + if ((bytes[i] & 0x80) != 0) { + return false; + } } + return true; + } + + private void writeCharArrayTextKey(char[] text, int offset, int len) + { + byte[] bytes = getBytesIfAscii(text, offset, len); + if (bytes != null) { + addKeyNode(new AsciiCharString(bytes)); + return; + } + addKeyNode(new String(text, offset, len)); + } + + private void writeCharArrayTextValue(char[] text, int offset, int len) throws IOException + { + byte[] bytes = getBytesIfAscii(text, offset, len); + if (bytes != null) { + addValueNode(new AsciiCharString(bytes)); + return; + } + addValueNode(new String(text, offset, len)); + } + + private void writeByteArrayTextValue(byte[] text, int offset, int len) throws IOException + { + if (areAllAsciiBytes(text, offset, len)) { + addValueNode(new AsciiCharString(text)); + return; + } + addValueNode(new String(text, offset, len, DEFAULT_CHARSET)); + } + + private void writeByteArrayTextKey(byte[] text, int offset, int len) throws IOException + { + if (areAllAsciiBytes(text, offset, len)) { + addValueNode(new AsciiCharString(text)); + return; + } + addValueNode(new String(text, offset, len, DEFAULT_CHARSET)); } @Override public void writeFieldName(String name) - throws IOException, JsonGenerationException { - addKeyToStackTop(name); + if (STRING_VALUE_FIELD_IS_CHARS.get()) { + char[] chars = name.toCharArray(); + writeCharArrayTextKey(chars, 0, chars.length); + } + else { + addKeyNode(name); + } } @Override public void writeFieldName(SerializableString name) - throws IOException { - if (name instanceof MessagePackSerializedString) { - addKeyToStackTop(((MessagePackSerializedString) name).getRawValue()); + if (name instanceof SerializedString) { + writeFieldName(name.getValue()); } - else if (name instanceof SerializedString) { - addKeyToStackTop(name.getValue()); + else if (name instanceof MessagePackSerializedString) { + addKeyNode(((MessagePackSerializedString) name).getRawValue()); } else { - System.out.println(name.getClass()); throw new IllegalArgumentException("Unsupported key: " + name); } } @Override public void writeString(String text) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(text); + if (STRING_VALUE_FIELD_IS_CHARS.get()) { + char[] chars = text.toCharArray(); + writeCharArrayTextValue(chars, 0, chars.length); + } + else { + addValueNode(text); + } } @Override public void writeString(char[] text, int offset, int len) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(new String(text, offset, len)); + writeCharArrayTextValue(text, offset, len); } @Override public void writeRawUTF8String(byte[] text, int offset, int length) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(new String(text, offset, length, DEFAULT_CHARSET)); + writeByteArrayTextValue(text, offset, length); } @Override public void writeUTF8String(byte[] text, int offset, int length) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(new String(text, offset, length, DEFAULT_CHARSET)); + writeByteArrayTextValue(text, offset, length); } @Override public void writeRaw(String text) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(text); + if (STRING_VALUE_FIELD_IS_CHARS.get()) { + char[] chars = text.toCharArray(); + writeCharArrayTextValue(chars, 0, chars.length); + } + else { + addValueNode(text); + } } @Override public void writeRaw(String text, int offset, int len) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(text.substring(0, len)); + // TODO: There is room to optimize this. + char[] chars = text.toCharArray(); + writeCharArrayTextValue(chars, offset, len); } @Override public void writeRaw(char[] text, int offset, int len) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(new String(text, offset, len)); + writeCharArrayTextValue(text, offset, len); } @Override public void writeRaw(char c) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(String.valueOf(c)); + writeCharArrayTextValue(new char[] { c }, 0, 1); } @Override public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(ByteBuffer.wrap(data, offset, len)); + addValueNode(ByteBuffer.wrap(data, offset, len)); } @Override public void writeNumber(int v) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Integer.valueOf(v)); + addValueNode(v); } @Override public void writeNumber(long v) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Long.valueOf(v)); + addValueNode(v); } @Override public void writeNumber(BigInteger v) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(v); + addValueNode(v); } @Override public void writeNumber(double d) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Double.valueOf(d)); + addValueNode(d); } @Override public void writeNumber(float f) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Float.valueOf(f)); + addValueNode(f); } @Override public void writeNumber(BigDecimal dec) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(dec); + addValueNode(dec); } @Override public void writeNumber(String encodedValue) - throws IOException, JsonGenerationException, UnsupportedOperationException + throws IOException, UnsupportedOperationException { // There is a room to improve this API's performance while the implementation is robust. // If users can use other MessagePackGenerator#writeNumber APIs that accept // proper numeric types not String, it's better to use the other APIs instead. try { long l = Long.parseLong(encodedValue); - addValueToStackTop(l); + addValueNode(l); return; } - catch (NumberFormatException e) { + catch (NumberFormatException ignored) { } try { double d = Double.parseDouble(encodedValue); - addValueToStackTop(d); + addValueNode(d); return; } - catch (NumberFormatException e) { + catch (NumberFormatException ignored) { } try { BigInteger bi = new BigInteger(encodedValue); - addValueToStackTop(bi); + addValueNode(bi); return; } - catch (NumberFormatException e) { + catch (NumberFormatException ignored) { } try { BigDecimal bc = new BigDecimal(encodedValue); - addValueToStackTop(bc); + addValueNode(bc); return; } - catch (NumberFormatException e) { + catch (NumberFormatException ignored) { } throw new NumberFormatException(encodedValue); @@ -479,22 +702,22 @@ public void writeNumber(String encodedValue) @Override public void writeBoolean(boolean state) - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(Boolean.valueOf(state)); + addValueNode(state); } @Override public void writeNull() - throws IOException, JsonGenerationException + throws IOException { - addValueToStackTop(null); + addValueNode(null); } public void writeExtensionType(MessagePackExtensionType extensionType) throws IOException { - addValueToStackTop(extensionType); + addValueNode(extensionType); } @Override @@ -516,19 +739,42 @@ public void close() public void flush() throws IOException { - if (rootStackItem != null) { - if (rootStackItem instanceof StackItemForObject) { - packObject((StackItemForObject) rootStackItem); + if (!isElementsClosed) { + // The whole elements are not closed yet. + return; + } + + for (int i = 0; i < nodes.size(); i++) { + Node node = nodes.get(i); + if (node instanceof NodeEntryInObject) { + NodeEntryInObject nodeEntry = (NodeEntryInObject) node; + packNonContainer(nodeEntry.key); + if (nodeEntry.value instanceof NodeObject) { + packObject((NodeObject) nodeEntry.value); + } + else if (nodeEntry.value instanceof NodeArray) { + packArray((NodeArray) nodeEntry.value); + } + else { + packNonContainer(nodeEntry.value); + } + } + else if (node instanceof NodeObject) { + packObject((NodeObject) node); + } + else if (node instanceof NodeEntryInArray) { + packNonContainer(((NodeEntryInArray) node).value); } - else if (rootStackItem instanceof StackItemForArray) { - packArray((StackItemForArray) rootStackItem); + else if (node instanceof NodeArray) { + packArray((NodeArray) node); } else { - throw new IllegalStateException("Unexpected rootStackItem: " + rootStackItem); + throw new AssertionError(); } - rootStackItem = null; - flushMessagePacker(); } + flushMessagePacker(); + nodes.clear(); + isElementsClosed = false; } private void flushMessagePacker() @@ -541,76 +787,18 @@ private void flushMessagePacker() @Override protected void _releaseBuffers() { - } - - @Override - protected void _verifyValueWrite(String typeMsg) - throws IOException, JsonGenerationException - { - int status = _writeContext.writeValue(); - if (status == JsonWriteContext.STATUS_EXPECT_NAME) { - _reportError("Can not " + typeMsg + ", expecting field name"); - } - } - - private StackItem getStackTop() - { - if (stack.isEmpty()) { - throw new IllegalStateException("The stack is empty"); - } - return stack.getFirst(); - } - - private StackItemForObject getStackTopForObject() - { - StackItem stackTop = getStackTop(); - if (!(stackTop instanceof StackItemForObject)) { - throw new IllegalStateException("The stack top should be Object: " + stackTop); - } - return (StackItemForObject) stackTop; - } - - private StackItemForArray getStackTopForArray() - { - StackItem stackTop = getStackTop(); - if (!(stackTop instanceof StackItemForArray)) { - throw new IllegalStateException("The stack top should be Array: " + stackTop); - } - return (StackItemForArray) stackTop; - } - - private void addKeyToStackTop(Object key) - { - getStackTop().addKey(key); - } - - private void addValueToStackTop(Object value) - throws IOException - { - if (stack.isEmpty()) { - pack(value); - flushMessagePacker(); + try { + messagePacker.close(); } - else { - getStackTop().addValue(value); + catch (IOException e) { + throw new RuntimeException("Failed to close MessagePacker", e); } } - private void popStackAndStoreTheItemAsValue() - throws IOException + @Override + protected void _verifyValueWrite(String typeMsg) throws IOException { - StackItem child = stack.pop(); - if (stack.size() > 0) { - addValueToStackTop(child); - } - else { - if (rootStackItem != null) { - throw new IllegalStateException("rootStackItem is not null"); - } - else { - rootStackItem = child; - } - } + // FIXME? } private MessagePacker getMessagePacker() diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackKeySerializer.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackKeySerializer.java index 8eaa80146..36fb235d5 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackKeySerializer.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackKeySerializer.java @@ -15,7 +15,6 @@ // package org.msgpack.jackson.dataformat; -import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; @@ -32,7 +31,7 @@ public MessagePackKeySerializer() @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) - throws JsonGenerationException, IOException + throws IOException { jgen.writeFieldName(new MessagePackSerializedString(value)); } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 2a95b69a0..4876c797c 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -17,9 +17,7 @@ import com.fasterxml.jackson.core.Base64Variant; import com.fasterxml.jackson.core.JsonLocation; -import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonStreamContext; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.ObjectCodec; @@ -28,7 +26,6 @@ import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.io.JsonEOFException; import com.fasterxml.jackson.core.json.DupDetector; -import com.fasterxml.jackson.core.json.JsonReadContext; import org.msgpack.core.ExtensionTypeHeader; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePack; @@ -42,27 +39,29 @@ import java.io.InputStream; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.LinkedList; +import java.nio.charset.StandardCharsets; + +import static org.msgpack.jackson.dataformat.JavaInfo.STRING_VALUE_FIELD_IS_CHARS; public class MessagePackParser extends ParserMinimalBase { - private static final ThreadLocal> messageUnpackerHolder = - new ThreadLocal>(); + private static final ThreadLocal> messageUnpackerHolder = new ThreadLocal<>(); private final MessageUnpacker messageUnpacker; - private static final BigInteger LONG_MIN = BigInteger.valueOf((long) Long.MIN_VALUE); - private static final BigInteger LONG_MAX = BigInteger.valueOf((long) Long.MAX_VALUE); + private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE); + private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); private ObjectCodec codec; - private JsonReadContext parsingContext; + private MessagePackReadContext streamReadContext; - private final LinkedList stack = new LinkedList(); private boolean isClosed; private long tokenPosition; private long currentPosition; private final IOContext ioContext; private ExtensionTypeCustomDeserializers extTypeCustomDesers; + private final byte[] tempBytes = new byte[64]; + private final char[] tempChars = new char[64]; private enum Type { @@ -76,51 +75,6 @@ private enum Type private String stringValue; private BigInteger biValue; private MessagePackExtensionType extensionTypeValue; - private boolean reuseResourceInParser; - - private abstract static class StackItem - { - private long numOfElements; - - protected StackItem(long numOfElements) - { - this.numOfElements = numOfElements; - } - - public void consume() - { - numOfElements--; - } - - public boolean isEmpty() - { - return numOfElements == 0; - } - } - - private static class StackItemForObject - extends StackItem - { - StackItemForObject(long numOfElements) - { - super(numOfElements); - } - } - - private static class StackItemForArray - extends StackItem - { - StackItemForArray(long numOfElements) - { - super(numOfElements); - } - } - - public MessagePackParser(IOContext ctxt, int features, ObjectCodec objectCodec, InputStream in) - throws IOException - { - this(ctxt, features, objectCodec, in, true); - } public MessagePackParser( IOContext ctxt, @@ -133,12 +87,6 @@ public MessagePackParser( this(ctxt, features, new InputStreamBufferInput(in), objectCodec, in, reuseResourceInParser); } - public MessagePackParser(IOContext ctxt, int features, ObjectCodec objectCodec, byte[] bytes) - throws IOException - { - this(ctxt, features, objectCodec, bytes, true); - } - public MessagePackParser( IOContext ctxt, int features, @@ -164,17 +112,12 @@ private MessagePackParser(IOContext ctxt, ioContext = ctxt; DupDetector dups = Feature.STRICT_DUPLICATE_DETECTION.enabledIn(features) ? DupDetector.rootDetector(this) : null; - parsingContext = JsonReadContext.createRootContext(dups); - this.reuseResourceInParser = reuseResourceInParser; + streamReadContext = MessagePackReadContext.createRootContext(dups); if (!reuseResourceInParser) { - this.messageUnpacker = MessagePack.newDefaultUnpacker(input); + messageUnpacker = MessagePack.newDefaultUnpacker(input); return; } - else { - this.messageUnpacker = null; - } - MessageUnpacker messageUnpacker; Tuple messageUnpackerTuple = messageUnpackerHolder.get(); if (messageUnpackerTuple == null) { messageUnpacker = MessagePack.newDefaultUnpacker(input); @@ -189,7 +132,7 @@ private MessagePackParser(IOContext ctxt, } messageUnpacker = messageUnpackerTuple.second(); } - messageUnpackerHolder.set(new Tuple(src, messageUnpacker)); + messageUnpackerHolder.set(new Tuple<>(src, messageUnpacker)); } public void setExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers extTypeCustomDesers) @@ -215,21 +158,47 @@ public Version version() return null; } + private String unpackString(MessageUnpacker messageUnpacker) throws IOException + { + int strLen = messageUnpacker.unpackRawStringHeader(); + if (strLen <= tempBytes.length) { + messageUnpacker.readPayload(tempBytes, 0, strLen); + if (STRING_VALUE_FIELD_IS_CHARS.get()) { + for (int i = 0; i < strLen; i++) { + byte b = tempBytes[i]; + if ((0x80 & b) != 0) { + return new String(tempBytes, 0, strLen, StandardCharsets.UTF_8); + } + tempChars[i] = (char) b; + } + return new String(tempChars, 0, strLen); + } + else { + return new String(tempBytes, 0, strLen); + } + } + else { + byte[] bytes = messageUnpacker.readPayload(strLen); + return new String(bytes, 0, strLen, StandardCharsets.UTF_8); + } + } + @Override - public JsonToken nextToken() - throws IOException, JsonParseException + public JsonToken nextToken() throws IOException { - MessageUnpacker messageUnpacker = getMessageUnpacker(); tokenPosition = messageUnpacker.getTotalReadBytes(); - JsonToken nextToken = null; - if (parsingContext.inObject() || parsingContext.inArray()) { - if (stack.getFirst().isEmpty()) { - stack.pop(); - _currToken = parsingContext.inObject() ? JsonToken.END_OBJECT : JsonToken.END_ARRAY; - parsingContext = parsingContext.getParent(); - - return _currToken; + boolean isObjectValueSet = streamReadContext.inObject() && _currToken != JsonToken.FIELD_NAME; + if (isObjectValueSet) { + if (!streamReadContext.expectMoreValues()) { + streamReadContext = streamReadContext.getParent(); + return _updateToken(JsonToken.END_OBJECT); + } + } + else if (streamReadContext.inArray()) { + if (!streamReadContext.expectMoreValues()) { + streamReadContext = streamReadContext.getParent(); + return _updateToken(JsonToken.END_ARRAY); } } @@ -238,24 +207,19 @@ public JsonToken nextToken() } MessageFormat format = messageUnpacker.getNextFormat(); - ValueType valueType = messageUnpacker.getNextFormat().getValueType(); - - // We should push a new StackItem lazily after updating the current stack. - StackItem newStack = null; + ValueType valueType = format.getValueType(); + JsonToken nextToken; switch (valueType) { - case NIL: - messageUnpacker.unpackNil(); - nextToken = JsonToken.VALUE_NULL; - break; - case BOOLEAN: - boolean b = messageUnpacker.unpackBoolean(); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(Boolean.toString(b)); + case STRING: + type = Type.STRING; + stringValue = unpackString(messageUnpacker); + if (isObjectValueSet) { + streamReadContext.setCurrentName(stringValue); nextToken = JsonToken.FIELD_NAME; } else { - nextToken = b ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE; + nextToken = JsonToken.VALUE_STRING; } break; case INTEGER: @@ -289,42 +253,45 @@ public JsonToken nextToken() break; } - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(String.valueOf(v)); + if (isObjectValueSet) { + streamReadContext.setCurrentName(String.valueOf(v)); nextToken = JsonToken.FIELD_NAME; } else { nextToken = JsonToken.VALUE_NUMBER_INT; } break; - case FLOAT: - type = Type.DOUBLE; - doubleValue = messageUnpacker.unpackDouble(); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(String.valueOf(doubleValue)); + case NIL: + messageUnpacker.unpackNil(); + nextToken = JsonToken.VALUE_NULL; + break; + case BOOLEAN: + boolean b = messageUnpacker.unpackBoolean(); + if (isObjectValueSet) { + streamReadContext.setCurrentName(Boolean.toString(b)); nextToken = JsonToken.FIELD_NAME; } else { - nextToken = JsonToken.VALUE_NUMBER_FLOAT; + nextToken = b ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE; } break; - case STRING: - type = Type.STRING; - stringValue = messageUnpacker.unpackString(); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(stringValue); + case FLOAT: + type = Type.DOUBLE; + doubleValue = messageUnpacker.unpackDouble(); + if (isObjectValueSet) { + streamReadContext.setCurrentName(String.valueOf(doubleValue)); nextToken = JsonToken.FIELD_NAME; } else { - nextToken = JsonToken.VALUE_STRING; + nextToken = JsonToken.VALUE_NUMBER_FLOAT; } break; case BINARY: type = Type.BYTES; int len = messageUnpacker.unpackBinaryHeader(); bytesValue = messageUnpacker.readPayload(len); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(new String(bytesValue, MessagePack.UTF8)); + if (isObjectValueSet) { + streamReadContext.setCurrentName(new String(bytesValue, MessagePack.UTF8)); nextToken = JsonToken.FIELD_NAME; } else { @@ -332,17 +299,19 @@ public JsonToken nextToken() } break; case ARRAY: - newStack = new StackItemForArray(messageUnpacker.unpackArrayHeader()); + nextToken = JsonToken.START_ARRAY; + streamReadContext = streamReadContext.createChildArrayContext(messageUnpacker.unpackArrayHeader()); break; case MAP: - newStack = new StackItemForObject(messageUnpacker.unpackMapHeader()); + nextToken = JsonToken.START_OBJECT; + streamReadContext = streamReadContext.createChildObjectContext(messageUnpacker.unpackMapHeader()); break; case EXTENSION: type = Type.EXT; ExtensionTypeHeader header = messageUnpacker.unpackExtensionTypeHeader(); extensionTypeValue = new MessagePackExtensionType(header.getType(), messageUnpacker.readPayload(header.getLength())); - if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { - parsingContext.setCurrentName(deserializedExtensionTypeValue().toString()); + if (isObjectValueSet) { + streamReadContext.setCurrentName(deserializedExtensionTypeValue().toString()); nextToken = JsonToken.FIELD_NAME; } else { @@ -354,35 +323,18 @@ public JsonToken nextToken() } currentPosition = messageUnpacker.getTotalReadBytes(); - if (parsingContext.inObject() && nextToken != JsonToken.FIELD_NAME || parsingContext.inArray()) { - stack.getFirst().consume(); - } - - if (newStack != null) { - stack.push(newStack); - if (newStack instanceof StackItemForArray) { - nextToken = JsonToken.START_ARRAY; - parsingContext = parsingContext.createChildArrayContext(-1, -1); - } - else if (newStack instanceof StackItemForObject) { - nextToken = JsonToken.START_OBJECT; - parsingContext = parsingContext.createChildObjectContext(-1, -1); - } - } - _currToken = nextToken; + _updateToken(nextToken); return nextToken; } @Override protected void _handleEOF() - throws JsonParseException { } @Override - public String getText() - throws IOException, JsonParseException + public String getText() throws IOException { switch (type) { case STRING: @@ -405,8 +357,7 @@ public String getText() } @Override - public char[] getTextCharacters() - throws IOException, JsonParseException + public char[] getTextCharacters() throws IOException { return getText().toCharArray(); } @@ -418,22 +369,19 @@ public boolean hasTextCharacters() } @Override - public int getTextLength() - throws IOException, JsonParseException + public int getTextLength() throws IOException { return getText().length(); } @Override public int getTextOffset() - throws IOException, JsonParseException { return 0; } @Override public byte[] getBinaryValue(Base64Variant b64variant) - throws IOException, JsonParseException { switch (type) { case BYTES: @@ -449,7 +397,6 @@ public byte[] getBinaryValue(Base64Variant b64variant) @Override public Number getNumberValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -467,7 +414,6 @@ public Number getNumberValue() @Override public int getIntValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -485,7 +431,6 @@ public int getIntValue() @Override public long getLongValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -503,7 +448,6 @@ public long getLongValue() @Override public BigInteger getBigIntegerValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -521,7 +465,6 @@ public BigInteger getBigIntegerValue() @Override public float getFloatValue() - throws IOException, JsonParseException { switch (type) { case INT: @@ -539,11 +482,10 @@ public float getFloatValue() @Override public double getDoubleValue() - throws IOException, JsonParseException { switch (type) { case INT: - return (double) intValue; + return intValue; case LONG: return (double) longValue; case DOUBLE: @@ -557,7 +499,6 @@ public double getDoubleValue() @Override public BigDecimal getDecimalValue() - throws IOException { switch (type) { case INT: @@ -586,8 +527,7 @@ private Object deserializedExtensionTypeValue() } @Override - public Object getEmbeddedObject() - throws IOException, JsonParseException + public Object getEmbeddedObject() throws IOException { switch (type) { case BYTES: @@ -601,7 +541,6 @@ public Object getEmbeddedObject() @Override public NumberType getNumberType() - throws IOException, JsonParseException { switch (type) { case INT: @@ -623,7 +562,6 @@ public void close() { try { if (isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)) { - MessageUnpacker messageUnpacker = getMessageUnpacker(); messageUnpacker.close(); } } @@ -641,7 +579,7 @@ public boolean isClosed() @Override public JsonStreamContext getParsingContext() { - return parsingContext; + return streamReadContext; } @Override @@ -659,41 +597,34 @@ public JsonLocation getCurrentLocation() @Override public void overrideCurrentName(String name) { + // Simple, but need to look for START_OBJECT/ARRAY's "off-by-one" thing: + MessagePackReadContext ctxt = streamReadContext; + if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { + ctxt = ctxt.getParent(); + } + // Unfortunate, but since we did not expose exceptions, need to wrap try { - if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { - JsonReadContext parent = parsingContext.getParent(); - parent.setCurrentName(name); - } - else { - parsingContext.setCurrentName(name); - } + ctxt.setCurrentName(name); } - catch (JsonProcessingException e) { + catch (IOException e) { throw new IllegalStateException(e); } } @Override - public String getCurrentName() - throws IOException + public String currentName() { if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { - JsonReadContext parent = parsingContext.getParent(); + MessagePackReadContext parent = streamReadContext.getParent(); return parent.getCurrentName(); } - return parsingContext.getCurrentName(); + return streamReadContext.getCurrentName(); } - private MessageUnpacker getMessageUnpacker() + @Override + public String getCurrentName() + throws IOException { - if (!reuseResourceInParser) { - return this.messageUnpacker; - } - - Tuple messageUnpackerTuple = messageUnpackerHolder.get(); - if (messageUnpackerTuple == null) { - throw new IllegalStateException("messageUnpacker is null"); - } - return messageUnpackerTuple.second(); + return currentName(); } } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackReadContext.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackReadContext.java new file mode 100644 index 000000000..403f1b368 --- /dev/null +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackReadContext.java @@ -0,0 +1,269 @@ +package org.msgpack.jackson.dataformat; + +import com.fasterxml.jackson.core.JsonLocation; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonStreamContext; +import com.fasterxml.jackson.core.io.CharTypes; +import com.fasterxml.jackson.core.io.ContentReference; +import com.fasterxml.jackson.core.json.DupDetector; + +/** + * Replacement of {@link com.fasterxml.jackson.core.json.JsonReadContext} + * to support features needed by MessagePack format. + */ +public final class MessagePackReadContext + extends JsonStreamContext +{ + /** + * Parent context for this context; null for root context. + */ + protected final MessagePackReadContext parent; + + // // // Optional duplicate detection + + protected final DupDetector dups; + + /** + * For fixed-size Arrays, Objects, this indicates expected number of entries. + */ + protected int expEntryCount; + + // // // Location information (minus source reference) + + protected String currentName; + + protected Object currentValue; + + /* + /********************************************************** + /* Simple instance reuse slots + /********************************************************** + */ + + protected MessagePackReadContext child = null; + + /* + /********************************************************** + /* Instance construction, reuse + /********************************************************** + */ + + public MessagePackReadContext(MessagePackReadContext parent, DupDetector dups, + int type, int expEntryCount) + { + super(); + this.parent = parent; + this.dups = dups; + _type = type; + this.expEntryCount = expEntryCount; + _index = -1; + _nestingDepth = parent == null ? 0 : parent._nestingDepth + 1; + } + + protected void reset(int type, int expEntryCount) + { + _type = type; + this.expEntryCount = expEntryCount; + _index = -1; + currentName = null; + currentValue = null; + if (dups != null) { + dups.reset(); + } + } + + @Override + public Object getCurrentValue() + { + return currentValue; + } + + @Override + public void setCurrentValue(Object v) + { + currentValue = v; + } + + // // // Factory methods + + public static MessagePackReadContext createRootContext(DupDetector dups) + { + return new MessagePackReadContext(null, dups, TYPE_ROOT, -1); + } + + public MessagePackReadContext createChildArrayContext(int expEntryCount) + { + MessagePackReadContext ctxt = child; + if (ctxt == null) { + ctxt = new MessagePackReadContext(this, + (dups == null) ? null : dups.child(), + TYPE_ARRAY, expEntryCount); + child = ctxt; + } + else { + ctxt.reset(TYPE_ARRAY, expEntryCount); + } + return ctxt; + } + + public MessagePackReadContext createChildObjectContext(int expEntryCount) + { + MessagePackReadContext ctxt = child; + if (ctxt == null) { + ctxt = new MessagePackReadContext(this, + (dups == null) ? null : dups.child(), + TYPE_OBJECT, expEntryCount); + child = ctxt; + return ctxt; + } + ctxt.reset(TYPE_OBJECT, expEntryCount); + return ctxt; + } + + /* + /********************************************************** + /* Abstract method implementation + /********************************************************** + */ + + @Override + public String getCurrentName() + { + return currentName; + } + + @Override + public MessagePackReadContext getParent() + { + return parent; + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + public boolean hasExpectedLength() + { + return (expEntryCount >= 0); + } + + public int getExpectedLength() + { + return expEntryCount; + } + + public boolean isEmpty() + { + return expEntryCount == 0; + } + + public int getRemainingExpectedLength() + { + int diff = expEntryCount - _index; + // Negative values would occur when expected count is -1 + return Math.max(0, diff); + } + + public boolean acceptsBreakMarker() + { + return (expEntryCount < 0) && _type != TYPE_ROOT; + } + + /** + * Method called to increment the current entry count (Object property, Array + * element or Root value) for this context level + * and then see if more entries are accepted. + * The only case where more entries are NOT expected is for fixed-count + * Objects and Arrays that just reached the entry count. + *

      + * Note that since the entry count is updated this is a state-changing method. + */ + public boolean expectMoreValues() + { + if (++_index == expEntryCount) { + return false; + } + return true; + } + + /** + * @return Location pointing to the point where the context + * start marker was found + */ + @Override + public JsonLocation startLocation(ContentReference srcRef) + { + return new JsonLocation(srcRef, 1L, -1, -1); + } + + @Override + @Deprecated // since 2.13 + public JsonLocation getStartLocation(Object rawSrc) + { + return startLocation(ContentReference.rawReference(rawSrc)); + } + + /* + /********************************************************** + /* State changes + /********************************************************** + */ + + public void setCurrentName(String name) throws JsonProcessingException + { + currentName = name; + if (dups != null) { + _checkDup(dups, name); + } + } + + private void _checkDup(DupDetector dd, String name) throws JsonProcessingException + { + if (dd.isDup(name)) { + throw new JsonParseException(null, + "Duplicate field '" + name + "'", dd.findLocation()); + } + } + + /* + /********************************************************** + /* Overridden standard methods + /********************************************************** + */ + + /** + * Overridden to provide developer readable "JsonPath" representation + * of the context. + */ + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(64); + switch (_type) { + case TYPE_ROOT: + sb.append("/"); + break; + case TYPE_ARRAY: + sb.append('['); + sb.append(getCurrentIndex()); + sb.append(']'); + break; + case TYPE_OBJECT: + sb.append('{'); + if (currentName != null) { + sb.append('"'); + CharTypes.appendQuoted(sb, currentName); + sb.append('"'); + } + else { + sb.append('?'); + } + sb.append('}'); + break; + } + return sb.toString(); + } +} diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializedString.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializedString.java index c7c65ff2b..72ed5d8de 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializedString.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializedString.java @@ -17,15 +17,15 @@ import com.fasterxml.jackson.core.SerializableString; -import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; public class MessagePackSerializedString implements SerializableString { - private static final Charset UTF8 = Charset.forName("UTF-8"); + private static final Charset UTF8 = StandardCharsets.UTF_8; private final Object value; public MessagePackSerializedString(Object value) @@ -89,28 +89,24 @@ public int appendUnquoted(char[] chars, int i) @Override public int writeQuotedUTF8(OutputStream outputStream) - throws IOException { return 0; } @Override public int writeUnquotedUTF8(OutputStream outputStream) - throws IOException { return 0; } @Override public int putQuotedUTF8(ByteBuffer byteBuffer) - throws IOException { return 0; } @Override public int putUnquotedUTF8(ByteBuffer byteBuffer) - throws IOException { return 0; } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java index c6b020686..52269a7d1 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java @@ -46,6 +46,7 @@ public void testNormal() assertArrayEquals(normalPojo.b, value.b); assertEquals(normalPojo.bi, value.bi); assertEquals(normalPojo.suit, Suit.HEART); + assertEquals(normalPojo.sMultibyte, value.sMultibyte); } @Test @@ -59,13 +60,38 @@ public void testNestedList() } @Test - public void testNestedListComplex() + public void testNestedListComplex1() throws IOException { - byte[] bytes = objectMapper.writeValueAsBytes(nestedListComplexPojo); - NestedListComplexPojo value = objectMapper.readValue(bytes, NestedListComplexPojo.class); - assertEquals(nestedListPojo.s, value.s); - assertEquals(nestedListComplexPojo.foos.get(0).t, value.foos.get(0).t); + byte[] bytes = objectMapper.writeValueAsBytes(nestedListComplexPojo1); + NestedListComplexPojo1 value = objectMapper.readValue(bytes, NestedListComplexPojo1.class); + assertEquals(nestedListComplexPojo1.s, value.s); + assertEquals(1, nestedListComplexPojo1.foos.size()); + assertEquals(nestedListComplexPojo1.foos.get(0).t, value.foos.get(0).t); + } + + @Test + public void testNestedListComplex2() + throws IOException + { + byte[] bytes = objectMapper.writeValueAsBytes(nestedListComplexPojo2); + NestedListComplexPojo2 value = objectMapper.readValue(bytes, NestedListComplexPojo2.class); + assertEquals(nestedListComplexPojo2.s, value.s); + assertEquals(2, nestedListComplexPojo2.foos.size()); + assertEquals(nestedListComplexPojo2.foos.get(0).t, value.foos.get(0).t); + assertEquals(nestedListComplexPojo2.foos.get(1).t, value.foos.get(1).t); + } + + @Test + public void testStrings() + throws IOException + { + byte[] bytes = objectMapper.writeValueAsBytes(stringPojo); + StringPojo value = objectMapper.readValue(bytes, StringPojo.class); + assertEquals(stringPojo.shortSingleByte, value.shortSingleByte); + assertEquals(stringPojo.longSingleByte, value.longSingleByte); + assertEquals(stringPojo.shortMultiByte, value.shortMultiByte); + assertEquals(stringPojo.longMultiByte, value.longMultiByte); } @Test diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java index d2d3d456a..b9ef4cf3d 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java @@ -43,7 +43,9 @@ public class MessagePackDataformatTestBase protected ObjectMapper objectMapper; protected NormalPojo normalPojo; protected NestedListPojo nestedListPojo; - protected NestedListComplexPojo nestedListComplexPojo; + protected NestedListComplexPojo1 nestedListComplexPojo1; + protected NestedListComplexPojo2 nestedListComplexPojo2; + protected StringPojo stringPojo; protected TinyPojo tinyPojo; protected ComplexPojo complexPojo; @@ -65,18 +67,31 @@ public void setup() normalPojo.b = new byte[] {0x01, 0x02, (byte) 0xFE, (byte) 0xFF}; normalPojo.bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); normalPojo.suit = Suit.HEART; + normalPojo.sMultibyte = "text文字"; nestedListPojo = new NestedListPojo(); nestedListPojo.s = "a string"; - nestedListPojo.strs = Arrays.asList("string", "another string", "another string"); + nestedListPojo.strs = Arrays.asList("string#1", "string#2", "string#3"); tinyPojo = new TinyPojo(); tinyPojo.t = "t string"; - nestedListComplexPojo = new NestedListComplexPojo(); - nestedListComplexPojo.s = "a string"; - nestedListComplexPojo.foos = new ArrayList(); - nestedListComplexPojo.foos.add(tinyPojo); + nestedListComplexPojo1 = new NestedListComplexPojo1(); + nestedListComplexPojo1.s = "a string"; + nestedListComplexPojo1.foos = new ArrayList<>(); + nestedListComplexPojo1.foos.add(tinyPojo); + + nestedListComplexPojo2 = new NestedListComplexPojo2(); + nestedListComplexPojo2.foos = new ArrayList<>(); + nestedListComplexPojo2.foos.add(tinyPojo); + nestedListComplexPojo2.foos.add(tinyPojo); + nestedListComplexPojo2.s = "another string"; + + stringPojo = new StringPojo(); + stringPojo.shortSingleByte = "hello"; + stringPojo.longSingleByte = "helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworld"; + stringPojo.shortMultiByte = "こんにちは"; + stringPojo.longMultiByte = "こんにちは、世界!!こんにちは、世界!!こんにちは、世界!!こんにちは、世界!!こんにちは、世界!!"; complexPojo = new ComplexPojo(); complexPojo.name = "komamitsu"; @@ -131,12 +146,26 @@ public static class TinyPojo public String t; } - public static class NestedListComplexPojo + public static class NestedListComplexPojo1 { public String s; public List foos; } + public static class NestedListComplexPojo2 + { + public List foos; + public String s; + } + + public static class StringPojo + { + public String shortSingleByte; + public String longSingleByte; + public String shortMultiByte; + public String longMultiByte; + } + public static class NormalPojo { String s; @@ -148,6 +177,7 @@ public static class NormalPojo public byte[] b; public BigInteger bi; public Suit suit; + public String sMultibyte; public String getS() { diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index 931a33f57..7ba48a613 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -40,6 +40,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -283,6 +284,8 @@ public void testWritePrimitives() generator.writeNumber(0); generator.writeString("one"); generator.writeNumber(2.0f); + generator.writeString("三"); + generator.writeString("444④"); generator.flush(); generator.close(); @@ -291,6 +294,8 @@ public void testWritePrimitives() assertEquals(0, unpacker.unpackInt()); assertEquals("one", unpacker.unpackString()); assertEquals(2.0f, unpacker.unpackFloat(), 0.001f); + assertEquals("三", unpacker.unpackString()); + assertEquals("444④", unpacker.unpackString()); assertFalse(unpacker.hasNext()); } @@ -382,23 +387,24 @@ public void testWritePrimitiveObjectViaObjectMapper() throws Exception { File tempFile = createTempFile(); - OutputStream out = new FileOutputStream(tempFile); - - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); - objectMapper.writeValue(out, 1); - objectMapper.writeValue(out, "two"); - objectMapper.writeValue(out, 3.14); - objectMapper.writeValue(out, Arrays.asList(4)); - objectMapper.writeValue(out, 5L); - - MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(new FileInputStream(tempFile)); - assertEquals(1, unpacker.unpackInt()); - assertEquals("two", unpacker.unpackString()); - assertEquals(3.14, unpacker.unpackFloat(), 0.0001); - assertEquals(1, unpacker.unpackArrayHeader()); - assertEquals(4, unpacker.unpackInt()); - assertEquals(5, unpacker.unpackLong()); + try (OutputStream out = Files.newOutputStream(tempFile.toPath())) { + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + objectMapper.writeValue(out, 1); + objectMapper.writeValue(out, "two"); + objectMapper.writeValue(out, 3.14); + objectMapper.writeValue(out, Arrays.asList(4)); + objectMapper.writeValue(out, 5L); + } + + try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(new FileInputStream(tempFile))) { + assertEquals(1, unpacker.unpackInt()); + assertEquals("two", unpacker.unpackString()); + assertEquals(3.14, unpacker.unpackFloat(), 0.0001); + assertEquals(1, unpacker.unpackArrayHeader()); + assertEquals(4, unpacker.unpackInt()); + assertEquals(5, unpacker.unpackLong()); + } } @Test @@ -442,10 +448,11 @@ public Exception call() throw exception; } else { - ByteArrayOutputStream outputStream = buffers.get(ti); - MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(outputStream.toByteArray()); - for (int i = 0; i < loopCount; i++) { - assertEquals(ti, unpacker.unpackInt()); + try (ByteArrayOutputStream outputStream = buffers.get(ti); + MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(outputStream.toByteArray())) { + for (int i = 0; i < loopCount; i++) { + assertEquals(ti, unpacker.unpackInt()); + } } } } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java index 179b09891..2713eaea3 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java @@ -15,7 +15,6 @@ // package org.msgpack.jackson.dataformat.benchmark; -import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; @@ -23,9 +22,6 @@ import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.NormalPojo; import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.Suit; -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStream; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; @@ -45,9 +41,6 @@ public class MessagePackDataformatPojoBenchmarkTest public MessagePackDataformatPojoBenchmarkTest() { - origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); - msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); - for (int i = 0; i < LOOP_MAX; i++) { NormalPojo pojo = new NormalPojo(); pojo.i = i; @@ -76,6 +69,7 @@ public MessagePackDataformatPojoBenchmarkTest() break; } pojo.b = new byte[] {(byte) i}; + pojo.sMultibyte = "012345678Ⅸ"; pojos.add(pojo); } @@ -104,14 +98,6 @@ public void testBenchmark() { Benchmarker benchmarker = new Benchmarker(); - File tempFileJackson = File.createTempFile("msgpack-jackson-", "-huge-jackson"); - tempFileJackson.deleteOnExit(); - final OutputStream outputStreamJackson = new FileOutputStream(tempFileJackson); - - File tempFileMsgpack = File.createTempFile("msgpack-jackson-", "-huge-msgpack"); - tempFileMsgpack.deleteOnExit(); - final OutputStream outputStreamMsgpack = new FileOutputStream(tempFileMsgpack); - benchmarker.addBenchmark(new Benchmarker.Benchmarkable("serialize(pojo) with JSON") { @Override public void run() @@ -119,7 +105,7 @@ public void run() { for (int j = 0; j < LOOP_FACTOR_SER; j++) { for (int i = 0; i < LOOP_MAX; i++) { - origObjectMapper.writeValue(outputStreamJackson, pojos.get(i)); + origObjectMapper.writeValueAsBytes(pojos.get(i)); } } } @@ -132,7 +118,7 @@ public void run() { for (int j = 0; j < LOOP_FACTOR_SER; j++) { for (int i = 0; i < LOOP_MAX; i++) { - msgpackObjectMapper.writeValue(outputStreamMsgpack, pojos.get(i)); + msgpackObjectMapper.writeValueAsBytes(pojos.get(i)); } } } @@ -164,12 +150,6 @@ public void run() } }); - try { - benchmarker.run(COUNT, WARMUP_COUNT); - } - finally { - outputStreamJackson.close(); - outputStreamMsgpack.close(); - } + benchmarker.run(COUNT, WARMUP_COUNT); } } From ae7a883b3d3c3fee028dc944300ecd94d2969f7b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 4 Feb 2025 06:56:46 +0100 Subject: [PATCH 375/417] Update airframe-json, airspec to 2025.1.1 (#872) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 31280a694..82ec44f0f 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "24.12.2" +val AIRFRAME_VERSION = "2025.1.1" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 91bc7f2029c4bb6e8c489fecf8c1525f0111012e Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 4 Feb 2025 06:56:56 +0100 Subject: [PATCH 376/417] Update scala-collection-compat to 2.13.0 (#871) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 82ec44f0f..235f6286f 100644 --- a/build.sbt +++ b/build.sbt @@ -92,7 +92,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.12.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.13.0" % "test" ) ) From f480b7bf828f08961f85a671758bd7f383136956 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 4 Feb 2025 06:57:07 +0100 Subject: [PATCH 377/417] Update sbt-scalafmt to 2.5.4 (#869) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index e702479f5..01d5e0ad6 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,7 +5,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.4") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.0") scalacOptions ++= Seq("-deprecation", "-feature") From 1cbd05f7ad1a44d8d78f6a6d55f0ce0fe78f386c Mon Sep 17 00:00:00 2001 From: brenbar <12563144+brenbar@users.noreply.github.com> Date: Mon, 10 Feb 2025 19:55:08 -0600 Subject: [PATCH 378/417] Add support for jackson field ids (#868) * Add test demonstrating field id case * Fix java 8 error * Add missing import * Add missing throws * Cleanup unused imports * Cleanup test * Implement jackson field ids * Address feedback from @komamitsu * Address feedback from @komamitsu * Address feedback from @komamitsu --- .../dataformat/MessagePackFactory.java | 9 +- .../dataformat/MessagePackGenerator.java | 22 ++- .../jackson/dataformat/MessagePackParser.java | 5 + .../MessagePackDataformatForFieldIdTest.java | 132 ++++++++++++++++++ 4 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForFieldIdTest.java diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index bb5064f1f..dbd2a4658 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -39,6 +39,7 @@ public class MessagePackFactory private final MessagePack.PackerConfig packerConfig; private boolean reuseResourceInGenerator = true; private boolean reuseResourceInParser = true; + private boolean supportIntegerKeys = false; private ExtensionTypeCustomDeserializers extTypeCustomDesers; public MessagePackFactory() @@ -74,6 +75,12 @@ public MessagePackFactory setReuseResourceInParser(boolean reuseResourceInParser return this; } + public MessagePackFactory setSupportIntegerKeys(boolean supportIntegerKeys) + { + this.supportIntegerKeys = supportIntegerKeys; + return this; + } + public MessagePackFactory setExtTypeCustomDesers(ExtensionTypeCustomDeserializers extTypeCustomDesers) { this.extTypeCustomDesers = extTypeCustomDesers; @@ -84,7 +91,7 @@ public MessagePackFactory setExtTypeCustomDesers(ExtensionTypeCustomDeserializer public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException { - return new MessagePackGenerator(_generatorFeatures, _objectCodec, out, packerConfig, reuseResourceInGenerator); + return new MessagePackGenerator(_generatorFeatures, _objectCodec, out, packerConfig, reuseResourceInGenerator, supportIntegerKeys); } @Override diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index 11aba6e59..abb5089e9 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -50,6 +50,7 @@ public class MessagePackGenerator private static final ThreadLocal messageBufferOutputHolder = new ThreadLocal<>(); private final OutputStream output; private final MessagePack.PackerConfig packerConfig; + private final boolean supportIntegerKeys; private int currentParentElementIndex = -1; private int currentState = IN_ROOT; @@ -188,13 +189,15 @@ private MessagePackGenerator( int features, ObjectCodec codec, OutputStream out, - MessagePack.PackerConfig packerConfig) + MessagePack.PackerConfig packerConfig, + boolean supportIntegerKeys) { super(features, codec); this.output = out; this.messagePacker = packerConfig.newPacker(out); this.packerConfig = packerConfig; this.nodes = new ArrayList<>(); + this.supportIntegerKeys = supportIntegerKeys; } public MessagePackGenerator( @@ -202,7 +205,8 @@ public MessagePackGenerator( ObjectCodec codec, OutputStream out, MessagePack.PackerConfig packerConfig, - boolean reuseResourceInGenerator) + boolean reuseResourceInGenerator, + boolean supportIntegerKeys) throws IOException { super(features, codec); @@ -210,6 +214,7 @@ public MessagePackGenerator( this.messagePacker = packerConfig.newPacker(getMessageBufferOutputForOutputStream(out, reuseResourceInGenerator)); this.packerConfig = packerConfig; this.nodes = new ArrayList<>(); + this.supportIntegerKeys = supportIntegerKeys; } private MessageBufferOutput getMessageBufferOutputForOutputStream( @@ -373,7 +378,7 @@ else if (v instanceof MessagePackExtensionType) { else { messagePacker.flush(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - MessagePackGenerator messagePackGenerator = new MessagePackGenerator(getFeatureMask(), getCodec(), outputStream, packerConfig); + MessagePackGenerator messagePackGenerator = new MessagePackGenerator(getFeatureMask(), getCodec(), outputStream, packerConfig, supportIntegerKeys); getCodec().writeValue(messagePackGenerator, v); output.write(outputStream.toByteArray()); } @@ -513,6 +518,17 @@ private void writeByteArrayTextKey(byte[] text, int offset, int len) throws IOEx addValueNode(new String(text, offset, len, DEFAULT_CHARSET)); } + @Override + public void writeFieldId(long id) throws IOException + { + if (this.supportIntegerKeys) { + addKeyNode(id); + } + else { + super.writeFieldId(id); + } + } + @Override public void writeFieldName(String name) { diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 4876c797c..e59b7f57c 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -621,6 +621,11 @@ public String currentName() return streamReadContext.getCurrentName(); } + public boolean isCurrentFieldId() + { + return this.type == Type.INT || this.type == Type.LONG; + } + @Override public String getCurrentName() throws IOException diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForFieldIdTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForFieldIdTest.java new file mode 100644 index 000000000..0e102ba8c --- /dev/null +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForFieldIdTest.java @@ -0,0 +1,132 @@ +// +// MessagePack for Java +// +// 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 org.msgpack.jackson.dataformat; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.KeyDeserializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.NullValueProvider; +import com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators; +import com.fasterxml.jackson.databind.deser.std.MapDeserializer; +import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.type.TypeFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.LinkedHashMap; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MessagePackDataformatForFieldIdTest +{ + static class MessagePackMapDeserializer extends MapDeserializer + { + public static KeyDeserializer keyDeserializer = new KeyDeserializer() + { + @Override + public Object deserializeKey(String s, DeserializationContext deserializationContext) + throws IOException + { + JsonParser parser = deserializationContext.getParser(); + if (parser instanceof MessagePackParser) { + MessagePackParser p = (MessagePackParser) parser; + if (p.isCurrentFieldId()) { + return Integer.valueOf(s); + } + } + return s; + } + }; + + public MessagePackMapDeserializer() + { + super( + TypeFactory.defaultInstance().constructMapType(Map.class, Object.class, Object.class), + JDKValueInstantiators.findStdValueInstantiator(null, LinkedHashMap.class), + keyDeserializer, null, null); + } + + public MessagePackMapDeserializer(MapDeserializer src, KeyDeserializer keyDeser, + JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser, NullValueProvider nuller, + Set ignorable, Set includable) + { + super(src, keyDeser, valueDeser, valueTypeDeser, nuller, ignorable, includable); + } + + @Override + protected MapDeserializer withResolved(KeyDeserializer keyDeser, TypeDeserializer valueTypeDeser, + JsonDeserializer valueDeser, NullValueProvider nuller, Set ignorable, + Set includable) + { + return new MessagePackMapDeserializer(this, keyDeser, (JsonDeserializer) valueDeser, valueTypeDeser, + nuller, ignorable, includable); + } + } + + @Test + public void testMixedKeys() + throws IOException + { + ObjectMapper mapper = new ObjectMapper( + new MessagePackFactory() + .setSupportIntegerKeys(true) + ) + .registerModule(new SimpleModule() + .addDeserializer(Map.class, new MessagePackMapDeserializer())); + + Map map = new HashMap<>(); + map.put(1, "one"); + map.put("2", "two"); + + byte[] bytes = mapper.writeValueAsBytes(map); + Map deserializedInit = mapper.readValue(bytes, new TypeReference>() {}); + + Map expected = new HashMap<>(map); + Map actual = new HashMap<>(deserializedInit); + + assertEquals(expected, actual); + } + + @Test + public void testMixedKeysBackwardsCompatiable() + throws IOException + { + ObjectMapper mapper = new ObjectMapper(new MessagePackFactory()) + .registerModule(new SimpleModule() + .addDeserializer(Map.class, new MessagePackMapDeserializer())); + + Map map = new HashMap<>(); + map.put(1, "one"); + map.put("2", "two"); + + byte[] bytes = mapper.writeValueAsBytes(map); + Map deserializedInit = mapper.readValue(bytes, new TypeReference>() {}); + + Map expected = new HashMap<>(); + expected.put("1", "one"); + expected.put("2", "two"); + Map actual = new HashMap<>(deserializedInit); + + assertEquals(expected, actual); + } +} From f73e394e48fa8e0556e8b9739ca1a5c6424db168 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 08:49:31 -0700 Subject: [PATCH 379/417] Add CLAUDE.md for AI-assisted development (#894) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This file provides essential guidance for Claude Code when working with the msgpack-java codebase, including common development commands and high-level architecture overview. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude --- CLAUDE.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..e01643b59 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,93 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +MessagePack-Java is a binary serialization library that provides a fast and compact alternative to JSON. The project consists of two main modules: +- **msgpack-core**: Standalone MessagePack implementation with no external dependencies +- **msgpack-jackson**: Jackson integration for object mapping capabilities + +## Essential Development Commands + +### Build and Compile +```bash +./sbt compile # Compile source code +./sbt test:compile # Compile source and test code +./sbt package # Create JAR files +``` + +### Testing +```bash +./sbt test # Run all tests +./sbt ~test # Run tests continuously on file changes +./sbt testOnly *TestClass # Run specific test class +./sbt "testOnly *TestClass -- -z pattern" # Run tests matching pattern + +# Test with universal buffer mode (for compatibility testing) +./sbt test -J-Dmsgpack.universal-buffer=true +``` + +### Code Quality +```bash +./sbt jcheckStyle # Run checkstyle (Facebook Presto style) +./sbt scalafmtAll # Format Scala test code +``` + +### Publishing +```bash +./sbt publishLocal # Install to local .ivy2 repository +./sbt publishM2 # Install to local .m2 Maven repository +``` + +## Architecture Overview + +### Core API Structure +The main entry point is the `MessagePack` factory class which creates: +- **MessagePacker**: Serializes objects to MessagePack binary format +- **MessageUnpacker**: Deserializes MessagePack binary data + +Key locations: +- Core interfaces: `msgpack-core/src/main/java/org/msgpack/core/` +- Jackson integration: `msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/` + +### Buffer Management System +MessagePack uses an efficient buffer abstraction layer: +- **MessageBuffer**: Platform-optimized buffer implementations + - Uses `sun.misc.Unsafe` for performance when available + - Falls back to ByteBuffer on restricted platforms +- **MessageBufferInput/Output**: Manages buffer sequences for streaming + +### Jackson Integration +The msgpack-jackson module provides: +- **MessagePackFactory**: Jackson JsonFactory implementation +- **MessagePackMapper**: Pre-configured ObjectMapper for MessagePack +- Support for field IDs (integer keys) for compact serialization +- Extension type support including timestamps + +### Testing Structure +- **msgpack-core tests**: Written in Scala using AirSpec framework + - Location: `msgpack-core/src/test/scala/` +- **msgpack-jackson tests**: Written in Java using JUnit + - Location: `msgpack-jackson/src/test/java/` + +## Important JVM Options + +For JDK 17+ compatibility, these options are automatically added: +``` +--add-opens=java.base/java.nio=ALL-UNNAMED +--add-opens=java.base/sun.nio.ch=ALL-UNNAMED +``` + +## Code Style Requirements +- Java code follows Facebook Presto style (enforced by checkstyle) +- Scala test code uses Scalafmt with 180 character line limit +- Checkstyle runs automatically during compilation +- No external dependencies allowed in msgpack-core + +## Key Design Principles +1. **Zero Dependencies**: msgpack-core has no external dependencies +2. **Platform Optimization**: Uses platform-specific optimizations when available +3. **Streaming Support**: Both streaming and object-based APIs +4. **Type Safety**: Immutable Value hierarchy for type-safe data handling +5. **Extension Support**: Extensible type system for custom data types \ No newline at end of file From 032823bd60f2f5b859f4ae962f3cb96cbe2ae7a0 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 09:18:02 -0700 Subject: [PATCH 380/417] Refactor CI to use matrix strategy and add JDK 24 support (#895) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace individual JDK test jobs with a single matrix-based job - Add JDK 24 to the test matrix (now tests JDK 8, 11, 17, 21, and 24) - Simplifies CI configuration and makes it easier to add new JDK versions 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude --- .github/workflows/CI.yml | 70 ++++++---------------------------------- 1 file changed, 10 insertions(+), 60 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7ff24e9b5..31f824e4b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -27,75 +27,25 @@ jobs: - uses: actions/checkout@v4 - name: jcheckstyle run: ./sbt jcheckStyle - test_jdk21: - name: Test JDK21 + + test: + name: Test JDK${{ matrix.java }} runs-on: ubuntu-latest + strategy: + matrix: + java: ['8', '11', '17', '21', '24'] steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: '21' + java-version: ${{ matrix.java }} - uses: actions/cache@v4 with: path: ~/.cache - key: ${{ runner.os }}-jdk21-${{ hashFiles('**/*.sbt') }} - restore-keys: ${{ runner.os }}-jdk21- + key: ${{ runner.os }}-jdk${{ matrix.java }}-${{ hashFiles('**/*.sbt') }} + restore-keys: ${{ runner.os }}-jdk${{ matrix.java }}- - name: Test run: ./sbt test - name: Universal Buffer Test - run: ./sbt test -J-Dmsgpack.universal-buffer=true - test_jdk17: - name: Test JDK17 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: '17' - - uses: actions/cache@v4 - with: - path: ~/.cache - key: ${{ runner.os }}-jdk17-${{ hashFiles('**/*.sbt') }} - restore-keys: ${{ runner.os }}-jdk17- - - name: Test - run: ./sbt test - - name: Universal Buffer Test - run: ./sbt test -J-Dmsgpack.universal-buffer=true - test_jdk11: - name: Test JDK11 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: '11' - - uses: actions/cache@v4 - with: - path: ~/.cache - key: ${{ runner.os }}-jdk11-${{ hashFiles('**/*.sbt') }} - restore-keys: ${{ runner.os }}-jdk11- - - name: Test - run: ./sbt test - - name: Universal Buffer Test - run: ./sbt test -J-Dmsgpack.universal-buffer=true - test_jdk8: - name: Test JDK8 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: '8' - - uses: actions/cache@v4 - with: - path: ~/.cache - key: ${{ runner.os }}-jdk8-${{ hashFiles('**/*.sbt') }} - restore-keys: ${{ runner.os }}-jdk8- - - name: Test - run: ./sbt test - - name: Universal Buffer Test - run: ./sbt test -J-Dmsgpack.universal-buffer=true + run: ./sbt test -J-Dmsgpack.universal-buffer=true \ No newline at end of file From 18ab7b7eae2aee3d50205fce1926823930622541 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 19 Jul 2025 18:21:43 +0200 Subject: [PATCH 381/417] Update sbt-scalafmt to 2.5.5 (#893) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 01d5e0ad6..a15bdf512 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,7 +5,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.4") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.5") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.0") scalacOptions ++= Seq("-deprecation", "-feature") From 8f1dddde88d5dcec0734224ddb447a0b893cc026 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 09:33:44 -0700 Subject: [PATCH 382/417] Update sbt-dynver to 5.1.1 (#896) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #892 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index a15bdf512..d68443759 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -6,6 +6,6 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.5") -addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.0") +addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.1") scalacOptions ++= Seq("-deprecation", "-feature") From 736765333c4043bea7a5e1157194b1f22e407a54 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 09:39:43 -0700 Subject: [PATCH 383/417] Migrate from JUnit 4 to JUnit 5 to resolve deprecation warnings (#897) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update build.sbt to use JUnit 5 dependencies (jupiter + vintage) - Replace JUnit 4 imports with JUnit 5 equivalents - Convert @Test(expected=Exception.class) to assertThrows() - Update @Before to @BeforeEach annotation - Replace deprecated org.junit.Assert.assertThat with Hamcrest assertThat - Maintain backward compatibility with JUnit Vintage engine Fixes all JUnit deprecation warnings in msgpack-jackson tests. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude --- build.sbt | 9 +++++--- .../MessagePackDataformatForFieldIdTest.java | 4 ++-- .../MessagePackDataformatForPojoTest.java | 8 +++---- .../dataformat/MessagePackFactoryTest.java | 6 ++--- .../dataformat/MessagePackGeneratorTest.java | 23 +++++++++++-------- .../dataformat/MessagePackMapperTest.java | 6 ++--- .../dataformat/MessagePackParserTest.java | 17 ++++++++------ .../TimestampExtensionModuleTest.java | 8 +++---- ...gePackDataformatHugeDataBenchmarkTest.java | 2 +- ...essagePackDataformatPojoBenchmarkTest.java | 2 +- 10 files changed, 47 insertions(+), 38 deletions(-) diff --git a/build.sbt b/build.sbt index 235f6286f..d4645a111 100644 --- a/build.sbt +++ b/build.sbt @@ -46,7 +46,8 @@ val buildSettings = Seq[Setting[_]]( Test / compile := ((Test / compile) dependsOn (Test / jcheckStyle)).value ) -val junitInterface = "com.github.sbt" % "junit-interface" % "0.13.3" % "test" +val junitJupiter = "org.junit.jupiter" % "junit-jupiter" % "5.11.4" % "test" +val junitVintage = "org.junit.vintage" % "junit-vintage-engine" % "5.11.4" % "test" // Project settings lazy val root = Project(id = "msgpack-java", base = file(".")) @@ -83,7 +84,8 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) Test / fork := true, libraryDependencies ++= Seq( // msgpack-core should have no external dependencies - junitInterface, + junitJupiter, + junitVintage, "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods @@ -110,7 +112,8 @@ lazy val msgpackJackson = ), libraryDependencies ++= Seq( "com.fasterxml.jackson.core" % "jackson-databind" % "2.18.2", - junitInterface, + junitJupiter, + junitVintage, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForFieldIdTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForFieldIdTest.java index 0e102ba8c..bbac6fb96 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForFieldIdTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForFieldIdTest.java @@ -33,9 +33,9 @@ import java.util.Map; import java.util.Set; import java.util.LinkedHashMap; -import org.junit.Test; +import org.junit.jupiter.api.Test; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class MessagePackDataformatForFieldIdTest { diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java index 52269a7d1..e899e4f4a 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java @@ -16,7 +16,7 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.charset.Charset; @@ -24,9 +24,9 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.hamcrest.MatcherAssert.assertThat; public class MessagePackDataformatForPojoTest extends MessagePackDataformatTestBase diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java index f8d7ac3c8..9e3765417 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java @@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.msgpack.core.MessagePack; import java.io.IOException; @@ -35,8 +35,8 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.hamcrest.MatcherAssert.assertThat; public class MessagePackFactoryTest extends MessagePackDataformatTestBase diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index 7ba48a613..a13951b23 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -24,7 +24,7 @@ import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.module.SimpleModule; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.msgpack.core.ExtensionTypeHeader; import org.msgpack.core.MessagePack; import org.msgpack.core.MessageUnpacker; @@ -53,13 +53,14 @@ import java.util.concurrent.TimeUnit; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.hamcrest.MatcherAssert.assertThat; public class MessagePackGeneratorTest extends MessagePackDataformatTestBase @@ -349,7 +350,7 @@ public void testBigDecimal() } } - @Test(expected = IOException.class) + @Test public void testEnableFeatureAutoCloseTarget() throws IOException { @@ -358,7 +359,9 @@ public void testEnableFeatureAutoCloseTarget() ObjectMapper objectMapper = new ObjectMapper(messagePackFactory); List integers = Arrays.asList(1); objectMapper.writeValue(out, integers); - objectMapper.writeValue(out, integers); + assertThrows(IOException.class, () -> { + objectMapper.writeValue(out, integers); + }); } @Test diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java index 68721fce8..d14f97f2e 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java @@ -16,14 +16,14 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.core.JsonProcessingException; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; public class MessagePackMapperTest { diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index a416c92bd..c0bab053e 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -27,7 +27,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; import org.msgpack.value.ExtensionValue; @@ -52,10 +52,11 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.assertThrows; public class MessagePackParserTest extends MessagePackDataformatTestBase @@ -450,7 +451,7 @@ public void setup(File f) return tempFile; } - @Test(expected = IOException.class) + @Test public void testEnableFeatureAutoCloseSource() throws Exception { @@ -459,7 +460,9 @@ public void testEnableFeatureAutoCloseSource() FileInputStream in = new FileInputStream(tempFile); ObjectMapper objectMapper = new ObjectMapper(factory); objectMapper.readValue(in, new TypeReference>() {}); - objectMapper.readValue(in, new TypeReference>() {}); + assertThrows(IOException.class, () -> { + objectMapper.readValue(in, new TypeReference>() {}); + }); } @Test diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/TimestampExtensionModuleTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/TimestampExtensionModuleTest.java index 05851dbc2..074d7bf54 100755 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/TimestampExtensionModuleTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/TimestampExtensionModuleTest.java @@ -16,8 +16,8 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; @@ -26,7 +26,7 @@ import java.io.IOException; import java.time.Instant; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class TimestampExtensionModuleTest { @@ -46,7 +46,7 @@ private static class TripleInstants public Instant c; } - @Before + @BeforeEach public void setUp() throws Exception { diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java index fea34fd8b..8ae73d0b5 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.msgpack.jackson.dataformat.MessagePackFactory; import java.io.File; diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java index 2713eaea3..8042153d3 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java @@ -17,7 +17,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.msgpack.jackson.dataformat.MessagePackFactory; import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.NormalPojo; import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.Suit; From faabef5592c6e25d750b28bc001131261b9fb5b9 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 19 Jul 2025 18:40:00 +0200 Subject: [PATCH 384/417] Update airframe-json, airspec to 2025.1.14 (#889) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index d4645a111..301b88b42 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "2025.1.1" +val AIRFRAME_VERSION = "2025.1.14" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 7a31503f71a269fff6bb238858a169934316ecd6 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 19 Jul 2025 18:40:10 +0200 Subject: [PATCH 385/417] Update sbt, scripted-plugin to 1.10.11 (#881) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 8fc29878c..fa5667a70 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.7 +sbt.version=1.10.11 From 5c57bcffc27c0f10a294d6b9e4fa8039d595820d Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 09:41:32 -0700 Subject: [PATCH 386/417] Upgrade sbt to 1.11.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update from sbt 1.10.11 to the latest stable version 1.11.3. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index fa5667a70..138bc7a55 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.10.11 +sbt.version=1.11.3 From 83a18920dac1baa101b1063801560fb37cec2071 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 10:11:44 -0700 Subject: [PATCH 387/417] Migrate from sbt-sonatype to built-in sonaRelease (#898) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update sbt-dynver to 5.1.1 Fixes #892 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Migrate from sbt-sonatype to built-in sonaRelease - Remove sbt-sonatype plugin dependency from project/plugins.sbt - Move publishing metadata from sonatype.sbt to build.sbt - Update publishTo configuration to use direct Sonatype URLs - Use built-in sbt functionality instead of plugin for Sonatype publishing 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Update to sbt 1.11.3 and fix publishTo configuration - Update sbt version to 1.11.3 for built-in localStaging support - Fix publishTo setting to use correct Sonatype Central URLs - Use localStaging.value for releases and central-snapshots for snapshots 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Format code with scalafmt and fix scalafmt configuration - Fix .scalafmt.conf with version 3.9.8 and scala213 dialect - Format Scala test code according to project style - Maintain 180 character line limit and alignment style 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Update GitHub Actions workflows for Sonatype Central migration - Fix secret names to use SONATYPE_USERNAME and SONATYPE_PASSWORD - Remove deprecated sonatypeBundleRelease command from release workflow - Consolidate release steps to use publishSigned with correct environment - Update both release.yml and snapshot.yml workflows 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Use sonaRelease command in release workflow - Replace publishSigned with sonaRelease for proper release flow - sonaRelease handles both publishing and release to Central Portal 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Add publishSigned step back to release workflow - First step: publishSigned to stage signed artifacts - Second step: sonaRelease to release staged artifacts to Central - Both steps needed for proper release flow 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Revert to original workflow structure with updated secrets - Restore "Build bundle" and "Release to Sonatype" step names - Keep publishSigned in Build bundle step - Use sonaRelease in Release step with correct secret names - Maintain original workflow structure with modern functionality 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --------- Co-authored-by: Claude --- .github/workflows/release.yml | 6 ++--- .github/workflows/snapshot.yml | 4 ++-- .scalafmt.conf | 2 ++ build.sbt | 24 ++++++++++++++++++- .../msgpack/core/InvalidDataReadTest.scala | 3 +-- .../org/msgpack/core/MessageFormatTest.scala | 3 +-- .../org/msgpack/core/MessagePackSpec.scala | 2 +- .../org/msgpack/core/MessagePackTest.scala | 23 +++++++++--------- .../org/msgpack/core/MessagePackerTest.scala | 15 ++++++------ .../msgpack/core/MessageUnpackerTest.scala | 4 ++-- .../core/buffer/MessageBufferInputTest.scala | 2 +- .../core/buffer/MessageBufferTest.scala | 3 +-- .../core/example/MessagePackExampleTest.scala | 3 +-- .../org/msgpack/value/ValueFactoryTest.scala | 3 +-- .../org/msgpack/value/ValueTypeTest.scala | 3 +-- .../org/msgpack/value/VariableTest.scala | 10 ++++---- project/plugins.sbt | 1 - sonatype.sbt | 18 -------------- 18 files changed, 62 insertions(+), 67 deletions(-) delete mode 100644 sonatype.sbt diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b214d8ecd..c3dca7c26 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,6 +33,6 @@ jobs: ./sbt publishSigned - name: Release to Sonatype env: - SONATYPE_USERNAME: '${{ secrets.SONATYPE_USER }}' - SONATYPE_PASSWORD: '${{ secrets.SONATYPE_PASS }}' - run: ./sbt sonatypeBundleRelease + SONATYPE_USERNAME: '${{ secrets.SONATYPE_USERNAME }}' + SONATYPE_PASSWORD: '${{ secrets.SONATYPE_PASSWORD }}' + run: ./sbt sonaRelease diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index cbce4c148..4cc858660 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -27,6 +27,6 @@ jobs: distribution: adopt - name: Publish snapshots env: - SONATYPE_USERNAME: '${{ secrets.SONATYPE_USER }}' - SONATYPE_PASSWORD: '${{ secrets.SONATYPE_PASS }}' + SONATYPE_USERNAME: '${{ secrets.SONATYPE_USERNAME }}' + SONATYPE_PASSWORD: '${{ secrets.SONATYPE_PASSWORD }}' run: ./sbt publish diff --git a/.scalafmt.conf b/.scalafmt.conf index bda502a5c..eccdf1c20 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,3 +1,5 @@ +version = 3.9.8 +runner.dialect = scala213 maxColumn = 180 style = defaultWithAlign optIn.breaksInsideChains = true diff --git a/build.sbt b/build.sbt index 301b88b42..70c8161eb 100644 --- a/build.sbt +++ b/build.sbt @@ -12,6 +12,24 @@ ThisBuild / dynverSonatypeSnapshots := true // Use coursier friendly version separator ThisBuild / dynverSeparator := "-" +// Publishing metadata +ThisBuild / homepage := Some(url("https://msgpack.org/")) +ThisBuild / licenses := Seq("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")) +ThisBuild / scmInfo := Some( + ScmInfo( + url("https://github.com/msgpack/msgpack-java"), + "scm:git@github.com:msgpack/msgpack-java.git" + ) +) +ThisBuild / developers := List( + Developer(id = "frsyuki", name = "Sadayuki Furuhashi", email = "frsyuki@users.sourceforge.jp", url = url("https://github.com/frsyuki")), + Developer(id = "muga", name = "Muga Nishizawa", email = "muga.nishizawa@gmail.com", url = url("https://github.com/muga")), + Developer(id = "oza", name = "Tsuyoshi Ozawa", email = "ozawa.tsuyoshi@gmail.com", url = url("https://github.com/oza")), + Developer(id = "komamitsu", name = "Mitsunori Komatsu", email = "komamitsu@gmail.com", url = url("https://github.com/komamitsu")), + Developer(id = "xerial", name = "Taro L. Saito", email = "leo@xerial.org", url = url("https://github.com/xerial")) +) + + val buildSettings = Seq[Setting[_]]( organization := "org.msgpack", organizationName := "MessagePack", @@ -38,7 +56,11 @@ val buildSettings = Seq[Setting[_]]( } }, // Add sonatype repository settings - publishTo := sonatypePublishToBundle.value, + publishTo := { + val centralSnapshots = "https://central.sonatype.com/repository/maven-snapshots/" + if (isSnapshot.value) Some("central-snapshots" at centralSnapshots) + else localStaging.value + }, // Style check config: (sbt-jchekcstyle) jcheckStyleConfig := "facebook", // Run jcheckstyle both for main and test codes diff --git a/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala index 6f0138385..1c43bb337 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala @@ -3,8 +3,7 @@ package org.msgpack.core import org.msgpack.core.MessagePackSpec.createMessagePackData import wvlet.airspec.AirSpec -/** - */ +/** */ class InvalidDataReadTest extends AirSpec { test("Reading long EXT32") { diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala index 06a58e112..782b2e402 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala @@ -22,8 +22,7 @@ import wvlet.airspec.spi.AirSpecException import scala.util.Random -/** - * Created on 2014/05/07. +/** Created on 2014/05/07. */ class MessageFormatTest extends AirSpec with Benchmark { test("MessageFormat") { diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala index dee315cd9..c4fb23b42 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala @@ -21,7 +21,7 @@ import wvlet.log.io.{TimeReport, Timer} import java.io.ByteArrayOutputStream object MessagePackSpec { - def toHex(arr: Array[Byte]) = arr.map(x => f"$x%02x").mkString(" ") + def toHex(arr: Array[Byte]) = arr.map(x => f"$x%02x").mkString(" ") def createMessagePackData(f: MessagePacker => Unit): Array[Byte] = { val b = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(b) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index c2993f96a..0cec1b4b3 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -30,8 +30,7 @@ import java.nio.charset.{CodingErrorAction, UnmappableCharacterException} import java.time.Instant import scala.util.Random -/** - * Created on 2014/05/07. +/** Created on 2014/05/07. */ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { @@ -396,7 +395,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { test("report errors when packing/unpacking malformed strings") { pending("We need to produce malformed utf-8 strings in Java 8") // Create 100 malformed UTF8 Strings - val r = new Random(0) + val r = new Random(0) val malformedStrings = Iterator .continually { val b = new Array[Byte](10) @@ -433,7 +432,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { test("report errors when packing/unpacking strings that contain unmappable characters") { val unmappable = Array[Byte](0xfc.toByte, 0x0a.toByte) - //val unmappableChar = Array[Char](new Character(0xfc0a).toChar) + // val unmappableChar = Array[Char](new Character(0xfc0a).toChar) // Report error on unmappable character val unpackerConfig = new UnpackerConfig() @@ -534,10 +533,9 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { m, { packer => packer.packMapHeader(v.length) - m.map { - case (k: Int, v: String) => - packer.packInt(k) - packer.packString(v) + m.map { case (k: Int, v: String) => + packer.packInt(k) + packer.packString(v) } }, { unpacker => @@ -666,13 +664,14 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { val posLong = Gen.chooseNum[Long](-31557014167219200L, 31556889864403199L) forAll(posLong) { (millis: Long) => val v = Instant.ofEpochMilli(millis) - check(v, { _.packTimestamp(millis) }, + check( + v, + { _.packTimestamp(millis) }, { u => val extHeader = u.unpackExtensionTypeHeader() - if(extHeader.isTimestampType) { + if (extHeader.isTimestampType) { u.unpackTimestamp(extHeader) - } - else { + } else { fail("Cannot reach here") } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index dea3e4ead..7d762149c 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -24,8 +24,7 @@ import wvlet.log.io.IOUtil.withResource import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream} import scala.util.Random -/** - */ +/** */ class MessagePackerTest extends AirSpec with Benchmark { private def verifyIntSeq(answer: Array[Int], packed: Array[Byte]): Unit = { @@ -141,8 +140,8 @@ class MessagePackerTest extends AirSpec with Benchmark { 32 -> 31, 34 -> 32 ) - testCases.foreach { - case (bufferSize, stringSize) => test(bufferSize, stringSize) + testCases.foreach { case (bufferSize, stringSize) => + test(bufferSize, stringSize) } } @@ -234,7 +233,7 @@ class MessagePackerTest extends AirSpec with Benchmark { } test("compute totalWrittenBytes") { - val out = new ByteArrayOutputStream + val out = new ByteArrayOutputStream val packerTotalWrittenBytes = withResource(MessagePack.newDefaultPacker(out)) { packer => packer @@ -255,7 +254,7 @@ class MessagePackerTest extends AirSpec with Benchmark { test("support read-only buffer") { val payload = Array[Byte](1) val out = new ByteArrayOutputStream() - val packer = MessagePack + val packer = MessagePack .newDefaultPacker(out) .packBinaryHeader(1) .writePayload(payload) @@ -299,14 +298,14 @@ class MessagePackerTest extends AirSpec with Benchmark { test("write raw binary") { val packer = new MessagePack.PackerConfig().newBufferPacker() - val msg = + val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) packer.writePayload(msg) } test("append raw binary") { val packer = new MessagePack.PackerConfig().newBufferPacker() - val msg = + val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) packer.addPayload(msg) } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 3ea5e911d..620e7dbe2 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -30,7 +30,7 @@ import scala.util.Random object MessageUnpackerTest { class SplitMessageBufferInput(array: Array[Array[Byte]]) extends MessageBufferInput { - var cursor = 0 + var cursor = 0 override def next(): MessageBuffer = { if (cursor < array.length) { val a = array(cursor) @@ -49,7 +49,7 @@ import org.msgpack.core.MessageUnpackerTest._ class MessageUnpackerTest extends AirSpec with Benchmark { - private val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] + private val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] private def testData: Array[Byte] = { val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index dd1cdb974..a43704fb0 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -33,7 +33,7 @@ class MessageBufferInputTest extends AirSpec { Seq(0, 10, 500, 1000, 2000, 4000, 8000, 10000, 30000, 50000, 100000) private def testData(size: Int): Array[Byte] = { - //debug(s"test data size: ${size}") + // debug(s"test data size: ${size}") val b = new Array[Byte](size) Random.nextBytes(b) b diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala index 4de059951..03e93b891 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala @@ -21,8 +21,7 @@ import wvlet.airspec.AirSpec import java.nio.ByteBuffer import scala.util.Random -/** - * Created on 2014/05/01. +/** Created on 2014/05/01. */ class MessageBufferTest extends AirSpec with Benchmark { diff --git a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala index 99876275d..d0b0e08e8 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala @@ -17,8 +17,7 @@ package org.msgpack.core.example import wvlet.airspec.AirSpec -/** - */ +/** */ class MessagePackExampleTest extends AirSpec { test("example") { diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala index 3fe2a07f8..3568ba5b9 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala @@ -19,8 +19,7 @@ import org.scalacheck.Gen import wvlet.airspec.AirSpec import wvlet.airspec.spi.PropertyCheck -/** - */ +/** */ class ValueFactoryTest extends AirSpec with PropertyCheck { private def isValid( diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala index e8b04d5f6..fc81bdebd 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala @@ -19,8 +19,7 @@ import org.msgpack.core.MessagePack.Code._ import org.msgpack.core.{MessageFormat, MessageFormatException} import wvlet.airspec.AirSpec -/** - * Created on 2014/05/06. +/** Created on 2014/05/06. */ class ValueTypeTest extends AirSpec { diff --git a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala index 5d97d8712..f9a1c2a0b 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala @@ -23,8 +23,7 @@ import java.time.Instant import java.util import scala.jdk.CollectionConverters._ -/** - */ +/** */ class VariableTest extends AirSpec with PropertyCheck { private def check(pack: MessagePacker => Unit, checker: Variable => Unit): Unit = { val packer = MessagePack.newDefaultBufferPacker() @@ -38,8 +37,7 @@ class VariableTest extends AirSpec with PropertyCheck { unpacker.close() } - /** - * Test Value -> MsgPack -> Value + /** Test Value -> MsgPack -> Value */ private def roundTrip(v: Value): Unit = { val packer = MessagePack.newDefaultBufferPacker() @@ -210,8 +208,8 @@ class VariableTest extends AirSpec with PropertyCheck { _.packDouble(x), checker = { v => val iv = validateValue(v.asFloatValue(), asFloat = true) - //iv.toDouble shouldBe v - //iv.toFloat shouldBe x.toFloat + // iv.toDouble shouldBe v + // iv.toFloat shouldBe x.toFloat } ) } diff --git a/project/plugins.sbt b/project/plugins.sbt index d68443759..5bc49937b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,3 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.2") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter diff --git a/sonatype.sbt b/sonatype.sbt deleted file mode 100644 index 3fcb592f9..000000000 --- a/sonatype.sbt +++ /dev/null @@ -1,18 +0,0 @@ -import xerial.sbt.Sonatype._ - -ThisBuild / sonatypeProfileName := "org.msgpack" -ThisBuild / homepage := Some(url("https://msgpack.org/")) -ThisBuild / licenses := Seq("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")) -ThisBuild / scmInfo := Some( - ScmInfo( - url("https://github.com/msgpack/msgpack-java"), - "scm:git@github.com:msgpack/msgpack-java.git" - ) -) -ThisBuild / developers := List( - Developer(id = "frsyuki", name = "Sadayuki Furuhashi", email = "frsyuki@users.sourceforge.jp", url = url("https://github.com/frsyuki")), - Developer(id = "muga", name = "Muga Nishizawa", email = "muga.nishizawa@gmail.com", url = url("https://github.com/muga")), - Developer(id = "oza", name = "Tsuyoshi Ozawa", email = "ozawa.tsuyoshi@gmail.com", url = url("https://github.com/oza")), - Developer(id = "komamitsu", name = "Mitsunori Komatsu", email = "komamitsu@gmail.com", url = url("https://github.com/komamitsu")), - Developer(id = "xerial", name = "Taro L. Saito", email = "leo@xerial.org", url = url("https://github.com/xerial")) -) From 4bcc43e5e539fdc05cc790852f82fb53618892dd Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 10:24:00 -0700 Subject: [PATCH 388/417] Upgrade Scala to 3.7.1 and update code format style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Upgrade Scala version from 2.13.12 to 3.7.1 in build.sbt - Update scalafmt.conf to use Scala 3 dialect and modern formatting rules - Fix Scala 3 compatibility issues in test files: - Update lambda syntax to use parentheses around parameters - Remove deprecated underscore suffix from function references - Apply Scala 3 formatting with scalafmt 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .scalafmt.conf | 18 +- build.sbt | 2 +- .../msgpack/core/InvalidDataReadTest.scala | 18 +- .../core/MessageBufferPackerTest.scala | 5 +- .../org/msgpack/core/MessageFormatTest.scala | 45 +- .../org/msgpack/core/MessagePackSpec.scala | 26 +- .../org/msgpack/core/MessagePackTest.scala | 312 +++++---- .../org/msgpack/core/MessagePackerTest.scala | 151 ++--- .../msgpack/core/MessageUnpackerTest.scala | 628 +++++++++--------- .../org/msgpack/core/StringLimitTest.scala | 5 +- .../msgpack/core/buffer/ByteStringTest.scala | 29 +- .../core/buffer/DirectBufferAccessTest.scala | 3 +- .../core/buffer/MessageBufferInputTest.scala | 128 ++-- .../core/buffer/MessageBufferOutputTest.scala | 19 +- .../core/buffer/MessageBufferTest.scala | 95 ++- .../core/example/MessagePackExampleTest.scala | 6 +- .../value/RawStringValueImplTest.scala | 3 +- .../org/msgpack/value/ValueFactoryTest.scala | 60 +- .../scala/org/msgpack/value/ValueTest.scala | 25 +- .../org/msgpack/value/ValueTypeTest.scala | 49 +- .../org/msgpack/value/VariableTest.scala | 226 +++---- 21 files changed, 904 insertions(+), 949 deletions(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index eccdf1c20..fcadd98d4 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,5 +1,17 @@ -version = 3.9.8 -runner.dialect = scala213 -maxColumn = 180 +version = 3.9.4 +project.layout = StandardConvention +runner.dialect = scala3 +maxColumn = 100 style = defaultWithAlign +docstrings.blankFirstLine = yes +rewrite.scala3.convertToNewSyntax = true +rewrite.scala3.removeOptionalBraces = yes +rewrite.scala3.insertEndMarkerMinLines = 30 +# Add a new line before case class +newlines.topLevelStatementBlankLines = [ + { + blanks { after = 1 } + } +] +newlines.source = unfold optIn.breaksInsideChains = true diff --git a/build.sbt b/build.sbt index 70c8161eb..3d6ba3202 100644 --- a/build.sbt +++ b/build.sbt @@ -35,7 +35,7 @@ val buildSettings = Seq[Setting[_]]( organizationName := "MessagePack", organizationHomepage := Some(url("http://msgpack.org/")), description := "MessagePack for Java", - scalaVersion := "2.13.12", + scalaVersion := "3.7.1", Test / logBuffered := false, // msgpack-java should be a pure-java library, so remove Scala specific configurations autoScalaLibrary := false, diff --git a/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala index 1c43bb337..76f04c97d 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/InvalidDataReadTest.scala @@ -3,21 +3,21 @@ package org.msgpack.core import org.msgpack.core.MessagePackSpec.createMessagePackData import wvlet.airspec.AirSpec -/** */ -class InvalidDataReadTest extends AirSpec { +/** + */ +class InvalidDataReadTest extends AirSpec: test("Reading long EXT32") { // Prepare an EXT32 data with 2GB (Int.MaxValue size) payload for testing the behavior of MessageUnpacker.skipValue() // Actually preparing 2GB of data, however, is too much for CI, so we create only the header part. - val msgpack = createMessagePackData(p => p.packExtensionTypeHeader(MessagePack.Code.EXT32, Int.MaxValue)) - val u = MessagePack.newDefaultUnpacker(msgpack) - try { + val msgpack = createMessagePackData(p => + p.packExtensionTypeHeader(MessagePack.Code.EXT32, Int.MaxValue) + ) + val u = MessagePack.newDefaultUnpacker(msgpack) + try // This error will be thrown after reading the header as the input has no EXT32 body intercept[MessageInsufficientBufferException] { u.skipValue() } - } finally { - u.close() - } + finally u.close() } -} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala index 58b29f435..f4b74986c 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageBufferPackerTest.scala @@ -17,10 +17,10 @@ package org.msgpack.core import java.io.ByteArrayOutputStream import java.util.Arrays -import org.msgpack.value.ValueFactory._ +import org.msgpack.value.ValueFactory.* import wvlet.airspec.AirSpec -class MessageBufferPackerTest extends AirSpec { +class MessageBufferPackerTest extends AirSpec: test("MessageBufferPacker") { test("be equivalent to ByteArrayOutputStream") { val packer1 = MessagePack.newDefaultBufferPacker @@ -48,4 +48,3 @@ class MessageBufferPackerTest extends AirSpec { } } -} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala index 782b2e402..a626978d5 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala @@ -22,48 +22,41 @@ import wvlet.airspec.spi.AirSpecException import scala.util.Random -/** Created on 2014/05/07. +/** + * Created on 2014/05/07. */ -class MessageFormatTest extends AirSpec with Benchmark { +class MessageFormatTest extends AirSpec with Benchmark: test("MessageFormat") { test("cover all byte codes") { - def checkV(b: Byte, tpe: ValueType): Unit = { - try MessageFormat.valueOf(b).getValueType shouldBe tpe - catch { + def checkV(b: Byte, tpe: ValueType): Unit = + try + MessageFormat.valueOf(b).getValueType shouldBe tpe + catch case e: AirSpecException => error(f"Failure when looking at byte ${b}%02x") throw e - } - } - def checkF(b: Byte, f: MessageFormat): Unit = { - MessageFormat.valueOf(b) shouldBe f - } + def checkF(b: Byte, f: MessageFormat): Unit = MessageFormat.valueOf(b) shouldBe f - def check(b: Byte, tpe: ValueType, f: MessageFormat): Unit = { + def check(b: Byte, tpe: ValueType, f: MessageFormat): Unit = checkV(b, tpe) checkF(b, f) - } - for (i <- 0 until 0x7f) { + for i <- 0 until 0x7f do check(i.toByte, ValueType.INTEGER, MessageFormat.POSFIXINT) - } - for (i <- 0x80 until 0x8f) { + for i <- 0x80 until 0x8f do check(i.toByte, ValueType.MAP, MessageFormat.FIXMAP) - } - for (i <- 0x90 until 0x9f) { + for i <- 0x90 until 0x9f do check(i.toByte, ValueType.ARRAY, MessageFormat.FIXARRAY) - } check(Code.NIL, ValueType.NIL, MessageFormat.NIL) MessageFormat.valueOf(Code.NEVER_USED) shouldBe MessageFormat.NEVER_USED - for (i <- Seq(Code.TRUE, Code.FALSE)) { + for i <- Seq(Code.TRUE, Code.FALSE) do check(i, ValueType.BOOLEAN, MessageFormat.BOOLEAN) - } check(Code.BIN8, ValueType.BINARY, MessageFormat.BIN8) check(Code.BIN16, ValueType.BINARY, MessageFormat.BIN16) @@ -97,9 +90,8 @@ class MessageFormatTest extends AirSpec with Benchmark { check(Code.ARRAY16, ValueType.ARRAY, MessageFormat.ARRAY16) check(Code.ARRAY32, ValueType.ARRAY, MessageFormat.ARRAY32) - for (i <- 0xe0 to 0xff) { + for i <- 0xe0 to 0xff do check(i.toByte, ValueType.INTEGER, MessageFormat.NEGFIXINT) - } } test("improve the valueOf performance") { @@ -112,20 +104,19 @@ class MessageFormatTest extends AirSpec with Benchmark { time("lookup", repeat = 10) { block("switch") { var i = 0 - while (i < N) { + while i < N do MessageFormat.toMessageFormat(idx(i)) i += 1 - } } block("table") { var i = 0 - while (i < N) { + while i < N do MessageFormat.valueOf(idx(i)) i += 1 - } } } } } -} + +end MessageFormatTest diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala index c4fb23b42..135c49216 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala @@ -20,31 +20,29 @@ import wvlet.log.io.{TimeReport, Timer} import java.io.ByteArrayOutputStream -object MessagePackSpec { - def toHex(arr: Array[Byte]) = arr.map(x => f"$x%02x").mkString(" ") - def createMessagePackData(f: MessagePacker => Unit): Array[Byte] = { +object MessagePackSpec: + def toHex(arr: Array[Byte]) = arr.map(x => f"$x%02x").mkString(" ") + def createMessagePackData(f: MessagePacker => Unit): Array[Byte] = val b = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(b) f(packer) packer.close() b.toByteArray - } -} -trait Benchmark extends Timer { +trait Benchmark extends Timer: private val numWarmUpRuns = 10 - override protected def time[A](blockName: String, logLevel: LogLevel = LogLevel.INFO, repeat: Int = 1, blockRepeat: Int = 1)(f: => A): TimeReport = { - super.time(blockName, logLevel = LogLevel.INFO, repeat)(f) - } + override protected def time[A]( + blockName: String, + logLevel: LogLevel = LogLevel.INFO, + repeat: Int = 1, + blockRepeat: Int = 1 + )(f: => A): TimeReport = super.time(blockName, logLevel = LogLevel.INFO, repeat)(f) - override protected def block[A](name: String)(f: => A): TimeReport = { + override protected def block[A](name: String)(f: => A): TimeReport = var i = 0 - while (i < numWarmUpRuns) { + while i < numWarmUpRuns do f i += 1 - } super.block(name)(f) - } -} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 0cec1b4b3..0a4328d8d 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -30,27 +30,26 @@ import java.nio.charset.{CodingErrorAction, UnmappableCharacterException} import java.time.Instant import scala.util.Random -/** Created on 2014/05/07. +/** + * Created on 2014/05/07. */ -class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { +class MessagePackTest extends AirSpec with PropertyCheck with Benchmark: - private def isValidUTF8(s: String) = { - MessagePack.UTF8.newEncoder().canEncode(s) - } + private def isValidUTF8(s: String) = MessagePack.UTF8.newEncoder().canEncode(s) - private def containsUnmappableCharacter(s: String): Boolean = { - try { - MessagePack.UTF8 + private def containsUnmappableCharacter(s: String): Boolean = + try + MessagePack + .UTF8 .newEncoder() .onUnmappableCharacter(CodingErrorAction.REPORT) .encode(CharBuffer.wrap(s)) false - } catch { + catch case e: UnmappableCharacterException => true - case _: Exception => false - } - } + case _: Exception => + false test("clone packer config") { val config = new PackerConfig() @@ -77,13 +76,11 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { test("detect fixint values") { - for (i <- 0 until 0x7f) { + for i <- 0 until 0x7f do Code.isPosFixInt(i.toByte) shouldBe true - } - for (i <- 0x80 until 0xff) { + for i <- 0x80 until 0xff do Code.isPosFixInt(i.toByte) shouldBe false - } } test("detect fixarray values") { @@ -92,12 +89,11 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { packer.close val bytes = packer.toByteArray MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() shouldBe 0 - try { + try MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() fail("Shouldn't reach here") - } catch { + catch case e: MessageTypeException => // OK - } } test("detect fixmap values") { @@ -106,12 +102,11 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { packer.close val bytes = packer.toByteArray MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() shouldBe 0 - try { + try MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() fail("Shouldn't reach here") - } catch { + catch case e: MessageTypeException => // OK - } } test("detect fixint quickly") { @@ -124,34 +119,28 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { block("mask") { var i = 0 var count = 0 - while (i < N) { - if ((idx(i) & Code.POSFIXINT_MASK) == 0) { + while i < N do + if (idx(i) & Code.POSFIXINT_MASK) == 0 then count += 1 - } i += 1 - } } block("mask in func") { var i = 0 var count = 0 - while (i < N) { - if (Code.isPosFixInt(idx(i))) { + while i < N do + if Code.isPosFixInt(idx(i)) then count += 1 - } i += 1 - } } block("shift cmp") { var i = 0 var count = 0 - while (i < N) { - if ((idx(i) >>> 7) == 0) { + while i < N do + if (idx(i) >>> 7) == 0 then count += 1 - } i += 1 - } } @@ -161,13 +150,11 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { test("detect neg fix int values") { - for (i <- 0 until 0xe0) { + for i <- 0 until 0xe0 do Code.isNegFixInt(i.toByte) shouldBe false - } - for (i <- 0xe0 until 0xff) { + for i <- 0xe0 until 0xff do Code.isNegFixInt(i.toByte) shouldBe true - } } @@ -177,9 +164,9 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { unpack: MessageUnpacker => A, packerConfig: PackerConfig = new PackerConfig(), unpackerConfig: UnpackerConfig = new UnpackerConfig() - ): Boolean = { + ): Boolean = var b: Array[Byte] = null - try { + try val bs = new ByteArrayOutputStream() val packer = packerConfig.newPacker(bs) pack(packer) @@ -191,15 +178,12 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { val ret = unpack(unpacker) ret shouldBe v true - } catch { + catch case e: Exception => warn(e.getMessage) - if (b != null) { + if b != null then warn(s"packed data (size:${b.length}): ${toHex(b)}") - } throw e - } - } private def checkException[A]( v: A, @@ -207,7 +191,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { unpack: MessageUnpacker => A, packerConfig: PackerConfig = new PackerConfig(), unpaackerConfig: UnpackerConfig = new UnpackerConfig() - ): Unit = { + ): Unit = var b: Array[Byte] = null val bs = new ByteArrayOutputStream() val packer = packerConfig.newPacker(bs) @@ -220,15 +204,16 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { val ret = unpack(unpacker) fail("cannot not reach here") - } - private def checkOverflow[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A): Unit = { - try { + private def checkOverflow[A]( + v: A, + pack: MessagePacker => Unit, + unpack: MessageUnpacker => A + ): Unit = + try checkException[A](v, pack, unpack) - } catch { + catch case e: MessageIntegerOverflowException => // OK - } - } test("pack/unpack primitive values") { forAll { (v: Boolean) => @@ -256,7 +241,8 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { null, _.packNil, { unpacker => - unpacker.unpackNil(); null + unpacker.unpackNil(); + null } ) } @@ -278,29 +264,35 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { packer.packString("val") }, { unpacker => - unpacker.tryUnpackNil(); unpacker.unpackString() + unpacker.tryUnpackNil(); + unpacker.unpackString() } ) check( "val", { packer => - packer.packNil(); packer.packString("val") + packer.packNil(); + packer.packString("val") }, { unpacker => - unpacker.tryUnpackNil(); unpacker.unpackString() + unpacker.tryUnpackNil(); + unpacker.unpackString() } ) - try { - checkException(null, { _ => }, _.tryUnpackNil) - } catch { + try + checkException( + null, + { _ => + }, + _.tryUnpackNil + ) + catch case e: MessageInsufficientBufferException => // OK - } } test("pack/unpack integer values") { val sampleData = Seq[Long]( - Int.MinValue.toLong - - 10, + Int.MinValue.toLong - 10, -65535, -8191, -1024, @@ -326,31 +318,26 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { 65536, Int.MaxValue.toLong + 10 ) - for (v <- sampleData) { + for v <- sampleData do check(v, _.packLong(v), _.unpackLong) - if (v.isValidInt) { + if v.isValidInt then val vi = v.toInt check(vi, _.packInt(vi), _.unpackInt) - } else { + else checkOverflow(v, _.packLong(v), _.unpackInt) - } - if (v.isValidShort) { + if v.isValidShort then val vi = v.toShort check(vi, _.packShort(vi), _.unpackShort) - } else { + else checkOverflow(v, _.packLong(v), _.unpackShort) - } - if (v.isValidByte) { + if v.isValidByte then val vi = v.toByte check(vi, _.packByte(vi), _.unpackByte) - } else { + else checkOverflow(v, _.packLong(v), _.unpackByte) - } - - } } @@ -360,23 +347,19 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { check(v, _.packBigInteger(v), _.unpackBigInteger) } - for (bi <- Seq(BigInteger.valueOf(Long.MaxValue).add(BigInteger.valueOf(1)))) { + for bi <- Seq(BigInteger.valueOf(Long.MaxValue).add(BigInteger.valueOf(1))) do check(bi, _.packBigInteger(bi), _.unpackBigInteger()) - } - for (bi <- Seq(BigInteger.valueOf(Long.MaxValue).shiftLeft(10))) { - try { + for bi <- Seq(BigInteger.valueOf(Long.MaxValue).shiftLeft(10)) do + try checkException(bi, _.packBigInteger(bi), _.unpackBigInteger()) fail("cannot reach here") - } catch { + catch case e: IllegalArgumentException => // OK - } - } - } test("pack/unpack strings") { - val utf8Strings = Arbitrary.arbitrary[String].suchThat(isValidUTF8 _) + val utf8Strings = Arbitrary.arbitrary[String].suchThat(isValidUTF8) utf8Strings.map { v => check(v, _.packString(v), _.unpackString) } @@ -385,17 +368,15 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { test("pack/unpack large strings") { // Large string val strLen = Seq(1000, 2000, 10000, 50000, 100000, 500000) - for (l <- strLen) { - val v: String = - Iterator.continually(Random.nextString(l * 10)).find(isValidUTF8).get + for l <- strLen do + val v: String = Iterator.continually(Random.nextString(l * 10)).find(isValidUTF8).get check(v, _.packString(v), _.unpackString) - } } test("report errors when packing/unpacking malformed strings") { pending("We need to produce malformed utf-8 strings in Java 8") // Create 100 malformed UTF8 Strings - val r = new Random(0) + val r = new Random(0) val malformedStrings = Iterator .continually { val b = new Array[Byte](10) @@ -405,16 +386,14 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { .filter(b => !isValidUTF8(new String(b))) .take(100) - for (malformedBytes <- malformedStrings) { + for malformedBytes <- malformedStrings do // Pack tests val malformed = new String(malformedBytes) - try { + try checkException(malformed, _.packString(malformed), _.unpackString()) - } catch { + catch case e: MessageStringCodingException => // OK - } - - try { + try checkException( malformed, { packer => @@ -423,10 +402,8 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { }, _.unpackString() ) - } catch { + catch case e: MessageStringCodingException => // OK - } - } } test("report errors when packing/unpacking strings that contain unmappable characters") { @@ -439,8 +416,8 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { .withActionOnMalformedString(CodingErrorAction.REPORT) .withActionOnUnmappableString(CodingErrorAction.REPORT) - for (bytes <- Seq(unmappable)) { - try { + for bytes <- Seq(unmappable) do + try checkException( bytes, { packer => @@ -451,10 +428,8 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { new PackerConfig(), unpackerConfig ) - } catch { + catch case e: MessageStringCodingException => // OK - } - } } test("pack/unpack binary") { @@ -462,7 +437,8 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { check( v, { packer => - packer.packBinaryHeader(v.length); packer.writePayload(v) + packer.packBinaryHeader(v.length); + packer.writePayload(v) }, { unpacker => val len = unpacker.unpackBinaryHeader() @@ -474,13 +450,14 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { } val len = Seq(1000, 2000, 10000, 50000, 100000, 500000) - for (l <- len) { + for l <- len do val v = new Array[Byte](l) Random.nextBytes(v) check( v, { packer => - packer.packBinaryHeader(v.length); packer.writePayload(v) + packer.packBinaryHeader(v.length); + packer.writePayload(v) }, { unpacker => val len = unpacker.unpackBinaryHeader() @@ -489,10 +466,11 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { out } ) - } } - val testHeaderLength = Seq(1, 2, 4, 8, 16, 17, 32, 64, 255, 256, 1000, 2000, 10000, 50000, 100000, 500000) + val testHeaderLength = Seq( + 1, 2, 4, 8, 16, 17, 32, 64, 255, 256, 1000, 2000, 10000, 50000, 100000, 500000 + ) test("pack/unpack arrays") { forAll { (v: Array[Int]) => @@ -505,24 +483,20 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { { unpacker => val len = unpacker.unpackArrayHeader() val out = new Array[Int](len) - for (i <- 0 until v.length) { + for i <- 0 until v.length do out(i) = unpacker.unpackInt - } out } ) } - for (l <- testHeaderLength) { + for l <- testHeaderLength do check(l, _.packArrayHeader(l), _.unpackArrayHeader()) - } - try { + try checkException(0, _.packArrayHeader(-1), _.unpackArrayHeader) - } catch { + catch case e: IllegalArgumentException => // OK - } - } test("pack/unpack maps") { @@ -541,40 +515,43 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { { unpacker => val len = unpacker.unpackMapHeader() val b = Seq.newBuilder[(Int, String)] - for (i <- 0 until len) { + for i <- 0 until len do b += ((unpacker.unpackInt, unpacker.unpackString)) - } b.result() } ) } - for (l <- testHeaderLength) { + for l <- testHeaderLength do check(l, _.packMapHeader(l), _.unpackMapHeader()) - } - try { + try checkException(0, _.packMapHeader(-1), _.unpackMapHeader) - } catch { + catch case e: IllegalArgumentException => // OK - } - } test("pack/unpack extension types") { forAll { (dataLen: Int, tpe: Byte) => val l = Math.abs(dataLen) l >= 0 ==> { - val ext = - new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(tpe), l) - check(ext, _.packExtensionTypeHeader(ext.getType, ext.getLength), _.unpackExtensionTypeHeader()) + val ext = new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(tpe), l) + check( + ext, + _.packExtensionTypeHeader(ext.getType, ext.getLength), + _.unpackExtensionTypeHeader() + ) } } - for (l <- testHeaderLength) { - val ext = new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(Random.nextInt(128)), l) - check(ext, _.packExtensionTypeHeader(ext.getType, ext.getLength), _.unpackExtensionTypeHeader()) - } + for l <- testHeaderLength do + val ext = + new ExtensionTypeHeader(ExtensionTypeHeader.checkedCastToByte(Random.nextInt(128)), l) + check( + ext, + _.packExtensionTypeHeader(ext.getType, ext.getLength), + _.unpackExtensionTypeHeader() + ) } @@ -585,31 +562,30 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { aMap, { packer => packer.packArrayHeader(aMap.size) - for (m <- aMap) { + for m <- aMap do packer.packMapHeader(m.size) - for ((k, v) <- m) { + for (k, v) <- m do packer.packString(k) packer.packString(v) - } - } }, { unpacker => val v = new Variable() unpacker.unpackValue(v) - import scala.jdk.CollectionConverters._ - v.asArrayValue().asScala + import scala.jdk.CollectionConverters.* + v.asArrayValue() + .asScala .map { m => val mv = m.asMapValue() val kvs = mv.getKeyValueArray kvs .grouped(2) - .map({ kvp: Array[Value] => + .map((kvp: Array[Value]) => val k = kvp(0) val v = kvp(1) (k.asStringValue().asString, v.asStringValue().asString) - }) + ) .toMap } .toList @@ -622,12 +598,24 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { val posInt = Gen.chooseNum(0, 1000000000 - 1) // NANOS_PER_SECOND forAll(posLong, posInt) { (second: Long, nano: Int) => val v = Instant.ofEpochSecond(second, nano) - check(v, { _.packTimestamp(v) }, { _.unpackTimestamp() }) + check( + v, { + _.packTimestamp(v) + }, { + _.unpackTimestamp() + } + ) } // Using different insterfaces forAll(posLong, posInt) { (second: Long, nano: Int) => val v = Instant.ofEpochSecond(second, nano) - check(v, { _.packTimestamp(second, nano) }, { _.unpackTimestamp() }) + check( + v, { + _.packTimestamp(second, nano) + }, { + _.unpackTimestamp() + } + ) } val secLessThan34bits = Gen.chooseNum[Long](0, 1L << 34) forAll(secLessThan34bits, posInt) { (second: Long, nano: Int) => @@ -640,23 +628,30 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { } // Corner-cases around uint32 boundaries - for ( - v <- Seq( - Instant.ofEpochSecond(Instant.now().getEpochSecond, 123456789L), // uint32 nanoseq (out of int32 range) - Instant.ofEpochSecond(-1302749144L, 0), // 1928-09-19T21:14:16Z - Instant.ofEpochSecond(-747359729L, 0), // 1946-04-27T00:04:31Z - Instant.ofEpochSecond(4257387427L, 0) // 2104-11-29T07:37:07Z + for v <- Seq( + Instant.ofEpochSecond( + Instant.now().getEpochSecond, + 123456789L + ), // uint32 nanoseq (out of int32 range) + Instant.ofEpochSecond(-1302749144L, 0), // 1928-09-19T21:14:16Z + Instant.ofEpochSecond(-747359729L, 0), // 1946-04-27T00:04:31Z + Instant.ofEpochSecond(4257387427L, 0) // 2104-11-29T07:37:07Z ) - ) { + do check(v, _.packTimestamp(v), _.unpackTimestamp()) - } } test("pack/unpack timestamp in millis") { val posLong = Gen.chooseNum[Long](-31557014167219200L, 31556889864403199L) forAll(posLong) { (millis: Long) => val v = Instant.ofEpochMilli(millis) - check(v, { _.packTimestamp(millis) }, { _.unpackTimestamp() }) + check( + v, { + _.packTimestamp(millis) + }, { + _.unpackTimestamp() + } + ) } } @@ -665,15 +660,15 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { forAll(posLong) { (millis: Long) => val v = Instant.ofEpochMilli(millis) check( - v, - { _.packTimestamp(millis) }, + v, { + _.packTimestamp(millis) + }, { u => val extHeader = u.unpackExtensionTypeHeader() - if (extHeader.isTimestampType) { + if extHeader.isTimestampType then u.unpackTimestamp(extHeader) - } else { + else fail("Cannot reach here") - } } ) } @@ -710,12 +705,11 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { a.withBufferSize(64 * 1024).equals(b) shouldBe false a.withAllowReadingStringAsBinary(false).equals(b) shouldBe false a.withAllowReadingBinaryAsString(false).equals(b) shouldBe false - a.withActionOnMalformedString(CodingErrorAction.REPORT) - .equals(b) shouldBe false - a.withActionOnUnmappableString(CodingErrorAction.REPORT) - .equals(b) shouldBe false + a.withActionOnMalformedString(CodingErrorAction.REPORT).equals(b) shouldBe false + a.withActionOnUnmappableString(CodingErrorAction.REPORT).equals(b) shouldBe false a.withStringSizeLimit(32).equals(b) shouldBe false a.withStringDecoderBufferSize(32).equals(b) shouldBe false } } -} + +end MessagePackTest diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index 7d762149c..c1b4b0a46 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -24,37 +24,33 @@ import wvlet.log.io.IOUtil.withResource import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream} import scala.util.Random -/** */ -class MessagePackerTest extends AirSpec with Benchmark { +/** + */ +class MessagePackerTest extends AirSpec with Benchmark: - private def verifyIntSeq(answer: Array[Int], packed: Array[Byte]): Unit = { + private def verifyIntSeq(answer: Array[Int], packed: Array[Byte]): Unit = val unpacker = MessagePack.newDefaultUnpacker(packed) val b = Array.newBuilder[Int] - while (unpacker.hasNext) { + while unpacker.hasNext do b += unpacker.unpackInt() - } val result = b.result() result.size shouldBe answer.size result shouldBe answer - } - private def createTempFile = { + private def createTempFile = val f = File.createTempFile("msgpackTest", "msgpack") f.deleteOnExit f - } - private def createTempFileWithOutputStream = { + private def createTempFileWithOutputStream = val f = createTempFile val out = new FileOutputStream(f) (f, out) - } - private def createTempFileWithChannel = { + private def createTempFileWithChannel = val (f, out) = createTempFileWithOutputStream val ch = out.getChannel (f, ch) - } test("MessagePacker") { @@ -69,16 +65,14 @@ class MessagePackerTest extends AirSpec with Benchmark { val intSeq2 = intSeq.reverse val b2 = new ByteArrayOutputStream - packer - .reset(new OutputStreamBufferOutput(b2)) + packer.reset(new OutputStreamBufferOutput(b2)) intSeq2 foreach packer.packInt packer.close verifyIntSeq(intSeq2, b2.toByteArray) val intSeq3 = intSeq2.sorted val b3 = new ByteArrayOutputStream - packer - .reset(new OutputStreamBufferOutput(b3)) + packer.reset(new OutputStreamBufferOutput(b3)) intSeq3 foreach packer.packInt packer.close verifyIntSeq(intSeq3, b3.toByteArray) @@ -86,43 +80,41 @@ class MessagePackerTest extends AirSpec with Benchmark { test("improve the performance via reset method") { val N = 1000 - val t = time("packer", repeat = 10) { - block("no-buffer-reset") { - val out = new ByteArrayOutputStream - withResource(MessagePack.newDefaultPacker(out)) { packer => - for (i <- 0 until N) { - val outputStream = new ByteArrayOutputStream() - packer - .reset(new OutputStreamBufferOutput(outputStream)) - packer.packInt(0) - packer.flush() + val t = + time("packer", repeat = 10) { + block("no-buffer-reset") { + val out = new ByteArrayOutputStream + withResource(MessagePack.newDefaultPacker(out)) { packer => + for i <- 0 until N do + val outputStream = new ByteArrayOutputStream() + packer.reset(new OutputStreamBufferOutput(outputStream)) + packer.packInt(0) + packer.flush() } } - } - block("buffer-reset") { - val out = new ByteArrayOutputStream - withResource(MessagePack.newDefaultPacker(out)) { packer => - val bufferOut = - new OutputStreamBufferOutput(new ByteArrayOutputStream()) - for (i <- 0 until N) { - val outputStream = new ByteArrayOutputStream() - bufferOut.reset(outputStream) - packer.reset(bufferOut) - packer.packInt(0) - packer.flush() + block("buffer-reset") { + val out = new ByteArrayOutputStream + withResource(MessagePack.newDefaultPacker(out)) { packer => + val bufferOut = new OutputStreamBufferOutput(new ByteArrayOutputStream()) + for i <- 0 until N do + val outputStream = new ByteArrayOutputStream() + bufferOut.reset(outputStream) + packer.reset(bufferOut) + packer.packInt(0) + packer.flush() } } } - } - t("buffer-reset").averageWithoutMinMax <= t("no-buffer-reset").averageWithoutMinMax shouldBe true + t("buffer-reset").averageWithoutMinMax <= t("no-buffer-reset").averageWithoutMinMax shouldBe + true } test("pack larger string array than byte buf") { // Based on https://github.com/msgpack/msgpack-java/issues/154 - def test(bufferSize: Int, stringSize: Int): Boolean = { + def test(bufferSize: Int, stringSize: Int): Boolean = val str = "a" * stringSize val rawString = ValueFactory.newString(str.getBytes("UTF-8")) val array = ValueFactory.newArray(rawString) @@ -132,14 +124,8 @@ class MessagePackerTest extends AirSpec with Benchmark { packer.close() out.toByteArray true - } - val testCases = Seq( - 32 -> 30, - 33 -> 31, - 32 -> 31, - 34 -> 32 - ) + val testCases = Seq(32 -> 30, 33 -> 31, 32 -> 31, 34 -> 32) testCases.foreach { case (bufferSize, stringSize) => test(bufferSize, stringSize) } @@ -151,24 +137,20 @@ class MessagePackerTest extends AirSpec with Benchmark { packer.packInt(99) packer.close - val up0 = MessagePack - .newDefaultUnpacker(new FileInputStream(f0)) + val up0 = MessagePack.newDefaultUnpacker(new FileInputStream(f0)) up0.unpackInt shouldBe 99 up0.hasNext shouldBe false up0.close val (f1, out1) = createTempFileWithOutputStream - packer - .reset(new OutputStreamBufferOutput(out1)) + packer.reset(new OutputStreamBufferOutput(out1)) packer.packInt(99) packer.flush - packer - .reset(new OutputStreamBufferOutput(out1)) + packer.reset(new OutputStreamBufferOutput(out1)) packer.packString("hello") packer.close - val up1 = MessagePack - .newDefaultUnpacker(new FileInputStream(f1)) + val up1 = MessagePack.newDefaultUnpacker(new FileInputStream(f1)) up1.unpackInt shouldBe 99 up1.unpackString shouldBe "hello" up1.hasNext shouldBe false @@ -181,24 +163,20 @@ class MessagePackerTest extends AirSpec with Benchmark { packer.packInt(99) packer.close - val up0 = MessagePack - .newDefaultUnpacker(new FileInputStream(f0)) + val up0 = MessagePack.newDefaultUnpacker(new FileInputStream(f0)) up0.unpackInt shouldBe 99 up0.hasNext shouldBe false up0.close val (f1, out1) = createTempFileWithChannel - packer - .reset(new ChannelBufferOutput(out1)) + packer.reset(new ChannelBufferOutput(out1)) packer.packInt(99) packer.flush - packer - .reset(new ChannelBufferOutput(out1)) + packer.reset(new ChannelBufferOutput(out1)) packer.packString("hello") packer.close - val up1 = MessagePack - .newDefaultUnpacker(new FileInputStream(f1)) + val up1 = MessagePack.newDefaultUnpacker(new FileInputStream(f1)) up1.unpackInt shouldBe 99 up1.unpackString shouldBe "hello" up1.hasNext shouldBe false @@ -208,32 +186,32 @@ class MessagePackerTest extends AirSpec with Benchmark { test("pack a lot of String within expected time") { val count = 20000 - def measureDuration(outputStream: java.io.OutputStream) = { + def measureDuration(outputStream: java.io.OutputStream) = val packer = MessagePack.newDefaultPacker(outputStream) var i = 0 - while (i < count) { + while i < count do packer.packString("0123456789ABCDEF") i += 1 - } packer.close - } - val t = time("packString into OutputStream", repeat = 10) { - block("byte-array-output-stream") { - measureDuration(new ByteArrayOutputStream()) - } + val t = + time("packString into OutputStream", repeat = 10) { + block("byte-array-output-stream") { + measureDuration(new ByteArrayOutputStream()) + } - block("file-output-stream") { - val (_, fileOutput) = createTempFileWithOutputStream - measureDuration(fileOutput) + block("file-output-stream") { + val (_, fileOutput) = createTempFileWithOutputStream + measureDuration(fileOutput) + } } - } - t("file-output-stream").averageWithoutMinMax < (t("byte-array-output-stream").averageWithoutMinMax * 5) shouldBe true + t("file-output-stream").averageWithoutMinMax < + (t("byte-array-output-stream").averageWithoutMinMax * 5) shouldBe true } } test("compute totalWrittenBytes") { - val out = new ByteArrayOutputStream + val out = new ByteArrayOutputStream val packerTotalWrittenBytes = withResource(MessagePack.newDefaultPacker(out)) { packer => packer @@ -254,11 +232,7 @@ class MessagePackerTest extends AirSpec with Benchmark { test("support read-only buffer") { val payload = Array[Byte](1) val out = new ByteArrayOutputStream() - val packer = MessagePack - .newDefaultPacker(out) - .packBinaryHeader(1) - .writePayload(payload) - .close() + val packer = MessagePack.newDefaultPacker(out).packBinaryHeader(1).writePayload(payload).close() } test("pack small string with STR8") { @@ -272,8 +246,7 @@ class MessagePackerTest extends AirSpec with Benchmark { } test("be able to disable STR8 for backward compatibility") { - val config = new PackerConfig() - .withStr8FormatSupport(false) + val config = new PackerConfig().withStr8FormatSupport(false) val packer = config.newBufferPacker() packer.packString("Hello. This is a string longer than 32 characters!") @@ -298,16 +271,14 @@ class MessagePackerTest extends AirSpec with Benchmark { test("write raw binary") { val packer = new MessagePack.PackerConfig().newBufferPacker() - val msg = - Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) + val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) packer.writePayload(msg) } test("append raw binary") { val packer = new MessagePack.PackerConfig().newBufferPacker() - val msg = - Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) + val msg = Array[Byte](-127, -92, 116, 121, 112, 101, -92, 112, 105, 110, 103) packer.addPayload(msg) } -} +end MessagePackerTest diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 620e7dbe2..ae25d2845 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -16,41 +16,37 @@ package org.msgpack.core import org.msgpack.core.MessagePackSpec.{createMessagePackData, toHex} -import org.msgpack.core.buffer._ +import org.msgpack.core.buffer.* import org.msgpack.value.ValueType import wvlet.airspec.AirSpec import wvlet.log.LogSupport import wvlet.log.io.IOUtil.withResource -import java.io._ +import java.io.* import java.nio.ByteBuffer import java.util.Collections -import scala.jdk.CollectionConverters._ +import scala.jdk.CollectionConverters.* import scala.util.Random -object MessageUnpackerTest { - class SplitMessageBufferInput(array: Array[Array[Byte]]) extends MessageBufferInput { - var cursor = 0 - override def next(): MessageBuffer = { - if (cursor < array.length) { +object MessageUnpackerTest: + class SplitMessageBufferInput(array: Array[Array[Byte]]) extends MessageBufferInput: + var cursor = 0 + override def next(): MessageBuffer = + if cursor < array.length then val a = array(cursor) cursor += 1 MessageBuffer.wrap(a) - } else { + else null - } - } override def close(): Unit = {} - } -} -import org.msgpack.core.MessageUnpackerTest._ +import org.msgpack.core.MessageUnpackerTest.* -class MessageUnpackerTest extends AirSpec with Benchmark { +class MessageUnpackerTest extends AirSpec with Benchmark: - private val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] - private def testData: Array[Byte] = { + private val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] + private def testData: Array[Byte] = val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) @@ -68,17 +64,18 @@ class MessageUnpackerTest extends AirSpec with Benchmark { debug(s"packed: ${toHex(arr)}, size:${arr.length}") arr - } - private val intSeq = (for (i <- 0 until 100) yield Random.nextInt()).toArray[Int] + private val intSeq = + ( + for (i <- 0 until 100) + yield Random.nextInt() + ).toArray[Int] - private def testData2: Array[Byte] = { + private def testData2: Array[Byte] = val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out); - packer - .packBoolean(true) - .packBoolean(false) + packer.packBoolean(true).packBoolean(false) intSeq.foreach(packer.packInt) packer.close() @@ -86,15 +83,15 @@ class MessageUnpackerTest extends AirSpec with Benchmark { val arr = out.toByteArray debug(s"packed: ${toHex(arr)}") arr - } - private def write(packer: MessagePacker, r: Random): Unit = { - val tpeIndex = Iterator - .continually(r.nextInt(MessageFormat.values().length)) - .find(_ != MessageFormat.NEVER_USED.ordinal()) - .get + private def write(packer: MessagePacker, r: Random): Unit = + val tpeIndex = + Iterator + .continually(r.nextInt(MessageFormat.values().length)) + .find(_ != MessageFormat.NEVER_USED.ordinal()) + .get val tpe = MessageFormat.values()(tpeIndex) - tpe.getValueType match { + tpe.getValueType match case ValueType.INTEGER => val v = r.nextInt(Int.MaxValue) @@ -124,27 +121,27 @@ class MessageUnpackerTest extends AirSpec with Benchmark { trace(s"array len: $len") packer.packArrayHeader(len) var i = 0 - while (i < len) { + while i < len do write(packer, r) i += 1 - } case ValueType.MAP => val len = r.nextInt(5) + 1 packer.packMapHeader(len) trace(s"map len: ${len}") var i = 0 - while (i < len * 2) { + while i < len * 2 do write(packer, r) i += 1 - } case _ => val v = r.nextInt(Int.MaxValue) trace(s"int: $v") packer.packInt(v) - } - } - private def testData3(N: Int): Array[Byte] = { + end match + + end write + + private def testData3(N: Int): Array[Byte] = val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) @@ -160,11 +157,10 @@ class MessageUnpackerTest extends AirSpec with Benchmark { trace(s"packed: ${toHex(arr)}") debug(s"size:${arr.length}") arr - } - private def readValue(unpacker: MessageUnpacker): Unit = { + private def readValue(unpacker: MessageUnpacker): Unit = val f = unpacker.getNextFormat() - f.getValueType match { + f.getValueType match case ValueType.ARRAY => val arrLen = unpacker.unpackArrayHeader() debug(s"arr size: $arrLen") @@ -180,24 +176,20 @@ class MessageUnpackerTest extends AirSpec with Benchmark { case other => unpacker.skipValue() debug(s"unknown type: $f") - } - } - private def createTempFile: File = { + private def createTempFile: File = val f = File.createTempFile("msgpackTest", "msgpack") f.deleteOnExit val p = MessagePack.newDefaultPacker(new FileOutputStream(f)) p.packInt(99) p.close f - } - private def checkFile(u: MessageUnpacker): Boolean = { + private def checkFile(u: MessageUnpacker): Boolean = u.unpackInt shouldBe 99 u.hasNext shouldBe false - } - private def unpackers(data: Array[Byte]): Seq[MessageUnpacker] = { + private def unpackers(data: Array[Byte]): Seq[MessageUnpacker] = val bb = ByteBuffer.allocate(data.length) val db = ByteBuffer.allocateDirect(data.length) bb.put(data).flip() @@ -205,20 +197,21 @@ class MessageUnpackerTest extends AirSpec with Benchmark { val builder = Seq.newBuilder[MessageUnpacker] builder += MessagePack.newDefaultUnpacker(data) builder += MessagePack.newDefaultUnpacker(bb) - if (!universal) { + if !universal then builder += MessagePack.newDefaultUnpacker(db) - } builder.result() - } - private def unpackerCollectionWithVariousBuffers(data: Array[Byte], chunkSize: Int): Seq[MessageUnpacker] = { + private def unpackerCollectionWithVariousBuffers( + data: Array[Byte], + chunkSize: Int + ): Seq[MessageUnpacker] = val seqBytes = Seq.newBuilder[MessageBufferInput] val seqByteBuffers = Seq.newBuilder[MessageBufferInput] val seqDirectBuffers = Seq.newBuilder[MessageBufferInput] var left = data.length var position = 0 - while (left > 0) { + while left > 0 do val length = Math.min(chunkSize, left) seqBytes += new ArrayBufferInput(data, position, length) val bb = ByteBuffer.allocate(length) @@ -229,52 +222,56 @@ class MessageUnpackerTest extends AirSpec with Benchmark { seqDirectBuffers += new ByteBufferInput(db) left -= length position += length - } val builder = Seq.newBuilder[MessageUnpacker] - builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqBytes.result().asJava))) - builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqByteBuffers.result().asJava))) - if (!universal) { - builder += MessagePack.newDefaultUnpacker(new SequenceMessageBufferInput(Collections.enumeration(seqDirectBuffers.result().asJava))) - } + builder += + MessagePack.newDefaultUnpacker( + new SequenceMessageBufferInput(Collections.enumeration(seqBytes.result().asJava)) + ) + builder += + MessagePack.newDefaultUnpacker( + new SequenceMessageBufferInput(Collections.enumeration(seqByteBuffers.result().asJava)) + ) + if !universal then + builder += + MessagePack.newDefaultUnpacker( + new SequenceMessageBufferInput(Collections.enumeration(seqDirectBuffers.result().asJava)) + ) builder.result() - } + + end unpackerCollectionWithVariousBuffers test("MessageUnpacker") { test("parse message packed data") { val arr = testData - for (unpacker <- unpackers(arr)) { + for unpacker <- unpackers(arr) do var count = 0 - while (unpacker.hasNext) { + while unpacker.hasNext do count += 1 readValue(unpacker) - } count shouldBe 6 unpacker.getTotalReadBytes shouldBe arr.length unpacker.close() unpacker.getTotalReadBytes shouldBe arr.length - } } test("skip reading values") { - for (unpacker <- unpackers(testData)) { + for unpacker <- unpackers(testData) do var skipCount = 0 - while (unpacker.hasNext) { + while unpacker.hasNext do unpacker.skipValue() skipCount += 1 - } skipCount shouldBe 2 unpacker.getTotalReadBytes shouldBe testData.length unpacker.close() unpacker.getTotalReadBytes shouldBe testData.length - } } test("compare skip performance") { @@ -283,23 +280,20 @@ class MessageUnpackerTest extends AirSpec with Benchmark { time("skip performance", repeat = 100) { block("switch") { - for (unpacker <- unpackers(data)) { + for unpacker <- unpackers(data) do var skipCount = 0 - while (unpacker.hasNext) { + while unpacker.hasNext do unpacker.skipValue() skipCount += 1 - } skipCount shouldBe N - } } } time("bulk skip performance", repeat = 100) { block("switch") { - for (unpacker <- unpackers(data)) { + for unpacker <- unpackers(data) do unpacker.skipValue(N) unpacker.hasNext shouldBe false - } } } @@ -308,12 +302,12 @@ class MessageUnpackerTest extends AirSpec with Benchmark { test("parse int data") { debug(intSeq.mkString(", ")) - for (unpacker <- unpackers(testData2)) { + for unpacker <- unpackers(testData2) do val ib = Seq.newBuilder[Int] - while (unpacker.hasNext) { + while unpacker.hasNext do val f = unpacker.getNextFormat - f.getValueType match { + f.getValueType match case ValueType.INTEGER => val i = unpacker.unpackInt() trace(f"read int: $i%,d") @@ -323,54 +317,48 @@ class MessageUnpackerTest extends AirSpec with Benchmark { trace(s"read boolean: $b") case other => unpacker.skipValue() - } - } ib.result() shouldBe intSeq.toSeq unpacker.getTotalReadBytes shouldBe testData2.length unpacker.close() unpacker.getTotalReadBytes shouldBe testData2.length - } } test("read data at the buffer boundary") { - trait SplitTest extends LogSupport { + trait SplitTest extends LogSupport: val data: Array[Byte] - def run: Unit = { - for (unpacker <- unpackers(data)) { - val numElems = { + def run: Unit = + for unpacker <- unpackers(data) do + val numElems = var c = 0 - while (unpacker.hasNext) { + while unpacker.hasNext do readValue(unpacker) c += 1 - } c - } - for (splitPoint <- 1 until data.length - 1) { + for splitPoint <- 1 until data.length - 1 do debug(s"split at $splitPoint") val (h, t) = data.splitAt(splitPoint) val bin = new SplitMessageBufferInput(Array(h, t)) val unpacker = MessagePack.newDefaultUnpacker(bin) var count = 0 - while (unpacker.hasNext) { + while unpacker.hasNext do count += 1 val f = unpacker.getNextFormat readValue(unpacker) - } count shouldBe numElems unpacker.getTotalReadBytes shouldBe data.length unpacker.close() unpacker.getTotalReadBytes shouldBe data.length - } - } - } - } - new SplitTest { val data = testData }.run - new SplitTest { val data = testData3(30) }.run + new SplitTest: + val data = testData + .run + new SplitTest: + val data = testData3(30) + .run } test("read integer at MessageBuffer boundaries") { @@ -382,18 +370,21 @@ class MessageUnpackerTest extends AirSpec with Benchmark { val data = packer.toByteArray // Boundary test - withResource(MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(data), 8192))) { unpacker => + withResource( + MessagePack.newDefaultUnpacker( + new InputStreamBufferInput(new ByteArrayInputStream(data), 8192) + ) + ) { unpacker => (0 until 1170).foreach { i => unpacker.unpackLong() shouldBe 0x0011223344556677L } } // Boundary test for sequences of ByteBuffer, DirectByteBuffer backed MessageInput. - for (unpacker <- unpackerCollectionWithVariousBuffers(data, 32)) { + for unpacker <- unpackerCollectionWithVariousBuffers(data, 32) do (0 until 1170).foreach { i => unpacker.unpackLong() shouldBe 0x0011223344556677L } - } } test("read string at MessageBuffer boundaries") { @@ -405,36 +396,34 @@ class MessageUnpackerTest extends AirSpec with Benchmark { val data = packer.toByteArray // Boundary test - withResource(MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(data), 8192))) { unpacker => + withResource( + MessagePack.newDefaultUnpacker( + new InputStreamBufferInput(new ByteArrayInputStream(data), 8192) + ) + ) { unpacker => (0 until 1170).foreach { i => unpacker.unpackString() shouldBe "hello world" } } // Boundary test for sequences of ByteBuffer, DirectByteBuffer backed MessageInput. - for (unpacker <- unpackerCollectionWithVariousBuffers(data, 32)) { + for unpacker <- unpackerCollectionWithVariousBuffers(data, 32) do (0 until 1170).foreach { i => unpacker.unpackString() shouldBe "hello world" } - } } test("be faster than msgpack-v6 skip") { - trait Fixture { + trait Fixture: val unpacker: MessageUnpacker - def run: Unit = { + def run: Unit = var count = 0 - try { - while (unpacker.hasNext) { + try + while unpacker.hasNext do unpacker.skipValue() count += 1 - } - } finally { - unpacker.close() - } - } - } + finally unpacker.close() val data = testData3(10000) val N = 100 @@ -443,64 +432,69 @@ class MessageUnpackerTest extends AirSpec with Benchmark { val db = ByteBuffer.allocateDirect(data.length) db.put(data).flip() - val t = time("skip performance", repeat = N) { - block("v6") { - val v6 = new org.msgpack.MessagePack() - val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(data)) - var count = 0 - try { - while (true) { - unpacker.skip() - count += 1 - } - } catch { - case e: EOFException => - } finally unpacker.close() - } + val t = + time("skip performance", repeat = N) { + block("v6") { + val v6 = new org.msgpack.MessagePack() + val unpacker = + new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(data)) + var count = 0 + try + while true do + unpacker.skip() + count += 1 + catch + case e: EOFException => + finally + unpacker.close() + } - block("v7-array") { - new Fixture { - override val unpacker = MessagePack.newDefaultUnpacker(data) - }.run - } + block("v7-array") { + new Fixture: + override val unpacker = MessagePack.newDefaultUnpacker(data) + .run + } - block("v7-array-buffer") { - new Fixture { - override val unpacker = MessagePack.newDefaultUnpacker(bb) - }.run - } - if (!universal) block("v7-direct-buffer") { - new Fixture { - override val unpacker = MessagePack.newDefaultUnpacker(db) - }.run + block("v7-array-buffer") { + new Fixture: + override val unpacker = MessagePack.newDefaultUnpacker(bb) + .run + } + if !universal then + block("v7-direct-buffer") { + new Fixture: + override val unpacker = MessagePack.newDefaultUnpacker(db) + .run + } } - } t("v7-array").averageWithoutMinMax <= t("v6").averageWithoutMinMax shouldBe true t("v7-array-buffer").averageWithoutMinMax <= t("v6").averageWithoutMinMax shouldBe true - if (!universal) { + if !universal then t("v7-direct-buffer").averageWithoutMinMax <= t("v6").averageWithoutMinMax shouldBe true - } } - import org.msgpack.`type`.{ValueType => ValueTypeV6} + import org.msgpack.`type`.ValueType as ValueTypeV6 test("be faster than msgpack-v6 read value") { - def readValueV6(unpacker: org.msgpack.unpacker.MessagePackUnpacker): Unit = { + def readValueV6(unpacker: org.msgpack.unpacker.MessagePackUnpacker): Unit = val vt = unpacker.getNextType() - vt match { + vt match case ValueTypeV6.ARRAY => val len = unpacker.readArrayBegin() var i = 0 - while (i < len) { readValueV6(unpacker); i += 1 } + while i < len do + readValueV6(unpacker); + i += 1 unpacker.readArrayEnd() case ValueTypeV6.MAP => val len = unpacker.readMapBegin() var i = 0 - while (i < len) { - readValueV6(unpacker); readValueV6(unpacker); i += 1 - } + while i < len do + readValueV6(unpacker); + readValueV6(unpacker); + i += 1 unpacker.readMapEnd() case ValueTypeV6.NIL => unpacker.readNil() @@ -514,23 +508,27 @@ class MessageUnpackerTest extends AirSpec with Benchmark { unpacker.readByteArray() case _ => unpacker.skip() - } - } + end readValueV6 val buf = new Array[Byte](8192) - def readValue(unpacker: MessageUnpacker): Unit = { + def readValue(unpacker: MessageUnpacker): Unit = val f = unpacker.getNextFormat val vt = f.getValueType - vt match { + vt match case ValueType.ARRAY => val len = unpacker.unpackArrayHeader() var i = 0 - while (i < len) { readValue(unpacker); i += 1 } + while i < len do + readValue(unpacker); + i += 1 case ValueType.MAP => val len = unpacker.unpackMapHeader() var i = 0 - while (i < len) { readValue(unpacker); readValue(unpacker); i += 1 } + while i < len do + readValue(unpacker); + readValue(unpacker); + i += 1 case ValueType.NIL => unpacker.unpackNil() case ValueType.INTEGER => @@ -547,20 +545,17 @@ class MessageUnpackerTest extends AirSpec with Benchmark { unpacker.readPayload(buf, 0, len) case _ => unpacker.skipValue() - } - } - trait Fixture { + end match + end readValue + trait Fixture: val unpacker: MessageUnpacker - def run: Unit = { + def run: Unit = var count = 0 - try { - while (unpacker.hasNext) { + try + while unpacker.hasNext do readValue(unpacker) count += 1 - } - } finally unpacker.close() - } - } + finally unpacker.close() val data = testData3(10000) val N = 100 @@ -569,49 +564,55 @@ class MessageUnpackerTest extends AirSpec with Benchmark { val db = ByteBuffer.allocateDirect(data.length) db.put(data).flip() - val t = time("unpack performance", repeat = N) { - block("v6") { - val v6 = new org.msgpack.MessagePack() - val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(data)) - var count = 0 - try { - while (true) { - readValueV6(unpacker) - count += 1 - } - } catch { - case e: EOFException => - } finally unpacker.close() - } + val t = + time("unpack performance", repeat = N) { + block("v6") { + val v6 = new org.msgpack.MessagePack() + val unpacker = + new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(data)) + var count = 0 + try + while true do + readValueV6(unpacker) + count += 1 + catch + case e: EOFException => + finally + unpacker.close() + } - block("v7-array") { - new Fixture { - override val unpacker = MessagePack.newDefaultUnpacker(data) - }.run - } + block("v7-array") { + new Fixture: + override val unpacker = MessagePack.newDefaultUnpacker(data) + .run + } - block("v7-array-buffer") { - new Fixture { - override val unpacker = MessagePack.newDefaultUnpacker(bb) - }.run - } + block("v7-array-buffer") { + new Fixture: + override val unpacker = MessagePack.newDefaultUnpacker(bb) + .run + } - if (!universal) block("v7-direct-buffer") { - new Fixture { - override val unpacker = MessagePack.newDefaultUnpacker(db) - }.run + if !universal then + block("v7-direct-buffer") { + new Fixture: + override val unpacker = MessagePack.newDefaultUnpacker(db) + .run + } } - } - if (t("v7-array").averageWithoutMinMax > t("v6").averageWithoutMinMax) { - warn(s"v7-array ${t("v7-array").averageWithoutMinMax} is slower than v6 ${t("v6").averageWithoutMinMax}") - } - if (t("v7-array-buffer").averageWithoutMinMax > t("v6").averageWithoutMinMax) { - warn(s"v7-array-buffer ${t("v7-array-buffer").averageWithoutMinMax} is slower than v6 ${t("v6").averageWithoutMinMax}") - } - if (!universal) { + if t("v7-array").averageWithoutMinMax > t("v6").averageWithoutMinMax then + warn( + s"v7-array ${t("v7-array").averageWithoutMinMax} is slower than v6 ${t("v6") + .averageWithoutMinMax}" + ) + if t("v7-array-buffer").averageWithoutMinMax > t("v6").averageWithoutMinMax then + warn( + s"v7-array-buffer ${t("v7-array-buffer").averageWithoutMinMax} is slower than v6 ${t("v6") + .averageWithoutMinMax}" + ) + if !universal then t("v7-direct-buffer").averageWithoutMinMax <= t("v6").averageWithoutMinMax shouldBe true - } } test("be faster for reading binary than v6") { @@ -626,31 +627,26 @@ class MessageUnpackerTest extends AirSpec with Benchmark { } packer.close() - trait Fixture { + trait Fixture: val unpacker: MessageUnpacker val loop: Int - def run: Unit = { + def run: Unit = var i = 0 - try { - while (i < loop) { + try + while i < loop do val len = unpacker.unpackBinaryHeader() val out = new Array[Byte](len) unpacker.readPayload(out, 0, len) i += 1 - } - } finally unpacker.close() - } - def runRef: Unit = { + finally unpacker.close() + def runRef: Unit = var i = 0 - try { - while (i < loop) { + try + while i < loop do val len = unpacker.unpackBinaryHeader() val out = unpacker.readPayloadAsReference(len) i += 1 - } - } finally unpacker.close() - } - } + finally unpacker.close() val b = bos.toByteArray val bb = ByteBuffer.allocate(b.length) bb.put(b).flip() @@ -659,66 +655,67 @@ class MessageUnpackerTest extends AirSpec with Benchmark { time("unpackBinary", repeat = 100) { block("v6") { - val v6 = new org.msgpack.MessagePack() - val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(b)) - var i = 0 - while (i < R) { + val v6 = new org.msgpack.MessagePack() + val unpacker = + new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(b)) + var i = 0 + while i < R do val out = unpacker.readByteArray() i += 1 - } unpacker.close() } block("v7-array") { - new Fixture { + new Fixture: override val unpacker = MessagePack.newDefaultUnpacker(b) override val loop = R - }.run + .run } block("v7-array-buffer") { - new Fixture { + new Fixture: override val unpacker = MessagePack.newDefaultUnpacker(bb) override val loop = R - }.run + .run } - if (!universal) block("v7-direct-buffer") { - new Fixture { - override val unpacker = MessagePack.newDefaultUnpacker(db) - override val loop = R - }.run - } + if !universal then + block("v7-direct-buffer") { + new Fixture: + override val unpacker = MessagePack.newDefaultUnpacker(db) + override val loop = R + .run + } block("v7-ref-array") { - new Fixture { + new Fixture: override val unpacker = MessagePack.newDefaultUnpacker(b) override val loop = R - }.runRef + .runRef } block("v7-ref-array-buffer") { - new Fixture { + new Fixture: override val unpacker = MessagePack.newDefaultUnpacker(bb) override val loop = R - }.runRef + .runRef } - if (!universal) block("v7-ref-direct-buffer") { - new Fixture { - override val unpacker = MessagePack.newDefaultUnpacker(db) - override val loop = R - }.runRef - } + if !universal then + block("v7-ref-direct-buffer") { + new Fixture: + override val unpacker = MessagePack.newDefaultUnpacker(db) + override val loop = R + .runRef + } } } test("read payload as a reference") { - val dataSizes = - Seq(0, 1, 5, 8, 16, 32, 128, 256, 1024, 2000, 10000, 100000) + val dataSizes = Seq(0, 1, 5, 8, 16, 32, 128, 256, 1024, 2000, 10000, 100000) - for (s <- dataSizes) { + for s <- dataSizes do test(f"data size is $s%,d") { val data = new Array[Byte](s) Random.nextBytes(data) @@ -728,7 +725,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark { packer.writePayload(data) packer.close() - for (unpacker <- unpackers(b.toByteArray)) { + for unpacker <- unpackers(b.toByteArray) do val len = unpacker.unpackBinaryHeader() len shouldBe s val ref = unpacker.readPayloadAsReference(len) @@ -738,21 +735,18 @@ class MessageUnpackerTest extends AirSpec with Benchmark { ref.getBytes(0, stored, 0, len) stored shouldBe data - } } - } } test("reset the internal states") { val data = intSeq val b = createMessagePackData(packer => data foreach packer.packInt) - for (unpacker <- unpackers(b)) { + for unpacker <- unpackers(b) do val unpacked = Array.newBuilder[Int] - while (unpacker.hasNext) { + while unpacker.hasNext do unpacked += unpacker.unpackInt() - } unpacker.close unpacked.result() shouldBe data @@ -761,9 +755,8 @@ class MessageUnpackerTest extends AirSpec with Benchmark { val bi = new ArrayBufferInput(b2) unpacker.reset(bi) val unpacked2 = Array.newBuilder[Int] - while (unpacker.hasNext) { + while unpacker.hasNext do unpacked2 += unpacker.unpackInt() - } unpacker.close unpacked2.result() shouldBe data2 @@ -771,12 +764,10 @@ class MessageUnpackerTest extends AirSpec with Benchmark { bi.reset(b2) unpacker.reset(bi) val unpacked3 = Array.newBuilder[Int] - while (unpacker.hasNext) { + while unpacker.hasNext do unpacked3 += unpacker.unpackInt() - } unpacker.close unpacked3.result() shouldBe data2 - } } @@ -790,42 +781,40 @@ class MessageUnpackerTest extends AirSpec with Benchmark { val mb = MessageBuffer.wrap(arr) val N = 1000 - val t = time("unpacker", repeat = 10) { - block("no-buffer-reset") { - withResource(MessagePack.newDefaultUnpacker(arr)) { unpacker => - for (i <- 0 until N) { - val buf = new ArrayBufferInput(arr) - unpacker.reset(buf) - unpacker.unpackInt - unpacker.close + val t = + time("unpacker", repeat = 10) { + block("no-buffer-reset") { + withResource(MessagePack.newDefaultUnpacker(arr)) { unpacker => + for i <- 0 until N do + val buf = new ArrayBufferInput(arr) + unpacker.reset(buf) + unpacker.unpackInt + unpacker.close } } - } - block("reuse-array-input") { - withResource(MessagePack.newDefaultUnpacker(arr)) { unpacker => - val buf = new ArrayBufferInput(arr) - for (i <- 0 until N) { - buf.reset(arr) - unpacker.reset(buf) - unpacker.unpackInt - unpacker.close + block("reuse-array-input") { + withResource(MessagePack.newDefaultUnpacker(arr)) { unpacker => + val buf = new ArrayBufferInput(arr) + for i <- 0 until N do + buf.reset(arr) + unpacker.reset(buf) + unpacker.unpackInt + unpacker.close } } - } - block("reuse-message-buffer") { - withResource(MessagePack.newDefaultUnpacker(arr)) { unpacker => - val buf = new ArrayBufferInput(arr) - for (i <- 0 until N) { - buf.reset(mb) - unpacker.reset(buf) - unpacker.unpackInt - unpacker.close + block("reuse-message-buffer") { + withResource(MessagePack.newDefaultUnpacker(arr)) { unpacker => + val buf = new ArrayBufferInput(arr) + for i <- 0 until N do + buf.reset(mb) + unpacker.reset(buf) + unpacker.unpackInt + unpacker.close } } } - } // This performance comparison is too close, so we disabled it // t("reuse-message-buffer").averageWithoutMinMax should be <= t("no-buffer-reset").averageWithoutMinMax @@ -857,24 +846,20 @@ class MessageUnpackerTest extends AirSpec with Benchmark { } test("unpack large string data") { - def createLargeData(stringLength: Int): Array[Byte] = { + def createLargeData(stringLength: Int): Array[Byte] = val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) - packer - .packArrayHeader(2) - .packString("l" * stringLength) - .packInt(1) + packer.packArrayHeader(2).packString("l" * stringLength).packInt(1) packer.close() out.toByteArray - } Seq(8191, 8192, 8193, 16383, 16384, 16385).foreach { n => val arr = createLargeData(n) - for (unpacker <- unpackers(arr)) { + for unpacker <- unpackers(arr) do unpacker.unpackArrayHeader shouldBe 2 unpacker.unpackString.length shouldBe n @@ -884,12 +869,11 @@ class MessageUnpackerTest extends AirSpec with Benchmark { unpacker.close() unpacker.getTotalReadBytes shouldBe arr.length - } } } test("unpack string crossing end of buffer") { - def check(expected: String, strLen: Int) = { + def check(expected: String, strLen: Int) = val bytes = new Array[Byte](strLen) val out = new ByteArrayOutputStream @@ -899,52 +883,58 @@ class MessageUnpackerTest extends AirSpec with Benchmark { packer.packString(expected) packer.close - val unpacker = MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(out.toByteArray))) - val len = unpacker.unpackBinaryHeader + val unpacker = MessagePack.newDefaultUnpacker( + new InputStreamBufferInput(new ByteArrayInputStream(out.toByteArray)) + ) + val len = unpacker.unpackBinaryHeader unpacker.readPayload(len) val got = unpacker.unpackString unpacker.close got shouldBe expected - } - Seq("\u3042", "a\u3042", "\u3042a", "\u3042\u3044\u3046\u3048\u304A\u304B\u304D\u304F\u3051\u3053\u3055\u3057\u3059\u305B\u305D") - .foreach { s => - Seq(8185, 8186, 8187, 8188, 16377, 16378, 16379, 16380).foreach { n => - check(s, n) - } + Seq( + "\u3042", + "a\u3042", + "\u3042a", + "\u3042\u3044\u3046\u3048\u304A\u304B\u304D\u304F\u3051\u3053\u3055\u3057\u3059\u305B\u305D" + ).foreach { s => + Seq(8185, 8186, 8187, 8188, 16377, 16378, 16379, 16380).foreach { n => + check(s, n) } + } } - def readTest(input: MessageBufferInput): Unit = { + def readTest(input: MessageBufferInput): Unit = withResource(MessagePack.newDefaultUnpacker(input)) { unpacker => - while (unpacker.hasNext) { + while unpacker.hasNext do unpacker.unpackValue() - } } - } test("read value length at buffer boundary") { - val input = new SplitMessageBufferInput( - Array( - Array[Byte](MessagePack.Code.STR16), - Array[Byte](0x00), - Array[Byte](0x05), // STR16 length at the boundary - "hello".getBytes(MessagePack.UTF8) + val input = + new SplitMessageBufferInput( + Array( + Array[Byte](MessagePack.Code.STR16), + Array[Byte](0x00), + Array[Byte](0x05), // STR16 length at the boundary + "hello".getBytes(MessagePack.UTF8) + ) ) - ) readTest(input) - val input2 = new SplitMessageBufferInput( - Array( - Array[Byte](MessagePack.Code.STR32), - Array[Byte](0x00), - Array[Byte](0x00, 0x00), - Array[Byte](0x05), // STR32 length at the boundary - "hello".getBytes(MessagePack.UTF8) + val input2 = + new SplitMessageBufferInput( + Array( + Array[Byte](MessagePack.Code.STR32), + Array[Byte](0x00), + Array[Byte](0x00, 0x00), + Array[Byte](0x05), // STR32 length at the boundary + "hello".getBytes(MessagePack.UTF8) + ) ) - ) readTest(input2) } } -} + +end MessageUnpackerTest diff --git a/msgpack-core/src/test/scala/org/msgpack/core/StringLimitTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/StringLimitTest.scala index 96319a7f2..c54ce6329 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/StringLimitTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/StringLimitTest.scala @@ -4,7 +4,7 @@ import org.msgpack.core.MessagePack.UnpackerConfig import org.msgpack.value.Variable import wvlet.airspec.AirSpec -class StringLimitTest extends AirSpec { +class StringLimitTest extends AirSpec: test("throws an exception when the string size exceeds a limit") { val customLimit = 100 @@ -34,4 +34,5 @@ class StringLimitTest extends AirSpec { } } } -} + +end StringLimitTest diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala index 42872fc44..06d363fd5 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala @@ -20,28 +20,26 @@ import org.msgpack.core.MessagePack import org.msgpack.core.MessagePackSpec.createMessagePackData import wvlet.airspec.AirSpec -class ByteStringTest extends AirSpec { +class ByteStringTest extends AirSpec: private val unpackedString = "foo" private val byteString = ByteString(createMessagePackData(_.packString(unpackedString))) - private def unpackString(messageBuffer: MessageBuffer) = { - val input = new MessageBufferInput { + private def unpackString(messageBuffer: MessageBuffer) = + val input = + new MessageBufferInput: - private var isRead = false + private var isRead = false - override def next(): MessageBuffer = - if (isRead) { - null - } else { - isRead = true - messageBuffer - } - override def close(): Unit = {} - } + override def next(): MessageBuffer = + if isRead then + null + else + isRead = true + messageBuffer + override def close(): Unit = {} MessagePack.newDefaultUnpacker(input).unpackString() - } test("Unpacking a ByteString's ByteBuffer") { test("fail with a regular MessageBuffer") { @@ -53,4 +51,5 @@ class ByteStringTest extends AirSpec { } } } -} + +end ByteStringTest diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/DirectBufferAccessTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/DirectBufferAccessTest.scala index 40f4c7708..5bb4b49d1 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/DirectBufferAccessTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/DirectBufferAccessTest.scala @@ -19,11 +19,10 @@ import wvlet.airspec.AirSpec import java.nio.ByteBuffer -class DirectBufferAccessTest extends AirSpec { +class DirectBufferAccessTest extends AirSpec: test("instantiate DirectBufferAccess") { val bb = ByteBuffer.allocateDirect(1) val addr = DirectBufferAccess.getAddress(bb) } -} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index a43704fb0..5e6c1f96d 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -19,7 +19,7 @@ import org.msgpack.core.MessagePack import wvlet.airspec.AirSpec import wvlet.log.io.IOUtil.withResource -import java.io._ +import java.io.* import java.net.InetSocketAddress import java.nio.ByteBuffer import java.nio.channels.{ServerSocketChannel, SocketChannel} @@ -27,63 +27,49 @@ import java.util.concurrent.{Callable, Executors, TimeUnit} import java.util.zip.{GZIPInputStream, GZIPOutputStream} import scala.util.Random -class MessageBufferInputTest extends AirSpec { +class MessageBufferInputTest extends AirSpec: - private val targetInputSize = - Seq(0, 10, 500, 1000, 2000, 4000, 8000, 10000, 30000, 50000, 100000) + private val targetInputSize = Seq(0, 10, 500, 1000, 2000, 4000, 8000, 10000, 30000, 50000, 100000) - private def testData(size: Int): Array[Byte] = { + private def testData(size: Int): Array[Byte] = // debug(s"test data size: ${size}") val b = new Array[Byte](size) Random.nextBytes(b) b - } - private def testDataSet: Seq[Array[Byte]] = { - targetInputSize.map(testData) - } + private def testDataSet: Seq[Array[Byte]] = targetInputSize.map(testData) - private def runTest(factory: Array[Byte] => MessageBufferInput): Unit = { - for (b <- testDataSet) { + private def runTest(factory: Array[Byte] => MessageBufferInput): Unit = + for b <- testDataSet do checkInputData(b, factory(b)) - } - } - implicit class InputData(b: Array[Byte]) { - def compress = { + implicit class InputData(b: Array[Byte]): + def compress = val compressed = new ByteArrayOutputStream() val out = new GZIPOutputStream(compressed) out.write(b) out.close() compressed.toByteArray - } - def toByteBuffer = { - ByteBuffer.wrap(b) - } + def toByteBuffer = ByteBuffer.wrap(b) - def saveToTmpFile: File = { - val tmp = File - .createTempFile("testbuf", ".dat", new File("target")) + def saveToTmpFile: File = + val tmp = File.createTempFile("testbuf", ".dat", new File("target")) tmp.getParentFile.mkdirs() tmp.deleteOnExit() withResource(new FileOutputStream(tmp)) { out => out.write(b) } tmp - } - } - private def checkInputData(inputData: Array[Byte], in: MessageBufferInput): Unit = { + private def checkInputData(inputData: Array[Byte], in: MessageBufferInput): Unit = test(s"When input data size = ${inputData.length}") { var cursor = 0 - for (m <- Iterator.continually(in.next).takeWhile(_ != null)) { + for m <- Iterator.continually(in.next).takeWhile(_ != null) do m.toByteArray() shouldBe inputData.slice(cursor, cursor + m.size()) cursor += m.size() - } cursor shouldBe inputData.length } - } test("MessageBufferInput") { test("support byte arrays") { @@ -95,46 +81,40 @@ class MessageBufferInputTest extends AirSpec { } test("support InputStreams") { - runTest(b => new InputStreamBufferInput(new GZIPInputStream(new ByteArrayInputStream(b.compress)))) + runTest(b => + new InputStreamBufferInput(new GZIPInputStream(new ByteArrayInputStream(b.compress))) + ) } test("support file input channel") { runTest { b => val tmp = b.saveToTmpFile - try { - InputStreamBufferInput - .newBufferInput(new FileInputStream(tmp)) - } finally { - tmp.delete() - } + try InputStreamBufferInput.newBufferInput(new FileInputStream(tmp)) + finally tmp.delete() } } } - private def createTempFile = { + private def createTempFile = val f = File.createTempFile("msgpackTest", "msgpack") f.deleteOnExit f - } - private def createTempFileWithInputStream = { + private def createTempFileWithInputStream = val f = createTempFile val out = new FileOutputStream(f) MessagePack.newDefaultPacker(out).packInt(42).close val in = new FileInputStream(f) (f, in) - } - private def createTempFileWithChannel = { + private def createTempFileWithChannel = val (f, in) = createTempFileWithInputStream val ch = in.getChannel (f, ch) - } - private def readInt(buf: MessageBufferInput): Int = { + private def readInt(buf: MessageBufferInput): Int = val unpacker = MessagePack.newDefaultUnpacker(buf) unpacker.unpackInt - } test("InputStreamBufferInput") { test("reset buffer") { @@ -186,42 +166,42 @@ class MessageBufferInputTest extends AirSpec { } test("unpack without blocking") { - val server = - ServerSocketChannel.open.bind(new InetSocketAddress("localhost", 0)) + val server = ServerSocketChannel.open.bind(new InetSocketAddress("localhost", 0)) val executorService = Executors.newCachedThreadPool - try { - executorService.execute(new Runnable { - override def run: Unit = { - val server_ch = server.accept - val packer = MessagePack.newDefaultPacker(server_ch) - packer.packString("0123456789") - packer.flush - // Keep the connection open - while (!executorService.isShutdown) { - TimeUnit.SECONDS.sleep(1) - } - packer.close - } - }) - - val future = executorService.submit(new Callable[String] { - override def call: String = { - val conn_ch = SocketChannel.open(new InetSocketAddress("localhost", server.socket.getLocalPort)) - val unpacker = MessagePack.newDefaultUnpacker(conn_ch) - val s = unpacker.unpackString - unpacker.close - s - } - }) + try + executorService.execute( + new Runnable: + override def run: Unit = + val server_ch = server.accept + val packer = MessagePack.newDefaultPacker(server_ch) + packer.packString("0123456789") + packer.flush + // Keep the connection open + while !executorService.isShutdown do + TimeUnit.SECONDS.sleep(1) + packer.close + ) + + val future = executorService.submit( + new Callable[String]: + override def call: String = + val conn_ch = SocketChannel.open( + new InetSocketAddress("localhost", server.socket.getLocalPort) + ) + val unpacker = MessagePack.newDefaultUnpacker(conn_ch) + val s = unpacker.unpackString + unpacker.close + s + ) future.get(5, TimeUnit.SECONDS) shouldBe "0123456789" - } finally { + finally executorService.shutdown - if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) { + if !executorService.awaitTermination(5, TimeUnit.SECONDS) then executorService.shutdownNow - } - } + end try } } -} + +end MessageBufferInputTest diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala index ea9cde57e..5f6e9b7a3 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala @@ -17,34 +17,30 @@ package org.msgpack.core.buffer import wvlet.airspec.AirSpec -import java.io._ +import java.io.* -class MessageBufferOutputTest extends AirSpec { +class MessageBufferOutputTest extends AirSpec: - private def createTempFile = { + private def createTempFile = val f = File.createTempFile("msgpackTest", "msgpack") f.deleteOnExit f - } - private def createTempFileWithOutputStream = { + private def createTempFileWithOutputStream = val f = createTempFile val out = new FileOutputStream(f) (f, out) - } - private def createTempFileWithChannel = { + private def createTempFileWithChannel = val (f, out) = createTempFileWithOutputStream val ch = out.getChannel (f, ch) - } - private def writeIntToBuf(buf: MessageBufferOutput) = { + private def writeIntToBuf(buf: MessageBufferOutput) = val mb0 = buf.next(8) mb0.putInt(0, 42) buf.writeBuffer(4) buf.close - } test("OutputStreamBufferOutput") { test("reset buffer") { @@ -73,4 +69,5 @@ class MessageBufferOutputTest extends AirSpec { f1.length.toInt > 0 shouldBe true } } -} + +end MessageBufferOutputTest diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala index 03e93b891..36940473d 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala @@ -21,9 +21,10 @@ import wvlet.airspec.AirSpec import java.nio.ByteBuffer import scala.util.Random -/** Created on 2014/05/01. +/** + * Created on 2014/05/01. */ -class MessageBufferTest extends AirSpec with Benchmark { +class MessageBufferTest extends AirSpec with Benchmark: private val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] @@ -54,97 +55,87 @@ class MessageBufferTest extends AirSpec with Benchmark { val ub = MessageBuffer.allocate(M) val ud = - if (universal) MessageBuffer.wrap(ByteBuffer.allocate(M)) - else MessageBuffer.wrap(ByteBuffer.allocateDirect(M)) + if universal then + MessageBuffer.wrap(ByteBuffer.allocate(M)) + else + MessageBuffer.wrap(ByteBuffer.allocateDirect(M)) val hb = ByteBuffer.allocate(M) val db = ByteBuffer.allocateDirect(M) - def bench(f: Int => Unit): Unit = { + def bench(f: Int => Unit): Unit = var i = 0 - while (i < N) { + while i < N do f((i * 4) % M) i += 1 - } - } val r = new Random(0) val rs = new Array[Int](N) (0 until N).map(i => rs(i) = r.nextInt(N)) - def randomBench(f: Int => Unit): Unit = { + def randomBench(f: Int => Unit): Unit = var i = 0 - while (i < N) { + while i < N do f((rs(i) * 4) % M) i += 1 - } - } val rep = 3 info(f"Reading buffers (of size:${M}%,d) ${N}%,d x $rep times") time("sequential getInt", repeat = rep) { block("unsafe array") { var i = 0 - while (i < N) { + while i < N do ub.getInt((i * 4) % M) i += 1 - } } block("unsafe direct") { var i = 0 - while (i < N) { + while i < N do ud.getInt((i * 4) % M) i += 1 - } } block("allocate") { var i = 0 - while (i < N) { + while i < N do hb.getInt((i * 4) % M) i += 1 - } } block("allocateDirect") { var i = 0 - while (i < N) { + while i < N do db.getInt((i * 4) % M) i += 1 - } } } time("random getInt", repeat = rep) { block("unsafe array") { var i = 0 - while (i < N) { + while i < N do ub.getInt((rs(i) * 4) % M) i += 1 - } } block("unsafe direct") { var i = 0 - while (i < N) { + while i < N do ud.getInt((rs(i) * 4) % M) i += 1 - } } block("allocate") { var i = 0 - while (i < N) { + while i < N do hb.getInt((rs(i) * 4) % M) i += 1 - } } block("allocateDirect") { var i = 0 - while (i < N) { + while i < N do db.getInt((rs(i) * 4) % M) i += 1 - } } } } @@ -152,20 +143,21 @@ class MessageBufferTest extends AirSpec with Benchmark { private val builder = Seq.newBuilder[MessageBuffer] builder += MessageBuffer.allocate(10) builder += MessageBuffer.wrap(ByteBuffer.allocate(10)) - if (!universal) builder += MessageBuffer.wrap(ByteBuffer.allocateDirect(10)) + if !universal then + builder += MessageBuffer.wrap(ByteBuffer.allocateDirect(10)) + private val buffers = builder.result() test("convert to ByteBuffer") { - for (t <- buffers) { + for t <- buffers do val bb = t.sliceAsByteBuffer bb.position() shouldBe 0 bb.limit() shouldBe 10 bb.capacity shouldBe 10 - } } test("put ByteBuffer on itself") { - for (t <- buffers) { + for t <- buffers do val b = Array[Byte](0x02, 0x03) val srcArray = ByteBuffer.wrap(b) val srcHeap = ByteBuffer.allocate(b.length) @@ -173,7 +165,7 @@ class MessageBufferTest extends AirSpec with Benchmark { val srcOffHeap = ByteBuffer.allocateDirect(b.length) srcOffHeap.put(b).flip - for (src <- Seq(srcArray, srcHeap, srcOffHeap)) { + for src <- Seq(srcArray, srcHeap, srcOffHeap) do // Write header bytes val header = Array[Byte](0x00, 0x01) t.putBytes(0, header, 0, header.length) @@ -184,12 +176,10 @@ class MessageBufferTest extends AirSpec with Benchmark { t.getByte(1) shouldBe 0x01 t.getByte(2) shouldBe 0x02 t.getByte(3) shouldBe 0x03 - } - } } test("put MessageBuffer on itself") { - for (t <- buffers) { + for t <- buffers do val b = Array[Byte](0x02, 0x03) val srcArray = ByteBuffer.wrap(b) val srcHeap = ByteBuffer.allocate(b.length) @@ -198,9 +188,10 @@ class MessageBufferTest extends AirSpec with Benchmark { srcOffHeap.put(b).flip val builder = Seq.newBuilder[ByteBuffer] builder ++= Seq(srcArray, srcHeap) - if (!universal) builder += srcOffHeap + if !universal then + builder += srcOffHeap - for (src <- builder.result().map(d => MessageBuffer.wrap(d))) { + for src <- builder.result().map(d => MessageBuffer.wrap(d)) do // Write header bytes val header = Array[Byte](0x00, 0x01) t.putBytes(0, header, 0, header.length) @@ -211,23 +202,18 @@ class MessageBufferTest extends AirSpec with Benchmark { t.getByte(1) shouldBe 0x01 t.getByte(2) shouldBe 0x02 t.getByte(3) shouldBe 0x03 - } - } } test("copy sliced buffer") { - def prepareBytes: Array[Byte] = { - Array[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07) - } + def prepareBytes: Array[Byte] = Array[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07) - def prepareDirectBuffer: ByteBuffer = { + def prepareDirectBuffer: ByteBuffer = val directBuffer = ByteBuffer.allocateDirect(prepareBytes.length) directBuffer.put(prepareBytes) directBuffer.flip directBuffer - } - def checkSliceAndCopyTo(srcBuffer: MessageBuffer, dstBuffer: MessageBuffer) = { + def checkSliceAndCopyTo(srcBuffer: MessageBuffer, dstBuffer: MessageBuffer) = val sliced = srcBuffer.slice(2, 5) sliced.size() shouldBe 5 @@ -247,12 +233,17 @@ class MessageBufferTest extends AirSpec with Benchmark { dstBuffer.getByte(5) shouldBe 0x05 dstBuffer.getByte(6) shouldBe 0x06 dstBuffer.getByte(7) shouldBe 0x07 - } checkSliceAndCopyTo(MessageBuffer.wrap(prepareBytes), MessageBuffer.wrap(prepareBytes)) - checkSliceAndCopyTo(MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)), MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes))) - if (!universal) { - checkSliceAndCopyTo(MessageBuffer.wrap(prepareDirectBuffer), MessageBuffer.wrap(prepareDirectBuffer)) - } + checkSliceAndCopyTo( + MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)), + MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)) + ) + if !universal then + checkSliceAndCopyTo( + MessageBuffer.wrap(prepareDirectBuffer), + MessageBuffer.wrap(prepareDirectBuffer) + ) } -} + +end MessageBufferTest diff --git a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala index d0b0e08e8..1a1a3a3ca 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/example/MessagePackExampleTest.scala @@ -17,8 +17,9 @@ package org.msgpack.core.example import wvlet.airspec.AirSpec -/** */ -class MessagePackExampleTest extends AirSpec { +/** + */ +class MessagePackExampleTest extends AirSpec: test("example") { @@ -38,4 +39,3 @@ class MessagePackExampleTest extends AirSpec { MessagePackExample.configuration(); } } -} diff --git a/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala index fb340553c..73e1edc56 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/RawStringValueImplTest.scala @@ -17,7 +17,7 @@ package org.msgpack.value import wvlet.airspec.AirSpec -class RawStringValueImplTest extends AirSpec { +class RawStringValueImplTest extends AirSpec: test("return the same hash code if they are equal") { val str = "a" @@ -29,4 +29,3 @@ class RawStringValueImplTest extends AirSpec { a2 shouldBe a1 a2.hashCode shouldBe a1.hashCode } -} diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala index 3568ba5b9..623ca36da 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueFactoryTest.scala @@ -19,8 +19,9 @@ import org.scalacheck.Gen import wvlet.airspec.AirSpec import wvlet.airspec.spi.PropertyCheck -/** */ -class ValueFactoryTest extends AirSpec with PropertyCheck { +/** + */ +class ValueFactoryTest extends AirSpec with PropertyCheck: private def isValid( v: Value, @@ -37,7 +38,7 @@ class ValueFactoryTest extends AirSpec with PropertyCheck { isRaw: Boolean = false, isNumber: Boolean = false, isTimestamp: Boolean = false - ): Boolean = { + ): Boolean = v.isNilValue shouldBe isNil v.isBooleanValue shouldBe isBoolean v.isIntegerValue shouldBe isInteger @@ -51,7 +52,6 @@ class ValueFactoryTest extends AirSpec with PropertyCheck { v.isNumberValue shouldBe isNumber v.isTimestampValue shouldBe isTimestamp true - } test("ValueFactory") { test("nil") { @@ -66,24 +66,44 @@ class ValueFactoryTest extends AirSpec with PropertyCheck { test("int") { forAll { (v: Int) => - isValid(ValueFactory.newInteger(v), expected = ValueType.INTEGER, isInteger = true, isNumber = true) + isValid( + ValueFactory.newInteger(v), + expected = ValueType.INTEGER, + isInteger = true, + isNumber = true + ) } } test("float") { forAll { (v: Float) => - isValid(ValueFactory.newFloat(v), expected = ValueType.FLOAT, isFloat = true, isNumber = true) + isValid( + ValueFactory.newFloat(v), + expected = ValueType.FLOAT, + isFloat = true, + isNumber = true + ) } } test("string") { forAll { (v: String) => - isValid(ValueFactory.newString(v), expected = ValueType.STRING, isString = true, isRaw = true) + isValid( + ValueFactory.newString(v), + expected = ValueType.STRING, + isString = true, + isRaw = true + ) } } test("array") { forAll { (v: Array[Byte]) => - isValid(ValueFactory.newBinary(v), expected = ValueType.BINARY, isBinary = true, isRaw = true) + isValid( + ValueFactory.newBinary(v), + expected = ValueType.BINARY, + isBinary = true, + isRaw = true + ) } } @@ -97,13 +117,23 @@ class ValueFactoryTest extends AirSpec with PropertyCheck { test("ext") { forAll { (v: Array[Byte]) => - isValid(ValueFactory.newExtension(0, v), expected = ValueType.EXTENSION, isExtension = true, isRaw = false) + isValid( + ValueFactory.newExtension(0, v), + expected = ValueType.EXTENSION, + isExtension = true, + isRaw = false + ) } } test("timestamp") { forAll { (millis: Long) => - isValid(ValueFactory.newTimestamp(millis), expected = ValueType.EXTENSION, isExtension = true, isTimestamp = true) + isValid( + ValueFactory.newTimestamp(millis), + expected = ValueType.EXTENSION, + isExtension = true, + isTimestamp = true + ) } } @@ -111,8 +141,14 @@ class ValueFactoryTest extends AirSpec with PropertyCheck { val posLong = Gen.chooseNum[Long](-31557014167219200L, 31556889864403199L) val posInt = Gen.chooseNum(0, 1000000000 - 1) // NANOS_PER_SECOND forAll(posLong, posInt) { (sec: Long, nano: Int) => - isValid(ValueFactory.newTimestamp(sec, nano), expected = ValueType.EXTENSION, isExtension = true, isTimestamp = true) + isValid( + ValueFactory.newTimestamp(sec, nano), + expected = ValueType.EXTENSION, + isExtension = true, + isTimestamp = true + ) } } } -} + +end ValueFactoryTest diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala index 83cbde6bf..76e2ed27a 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala @@ -18,14 +18,17 @@ package org.msgpack.value import org.msgpack.core.MessagePackSpec.createMessagePackData import java.math.BigInteger -import org.msgpack.core._ +import org.msgpack.core.* import org.scalacheck.Prop.propBoolean import wvlet.airframe.json.JSON import wvlet.airspec.AirSpec import wvlet.airspec.spi.PropertyCheck -class ValueTest extends AirSpec with PropertyCheck { - private def checkSuccinctType(pack: MessagePacker => Unit, expectedAtMost: MessageFormat): Boolean = { +class ValueTest extends AirSpec with PropertyCheck: + private def checkSuccinctType( + pack: MessagePacker => Unit, + expectedAtMost: MessageFormat + ): Boolean = val b = createMessagePackData(pack) val v1 = MessagePack.newDefaultUnpacker(b).unpackValue() val mf = v1.asIntegerValue().mostSuccinctMessageFormat() @@ -39,7 +42,6 @@ class ValueTest extends AirSpec with PropertyCheck { mf2.ordinal() <= expectedAtMost.ordinal() shouldBe true true - } test("Value") { test("tell most succinct integer type") { @@ -61,14 +63,17 @@ class ValueTest extends AirSpec with PropertyCheck { forAll { (v: Long) => v > 0 ==> { // Create value between 2^63-1 < v <= 2^64-1 - checkSuccinctType(_.packBigInteger(BigInteger.valueOf(Long.MaxValue).add(BigInteger.valueOf(v))), MessageFormat.UINT64) + checkSuccinctType( + _.packBigInteger(BigInteger.valueOf(Long.MaxValue).add(BigInteger.valueOf(v))), + MessageFormat.UINT64 + ) } } } test("produce json strings") { - import ValueFactory._ + import ValueFactory.* newNil().toJson shouldBe "null" newNil().toString shouldBe "null" @@ -88,7 +93,8 @@ class ValueTest extends AirSpec with PropertyCheck { newArray(newInteger(0), newString("hello")).toJson shouldBe "[0,\"hello\"]" newArray(newInteger(0), newString("hello")).toString shouldBe "[0,\"hello\"]" - newArray(newArray(newString("Apple"), newFloat(0.2)), newNil()).toJson shouldBe """[["Apple",0.2],null]""" + newArray(newArray(newString("Apple"), newFloat(0.2)), newNil()).toJson shouldBe + """[["Apple",0.2],null]""" // Map value val m = newMapBuilder() @@ -112,7 +118,7 @@ class ValueTest extends AirSpec with PropertyCheck { } test("check appropriate range for integers") { - import ValueFactory._ + import ValueFactory.* import java.lang.Byte import java.lang.Short @@ -142,4 +148,5 @@ class ValueTest extends AirSpec with PropertyCheck { } } } -} + +end ValueTest diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala index fc81bdebd..7b992f28b 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala @@ -15,70 +15,59 @@ // package org.msgpack.value -import org.msgpack.core.MessagePack.Code._ +import org.msgpack.core.MessagePack.Code.* import org.msgpack.core.{MessageFormat, MessageFormatException} import wvlet.airspec.AirSpec -/** Created on 2014/05/06. +/** + * Created on 2014/05/06. */ -class ValueTypeTest extends AirSpec { +class ValueTypeTest extends AirSpec: test("lookup ValueType from a byte value") { - def check(b: Byte, tpe: ValueType): Unit = { - MessageFormat.valueOf(b).getValueType shouldBe tpe - } + def check(b: Byte, tpe: ValueType): Unit = MessageFormat.valueOf(b).getValueType shouldBe tpe - for (i <- 0 until 0x7f) { + for i <- 0 until 0x7f do check(i.toByte, ValueType.INTEGER) - } - for (i <- 0x80 until 0x8f) { + for i <- 0x80 until 0x8f do check(i.toByte, ValueType.MAP) - } - for (i <- 0x90 until 0x9f) { + for i <- 0x90 until 0x9f do check(i.toByte, ValueType.ARRAY) - } check(NIL, ValueType.NIL) - try { + try MessageFormat.valueOf(NEVER_USED).getValueType fail("NEVER_USED type should not have ValueType") - } catch { + catch case e: MessageFormatException => // OK - } check(TRUE, ValueType.BOOLEAN) check(FALSE, ValueType.BOOLEAN) - for (t <- Seq(BIN8, BIN16, BIN32)) { + for t <- Seq(BIN8, BIN16, BIN32) do check(t, ValueType.BINARY) - } - for (t <- Seq(FIXEXT1, FIXEXT2, FIXEXT4, FIXEXT8, FIXEXT16, EXT8, EXT16, EXT32)) { + for t <- Seq(FIXEXT1, FIXEXT2, FIXEXT4, FIXEXT8, FIXEXT16, EXT8, EXT16, EXT32) do check(t, ValueType.EXTENSION) - } - for (t <- Seq(INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64)) { + for t <- Seq(INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64) do check(t, ValueType.INTEGER) - } - for (t <- Seq(STR8, STR16, STR32)) { + for t <- Seq(STR8, STR16, STR32) do check(t, ValueType.STRING) - } - for (t <- Seq(FLOAT32, FLOAT64)) { + for t <- Seq(FLOAT32, FLOAT64) do check(t, ValueType.FLOAT) - } - for (t <- Seq(ARRAY16, ARRAY32)) { + for t <- Seq(ARRAY16, ARRAY32) do check(t, ValueType.ARRAY) - } - for (i <- 0xe0 until 0xff) { + for i <- 0xe0 until 0xff do check(i.toByte, ValueType.INTEGER) - } } -} + +end ValueTypeTest diff --git a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala index f9a1c2a0b..4eabdbd72 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala @@ -21,11 +21,12 @@ import wvlet.airspec.spi.PropertyCheck import java.time.Instant import java.util -import scala.jdk.CollectionConverters._ +import scala.jdk.CollectionConverters.* -/** */ -class VariableTest extends AirSpec with PropertyCheck { - private def check(pack: MessagePacker => Unit, checker: Variable => Unit): Unit = { +/** + */ +class VariableTest extends AirSpec with PropertyCheck: + private def check(pack: MessagePacker => Unit, checker: Variable => Unit): Unit = val packer = MessagePack.newDefaultBufferPacker() pack(packer) val msgpack = packer.toByteArray @@ -35,11 +36,11 @@ class VariableTest extends AirSpec with PropertyCheck { unpacker.unpackValue(v) checker(v) unpacker.close() - } - /** Test Value -> MsgPack -> Value + /** + * Test Value -> MsgPack -> Value */ - private def roundTrip(v: Value): Unit = { + private def roundTrip(v: Value): Unit = val packer = MessagePack.newDefaultBufferPacker() v.writeTo(packer) val msgpack = packer.toByteArray @@ -48,7 +49,6 @@ class VariableTest extends AirSpec with PropertyCheck { unpacker.close() v shouldBe v1 v.immutableValue() shouldBe v1 - } private def validateValue[V <: Value]( v: V, @@ -62,7 +62,7 @@ class VariableTest extends AirSpec with PropertyCheck { asMap: Boolean = false, asExtension: Boolean = false, asTimestamp: Boolean = false - ): V = { + ): V = v.isNilValue shouldBe asNil v.isBooleanValue shouldBe asBoolean v.isIntegerValue shouldBe asInteger @@ -76,203 +76,200 @@ class VariableTest extends AirSpec with PropertyCheck { v.isExtensionValue shouldBe asExtension | asTimestamp v.isTimestampValue shouldBe asTimestamp - if (asNil) { + if asNil then v.getValueType shouldBe ValueType.NIL roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asNilValue() } - } - if (asBoolean) { + if asBoolean then v.getValueType shouldBe ValueType.BOOLEAN roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asBooleanValue() } - } - if (asInteger) { + if asInteger then v.getValueType shouldBe ValueType.INTEGER roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asIntegerValue() } - } - if (asFloat) { + if asFloat then v.getValueType shouldBe ValueType.FLOAT roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asFloatValue() } - } - if (asBinary | asString) { + if asBinary | asString then v.asRawValue() roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asRawValue() } - } - if (asBinary) { + if asBinary then v.getValueType shouldBe ValueType.BINARY roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asBinaryValue() } - } - if (asString) { + if asString then v.getValueType shouldBe ValueType.STRING roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asStringValue() } - } - if (asArray) { + if asArray then v.getValueType shouldBe ValueType.ARRAY roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asArrayValue() } - } - if (asMap) { + if asMap then v.getValueType shouldBe ValueType.MAP roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asMapValue() } - } - if (asExtension) { + if asExtension then v.getValueType shouldBe ValueType.EXTENSION roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asExtensionValue() } - } - if (asTimestamp) { + if asTimestamp then v.getValueType shouldBe ValueType.EXTENSION roundTrip(v) - } else { + else intercept[MessageTypeCastException] { v.asTimestampValue() } - } v - } + + end validateValue test("Variable") { test("read nil") { check( _.packNil, - checker = { v => - val iv = validateValue(v.asNilValue(), asNil = true) - iv.toJson shouldBe "null" - } + checker = + v => + val iv = validateValue(v.asNilValue(), asNil = true) + iv.toJson shouldBe "null" ) } test("read integers") { - forAll { i: Int => - check( - _.packInt(i), - checker = { v => - val iv = validateValue(v.asIntegerValue(), asInteger = true) - iv.asInt() shouldBe i - iv.asLong() shouldBe i.toLong - } - ) + forAll { (i: Int) => + check( + _.packInt(i), + checker = + v => + val iv = validateValue(v.asIntegerValue(), asInteger = true) + iv.asInt() shouldBe i + iv.asLong() shouldBe i.toLong + ) } } test("read double") { - forAll { x: Double => - check( - _.packDouble(x), - checker = { v => - val iv = validateValue(v.asFloatValue(), asFloat = true) - // iv.toDouble shouldBe v - // iv.toFloat shouldBe x.toFloat - } - ) + forAll { (x: Double) => + check( + _.packDouble(x), + checker = + v => + val iv = validateValue(v.asFloatValue(), asFloat = true) + // iv.toDouble shouldBe v + // iv.toFloat shouldBe x.toFloat + ) } } test("read boolean") { - forAll { x: Boolean => - check( - _.packBoolean(x), - checker = { v => - val iv = validateValue(v.asBooleanValue(), asBoolean = true) - iv.getBoolean shouldBe x - } - ) + forAll { (x: Boolean) => + check( + _.packBoolean(x), + checker = + v => + val iv = validateValue(v.asBooleanValue(), asBoolean = true) + iv.getBoolean shouldBe x + ) } } test("read binary") { - forAll { x: Array[Byte] => + forAll { (x: Array[Byte]) => check( { packer => - packer.packBinaryHeader(x.length); packer.addPayload(x) + packer.packBinaryHeader(x.length); + packer.addPayload(x) }, - checker = { v => - val iv = validateValue(v.asBinaryValue(), asBinary = true) - util.Arrays.equals(iv.asByteArray(), x) - } + checker = + v => + val iv = validateValue(v.asBinaryValue(), asBinary = true) + util.Arrays.equals(iv.asByteArray(), x) ) } } test("read string") { - forAll { x: String => - check( - _.packString(x), - checker = { v => - val iv = validateValue(v.asStringValue(), asString = true) - iv.asString() shouldBe x - } - ) + forAll { (x: String) => + check( + _.packString(x), + checker = + v => + val iv = validateValue(v.asStringValue(), asString = true) + iv.asString() shouldBe x + ) } } test("read array") { - forAll { x: Seq[Int] => + forAll { (x: Seq[Int]) => check( { packer => packer.packArrayHeader(x.size) - x.foreach { packer.packInt(_) } + x.foreach { + packer.packInt(_) + } }, - checker = { v => - val iv = validateValue(v.asArrayValue(), asArray = true) - val lst = iv.list().asScala.map(_.asIntegerValue().toInt) - lst shouldBe x - } + checker = + v => + val iv = validateValue(v.asArrayValue(), asArray = true) + val lst = iv.list().asScala.map(_.asIntegerValue().toInt) + lst shouldBe x ) } } test("read map") { - forAll { x: Seq[Int] => + forAll { (x: Seq[Int]) => // Generate map with unique keys - val map = x.zipWithIndex.map { case (x, i) => (s"key-${i}", x) } + val map = x + .zipWithIndex + .map { case (x, i) => + (s"key-${i}", x) + } check( { packer => packer.packMapHeader(map.size) @@ -281,27 +278,32 @@ class VariableTest extends AirSpec with PropertyCheck { packer.packInt(x._2) } }, - checker = { v => - val iv = validateValue(v.asMapValue(), asMap = true) - val lst = iv.map().asScala.map(p => (p._1.asStringValue().asString(), p._2.asIntegerValue().asInt())).toSeq - lst.sortBy(_._1) shouldBe map.sortBy(_._1) - } + checker = + v => + val iv = validateValue(v.asMapValue(), asMap = true) + val lst = + iv.map() + .asScala + .map(p => (p._1.asStringValue().asString(), p._2.asIntegerValue().asInt())) + .toSeq + lst.sortBy(_._1) shouldBe map.sortBy(_._1) ) } } test("read timestamps") { - forAll { millis: Long => - val i = Instant.ofEpochMilli(millis) - check( - _.packTimestamp(i), - checker = { v => - val ts = validateValue(v.asTimestampValue(), asTimestamp = true) - ts.isTimestampValue shouldBe true - ts.toInstant shouldBe i - } - ) + forAll { (millis: Long) => + val i = Instant.ofEpochMilli(millis) + check( + _.packTimestamp(i), + checker = + v => + val ts = validateValue(v.asTimestampValue(), asTimestamp = true) + ts.isTimestampValue shouldBe true + ts.toInstant shouldBe i + ) } } } -} + +end VariableTest From 2bb48340b5159b96d14b8bb73fd293ce08ff89db Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 10:35:17 -0700 Subject: [PATCH 389/417] Upgrade Scala to 3.7.1 and use Scala 3 code format style (#899) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Upgrade Scala to 3.7.1 and update code format style - Upgrade Scala version from 2.13.12 to 3.7.1 in build.sbt - Update scalafmt.conf to use Scala 3 dialect and modern formatting rules - Fix Scala 3 compatibility issues in test files: - Update lambda syntax to use parentheses around parameters - Remove deprecated underscore suffix from function references - Apply Scala 3 formatting with scalafmt 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Update CLAUDE.md for Scala 3.7.1 and modern sbt syntax - Fix build command to use modern sbt syntax: Test / compile instead of test:compile - Update Scala version reference to 3.7.1 in testing structure - Update scalafmt configuration notes to reflect Scala 3 dialect and 100 char limit * Update CLAUDE.md to recommend latest Scala 3 version - Change specific version reference to 'always use the latest Scala 3 version' - This ensures the documentation remains current as new Scala 3 versions are released * Update README.md for modern sbt syntax and Scala 3 - Fix sbt command syntax: change test:compile to 'Test / compile' - Add note about Scala 3 dialect and latest version recommendation - Ensure developer documentation matches current project configuration * Update scalafmtAll command description - Change comment from 'Format Scala test code' to 'Format all Scala and sbt code' - More accurately reflects what scalafmtAll does (formats all Scala files, not just tests) - Apply change to both README.md and CLAUDE.md for consistency --------- Co-authored-by: Claude --- .scalafmt.conf | 2 +- CLAUDE.md | 8 +- README.md | 5 +- .../org/msgpack/core/MessagePackTest.scala | 6 +- .../org/msgpack/core/MessagePackerTest.scala | 2 +- .../msgpack/core/MessageUnpackerTest.scala | 10 +-- .../org/msgpack/value/VariableTest.scala | 80 +++++++++---------- 7 files changed, 57 insertions(+), 56 deletions(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index fcadd98d4..e8563bafe 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = 3.9.4 +version = 3.9.8 project.layout = StandardConvention runner.dialect = scala3 maxColumn = 100 diff --git a/CLAUDE.md b/CLAUDE.md index e01643b59..2e72e982e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,7 +13,7 @@ MessagePack-Java is a binary serialization library that provides a fast and comp ### Build and Compile ```bash ./sbt compile # Compile source code -./sbt test:compile # Compile source and test code +./sbt "Test / compile" # Compile source and test code ./sbt package # Create JAR files ``` @@ -31,7 +31,7 @@ MessagePack-Java is a binary serialization library that provides a fast and comp ### Code Quality ```bash ./sbt jcheckStyle # Run checkstyle (Facebook Presto style) -./sbt scalafmtAll # Format Scala test code +./sbt scalafmtAll # Format all Scala and sbt code ``` ### Publishing @@ -66,7 +66,7 @@ The msgpack-jackson module provides: - Extension type support including timestamps ### Testing Structure -- **msgpack-core tests**: Written in Scala using AirSpec framework +- **msgpack-core tests**: Written in Scala (always use the latest Scala 3 version) using AirSpec framework - Location: `msgpack-core/src/test/scala/` - **msgpack-jackson tests**: Written in Java using JUnit - Location: `msgpack-jackson/src/test/java/` @@ -81,7 +81,7 @@ For JDK 17+ compatibility, these options are automatically added: ## Code Style Requirements - Java code follows Facebook Presto style (enforced by checkstyle) -- Scala test code uses Scalafmt with 180 character line limit +- Scala test code uses Scalafmt with Scala 3 dialect and 100 character line limit - Checkstyle runs automatically during compilation - No external dependencies allowed in msgpack-core diff --git a/README.md b/README.md index 34a3f277a..54d1877a6 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ msgpack-java uses [sbt](http://www.scala-sbt.org/) for building the projects. Fo Coding style * msgpack-java uses [the same coding style](https://github.com/airlift/codestyle) with Facebook Presto * [IntelliJ setting file](https://raw.githubusercontent.com/airlift/codestyle/master/IntelliJIdea14/Airlift.xml) + * Scala test code uses Scalafmt with Scala 3 dialect (always use the latest Scala 3 version) ### Basic sbt commands Enter the sbt console: @@ -76,14 +77,14 @@ $ ./sbt Here is a list of sbt commands for daily development: ``` > ~compile # Compile source codes -> ~test:compile # Compile both source and test codes +> ~"Test / compile" # Compile both source and test codes > ~test # Run tests upon source code change > ~testOnly *MessagePackTest # Run tests in the specified class > ~testOnly *MessagePackTest -- (pattern) # Run tests matching the pattern > project msgpack-core # Focus on a specific project > package # Create a jar file in the target folder of each project > jcheckStyle # Run check style -> scalafmtAll # Reformat code +> scalafmtAll # Format all Scala and sbt code ``` ### Publishing diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 0a4328d8d..b55413934 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -376,7 +376,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark: test("report errors when packing/unpacking malformed strings") { pending("We need to produce malformed utf-8 strings in Java 8") // Create 100 malformed UTF8 Strings - val r = new Random(0) + val r = new Random(0) val malformedStrings = Iterator .continually { val b = new Array[Byte](10) @@ -580,12 +580,12 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark: kvs .grouped(2) - .map((kvp: Array[Value]) => + .map { (kvp: Array[Value]) => val k = kvp(0) val v = kvp(1) (k.asStringValue().asString, v.asStringValue().asString) - ) + } .toMap } .toList diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index c1b4b0a46..7ff5d82ee 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -211,7 +211,7 @@ class MessagePackerTest extends AirSpec with Benchmark: } test("compute totalWrittenBytes") { - val out = new ByteArrayOutputStream + val out = new ByteArrayOutputStream val packerTotalWrittenBytes = withResource(MessagePack.newDefaultPacker(out)) { packer => packer diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index ae25d2845..adab47089 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -30,7 +30,7 @@ import scala.util.Random object MessageUnpackerTest: class SplitMessageBufferInput(array: Array[Array[Byte]]) extends MessageBufferInput: - var cursor = 0 + var cursor = 0 override def next(): MessageBuffer = if cursor < array.length then val a = array(cursor) @@ -45,7 +45,7 @@ import org.msgpack.core.MessageUnpackerTest.* class MessageUnpackerTest extends AirSpec with Benchmark: - private val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] + private val universal = MessageBuffer.allocate(0).isInstanceOf[MessageBufferU] private def testData: Array[Byte] = val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) @@ -435,7 +435,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark: val t = time("skip performance", repeat = N) { block("v6") { - val v6 = new org.msgpack.MessagePack() + val v6 = new org.msgpack.MessagePack() val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(data)) var count = 0 @@ -567,7 +567,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark: val t = time("unpack performance", repeat = N) { block("v6") { - val v6 = new org.msgpack.MessagePack() + val v6 = new org.msgpack.MessagePack() val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(data)) var count = 0 @@ -655,7 +655,7 @@ class MessageUnpackerTest extends AirSpec with Benchmark: time("unpackBinary", repeat = 100) { block("v6") { - val v6 = new org.msgpack.MessagePack() + val v6 = new org.msgpack.MessagePack() val unpacker = new org.msgpack.unpacker.MessagePackUnpacker(v6, new ByteArrayInputStream(b)) var i = 0 diff --git a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala index 4eabdbd72..2f3cbf9c8 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala @@ -181,39 +181,39 @@ class VariableTest extends AirSpec with PropertyCheck: test("read integers") { forAll { (i: Int) => - check( - _.packInt(i), - checker = - v => - val iv = validateValue(v.asIntegerValue(), asInteger = true) - iv.asInt() shouldBe i - iv.asLong() shouldBe i.toLong - ) + check( + _.packInt(i), + checker = + v => + val iv = validateValue(v.asIntegerValue(), asInteger = true) + iv.asInt() shouldBe i + iv.asLong() shouldBe i.toLong + ) } } test("read double") { forAll { (x: Double) => - check( - _.packDouble(x), - checker = - v => - val iv = validateValue(v.asFloatValue(), asFloat = true) - // iv.toDouble shouldBe v - // iv.toFloat shouldBe x.toFloat - ) + check( + _.packDouble(x), + checker = + v => + val iv = validateValue(v.asFloatValue(), asFloat = true) + // iv.toDouble shouldBe v + // iv.toFloat shouldBe x.toFloat + ) } } test("read boolean") { forAll { (x: Boolean) => - check( - _.packBoolean(x), - checker = - v => - val iv = validateValue(v.asBooleanValue(), asBoolean = true) - iv.getBoolean shouldBe x - ) + check( + _.packBoolean(x), + checker = + v => + val iv = validateValue(v.asBooleanValue(), asBoolean = true) + iv.getBoolean shouldBe x + ) } } @@ -234,13 +234,13 @@ class VariableTest extends AirSpec with PropertyCheck: test("read string") { forAll { (x: String) => - check( - _.packString(x), - checker = - v => - val iv = validateValue(v.asStringValue(), asString = true) - iv.asString() shouldBe x - ) + check( + _.packString(x), + checker = + v => + val iv = validateValue(v.asStringValue(), asString = true) + iv.asString() shouldBe x + ) } } @@ -280,7 +280,7 @@ class VariableTest extends AirSpec with PropertyCheck: }, checker = v => - val iv = validateValue(v.asMapValue(), asMap = true) + val iv = validateValue(v.asMapValue(), asMap = true) val lst = iv.map() .asScala @@ -293,15 +293,15 @@ class VariableTest extends AirSpec with PropertyCheck: test("read timestamps") { forAll { (millis: Long) => - val i = Instant.ofEpochMilli(millis) - check( - _.packTimestamp(i), - checker = - v => - val ts = validateValue(v.asTimestampValue(), asTimestamp = true) - ts.isTimestampValue shouldBe true - ts.toInstant shouldBe i - ) + val i = Instant.ofEpochMilli(millis) + check( + _.packTimestamp(i), + checker = + v => + val ts = validateValue(v.asTimestampValue(), asTimestamp = true) + ts.isTimestampValue shouldBe true + ts.toInstant shouldBe i + ) } } } From fe697bc1b401d0ed2e5da77f6164f1c138647351 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 10:40:59 -0700 Subject: [PATCH 390/417] Update README.md publishing instructions for Sonatype Central (#900) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove references to deprecated sbt-sonatype plugin - Update credentials setup to use new Sonatype Central format - Replace sonatypeBundleRelease with sonaRelease command - Add environment variable alternative for credentials - Update host from oss.sonatype.org to central.sonatype.com 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude --- README.md | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 54d1877a6..f23af0b77 100644 --- a/README.md +++ b/README.md @@ -108,27 +108,38 @@ A new release note will be generated automatically at the [GitHub Releases](http #### Publishing to Sonatype from Local Machine -If you need to publish to Maven central using a local machine, you need to configure [sbt-sonatype](https://github.com/xerial/sbt-sonatype) plugin. First set Sonatype account information (user name and password) in the global sbt settings. To protect your password, never include this file in your project. +If you need to publish to Maven central using a local machine, you need to configure credentials for Sonatype Central. First set Sonatype account information (user name and password) in the global sbt settings. To protect your password, never include this file in your project. -___$HOME/.sbt/(sbt-version)/sonatype.sbt___ +___$HOME/.sbt/1.0/credentials.sbt___ ``` -credentials += Credentials("Sonatype Nexus Repository Manager", - "oss.sonatype.org", - "(Sonatype user name)", - "(Sonatype password)") +credentials += Credentials(Path.userHome / ".sbt" / "sonatype_central_credentials") +``` + +Then create a credentials file at `~/.sbt/sonatype_central_credentials`: + +``` +host=central.sonatype.com +user= +password= +``` + +Alternatively, you can use environment variables: +```bash +export SONATYPE_USERNAME= +export SONATYPE_PASSWORD= ``` You may also need to configure GPG. See the instruction in [sbt-pgp](https://github.com/sbt/sbt-pgp). -Then, run `publishedSigned` followed by `sonatypeBundleRelease`: +Then, run `publishSigned` followed by `sonaRelease`: ``` # [optional] When you need to perform the individual release steps manually, use the following commands: > publishSigned # Publish GPG signed artifacts to the Sonatype repository -> sonatypeBundleRelease # Publish to the Maven Central (It will be synched within less than 4 hours) +> sonaRelease # Publish to the Maven Central (It will be synched within less than 4 hours) ``` -If some sporadic error happens (e.g., Sonatype timeout), rerun `sonatypeBundleRelease` again. +If some sporadic error happens (e.g., Sonatype timeout), rerun `sonaRelease` again. ### Project Structure From 4e6458a23978c91c74ffa843e7692b5e75b40b3a Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 10:45:17 -0700 Subject: [PATCH 391/417] Skip CI tests for non-code changes using dorny/paths-filter (#901) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add dorny/paths-filter action to detect file changes - Skip code format and test jobs when only docs are changed - Improve CI efficiency by running tests only when needed 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude --- .github/workflows/CI.yml | 43 ++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 31f824e4b..11c3501b8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,27 +2,42 @@ name: CI on: pull_request: - paths: - - '**.scala' - - '**.java' - - '**.sbt' - - '.github/workflows/**.yml' - - 'project/build.properties' push: branches: - main - paths: - - '**.scala' - - '**.java' - - '**.sbt' - - '.github/workflows/**.yml' - - 'project/build.properties' - workflow_dispatch: + workflow_dispatch: jobs: + changes: + runs-on: ubuntu-latest + outputs: + code: ${{ steps.changes.outputs.code }} + docs: ${{ steps.changes.outputs.docs }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + code: + - '**.scala' + - '**.java' + - '**.sbt' + - '.github/workflows/**.yml' + - 'project/build.properties' + - 'msgpack-core/**' + - 'msgpack-jackson/**' + docs: + - '**.md' + - '**.txt' + - 'LICENSE' + code_format: name: Code Format runs-on: ubuntu-latest + needs: changes + if: ${{ needs.changes.outputs.code == 'true' }} steps: - uses: actions/checkout@v4 - name: jcheckstyle @@ -31,6 +46,8 @@ jobs: test: name: Test JDK${{ matrix.java }} runs-on: ubuntu-latest + needs: changes + if: ${{ needs.changes.outputs.code == 'true' }} strategy: matrix: java: ['8', '11', '17', '21', '24'] From a08b9eb295c6fdfd203bb8346a3f4b955df3dfd1 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 19 Jul 2025 19:58:41 +0200 Subject: [PATCH 392/417] Update jackson-databind to 2.18.4 (#886) * Update jackson-databind to 2.18.4 * Update build.sbt --------- Co-authored-by: Taro L. Saito --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3d6ba3202..135145fdd 100644 --- a/build.sbt +++ b/build.sbt @@ -133,7 +133,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.18.2", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.18.4", junitJupiter, junitVintage, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" From 3021550c18f65985db7ea2e0fd12339d0c75fd1e Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 11:02:02 -0700 Subject: [PATCH 393/417] Add scalafmtCheckAll to code format CI (#902) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures Scala code formatting is validated in CI alongside Java checkstyle. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude --- .github/workflows/CI.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 11c3501b8..4c49c411d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -42,6 +42,8 @@ jobs: - uses: actions/checkout@v4 - name: jcheckstyle run: ./sbt jcheckStyle + - name: scalafmtCheckAll + run: ./sbt scalafmtCheckAll test: name: Test JDK${{ matrix.java }} From 799e2d188b13b07704d1708d4e10283fe6dfdc8f Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sat, 19 Jul 2025 12:40:06 -0700 Subject: [PATCH 394/417] Fix Jackson deprecation warnings in MessagePackFactory (#903) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix Jackson deprecation warnings in MessagePackFactory Replace deprecated _createContext(Object, boolean) calls with _createContext(ContentReference, boolean) to eliminate warnings when running tests with Jackson 2.18.4. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Fix Jackson deprecation warnings in MessagePackParserTest Replace deprecated JsonParser methods with their current equivalents: - getCurrentName() → currentName() - getTokenLocation() → currentTokenLocation() - getCurrentLocation() → currentLocation() 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Fix all remaining Jackson deprecation warnings - Replace deprecated ParserMinimalBase constructor with StreamReadConstraints - Add non-deprecated location methods (currentTokenLocation, currentLocation) - Update GeneratorBase constructor to use 4-parameter form with IOContext and JsonWriteContext - Add new createKeySerializer method signature for Jackson 2.18 - Keep deprecated methods for backward compatibility All tests pass and Jackson deprecation warnings are eliminated. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --------- Co-authored-by: Claude --- .../dataformat/MessagePackFactory.java | 5 ++- .../dataformat/MessagePackGenerator.java | 10 ++++- .../jackson/dataformat/MessagePackParser.java | 21 ++++++++-- .../MessagePackSerializerFactory.java | 9 +++++ .../dataformat/MessagePackParserTest.java | 38 +++++++++---------- 5 files changed, 57 insertions(+), 26 deletions(-) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index dbd2a4658..865c0cf4d 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.io.ContentReference; import com.fasterxml.jackson.core.io.IOContext; import org.msgpack.core.MessagePack; import org.msgpack.core.annotations.VisibleForTesting; @@ -111,7 +112,7 @@ public JsonGenerator createGenerator(Writer w) public JsonParser createParser(byte[] data) throws IOException { - IOContext ioContext = _createContext(data, false); + IOContext ioContext = _createContext(ContentReference.rawReference(data), false); return _createParser(data, 0, data.length, ioContext); } @@ -119,7 +120,7 @@ public JsonParser createParser(byte[] data) public JsonParser createParser(InputStream in) throws IOException { - IOContext ioContext = _createContext(in, false); + IOContext ioContext = _createContext(ContentReference.rawReference(in), false); return _createParser(in, ioContext); } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index abb5089e9..3dde5604d 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -19,7 +19,11 @@ import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.base.GeneratorBase; +import com.fasterxml.jackson.core.io.ContentReference; +import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.io.SerializedString; +import com.fasterxml.jackson.core.json.JsonWriteContext; +import com.fasterxml.jackson.core.util.BufferRecycler; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; import org.msgpack.core.annotations.Nullable; @@ -185,6 +189,7 @@ else if (value instanceof NodeArray) { } // This is an internal constructor for nested serialization. + @SuppressWarnings("deprecation") private MessagePackGenerator( int features, ObjectCodec codec, @@ -192,7 +197,7 @@ private MessagePackGenerator( MessagePack.PackerConfig packerConfig, boolean supportIntegerKeys) { - super(features, codec); + super(features, codec, new IOContext(new BufferRecycler(), ContentReference.rawReference(out), false), JsonWriteContext.createRootContext(null)); this.output = out; this.messagePacker = packerConfig.newPacker(out); this.packerConfig = packerConfig; @@ -200,6 +205,7 @@ private MessagePackGenerator( this.supportIntegerKeys = supportIntegerKeys; } + @SuppressWarnings("deprecation") public MessagePackGenerator( int features, ObjectCodec codec, @@ -209,7 +215,7 @@ public MessagePackGenerator( boolean supportIntegerKeys) throws IOException { - super(features, codec); + super(features, codec, new IOContext(new BufferRecycler(), ContentReference.rawReference(out), false), JsonWriteContext.createRootContext(null)); this.output = out; this.messagePacker = packerConfig.newPacker(getMessageBufferOutputForOutputStream(out, reuseResourceInGenerator)); this.packerConfig = packerConfig; diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index e59b7f57c..72aeed205 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -106,7 +106,7 @@ private MessagePackParser(IOContext ctxt, boolean reuseResourceInParser) throws IOException { - super(features); + super(features, ctxt.streamReadConstraints()); this.codec = objectCodec; ioContext = ctxt; @@ -583,15 +583,29 @@ public JsonStreamContext getParsingContext() } @Override + public JsonLocation currentTokenLocation() + { + return new JsonLocation(ioContext.contentReference(), tokenPosition, -1, -1); + } + + @Override + public JsonLocation currentLocation() + { + return new JsonLocation(ioContext.contentReference(), currentPosition, -1, -1); + } + + @Override + @Deprecated public JsonLocation getTokenLocation() { - return new JsonLocation(ioContext.getSourceReference(), tokenPosition, -1, -1, (int) tokenPosition); + return currentTokenLocation(); } @Override + @Deprecated public JsonLocation getCurrentLocation() { - return new JsonLocation(ioContext.getSourceReference(), currentPosition, -1, -1, (int) currentPosition); + return currentLocation(); } @Override @@ -627,6 +641,7 @@ public boolean isCurrentFieldId() } @Override + @Deprecated public String getCurrentName() throws IOException { diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializerFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializerFactory.java index fa2148dc0..4100ef4cc 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializerFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackSerializerFactory.java @@ -16,8 +16,10 @@ package org.msgpack.jackson.dataformat; import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig; import com.fasterxml.jackson.databind.ser.BeanSerializerFactory; @@ -43,6 +45,13 @@ public MessagePackSerializerFactory(SerializerFactoryConfig config) } @Override + public JsonSerializer createKeySerializer(SerializerProvider prov, JavaType keyType, JsonSerializer defaultImpl) throws JsonMappingException + { + return new MessagePackKeySerializer(); + } + + @Override + @Deprecated public JsonSerializer createKeySerializer(SerializationConfig config, JavaType keyType, JsonSerializer defaultImpl) { return new MessagePackKeySerializer(); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index c0bab053e..256c43321 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -317,43 +317,43 @@ public void testMessagePackParserDirectly() JsonToken jsonToken = parser.nextToken(); assertEquals(JsonToken.START_OBJECT, jsonToken); - assertEquals(-1, parser.getTokenLocation().getLineNr()); - assertEquals(0, parser.getTokenLocation().getColumnNr()); - assertEquals(-1, parser.getCurrentLocation().getLineNr()); - assertEquals(1, parser.getCurrentLocation().getColumnNr()); + assertEquals(-1, parser.currentTokenLocation().getLineNr()); + assertEquals(0, parser.currentTokenLocation().getColumnNr()); + assertEquals(-1, parser.currentLocation().getLineNr()); + assertEquals(1, parser.currentLocation().getColumnNr()); jsonToken = parser.nextToken(); assertEquals(JsonToken.FIELD_NAME, jsonToken); - assertEquals("zero", parser.getCurrentName()); - assertEquals(1, parser.getTokenLocation().getColumnNr()); - assertEquals(6, parser.getCurrentLocation().getColumnNr()); + assertEquals("zero", parser.currentName()); + assertEquals(1, parser.currentTokenLocation().getColumnNr()); + assertEquals(6, parser.currentLocation().getColumnNr()); jsonToken = parser.nextToken(); assertEquals(JsonToken.VALUE_NUMBER_INT, jsonToken); assertEquals(0, parser.getIntValue()); - assertEquals(6, parser.getTokenLocation().getColumnNr()); - assertEquals(7, parser.getCurrentLocation().getColumnNr()); + assertEquals(6, parser.currentTokenLocation().getColumnNr()); + assertEquals(7, parser.currentLocation().getColumnNr()); jsonToken = parser.nextToken(); assertEquals(JsonToken.FIELD_NAME, jsonToken); - assertEquals("one", parser.getCurrentName()); - assertEquals(7, parser.getTokenLocation().getColumnNr()); - assertEquals(11, parser.getCurrentLocation().getColumnNr()); + assertEquals("one", parser.currentName()); + assertEquals(7, parser.currentTokenLocation().getColumnNr()); + assertEquals(11, parser.currentLocation().getColumnNr()); parser.overrideCurrentName("two"); - assertEquals("two", parser.getCurrentName()); + assertEquals("two", parser.currentName()); jsonToken = parser.nextToken(); assertEquals(JsonToken.VALUE_NUMBER_FLOAT, jsonToken); assertEquals(1.0f, parser.getIntValue(), 0.001f); - assertEquals(11, parser.getTokenLocation().getColumnNr()); - assertEquals(16, parser.getCurrentLocation().getColumnNr()); + assertEquals(11, parser.currentTokenLocation().getColumnNr()); + assertEquals(16, parser.currentLocation().getColumnNr()); jsonToken = parser.nextToken(); assertEquals(JsonToken.END_OBJECT, jsonToken); - assertEquals(-1, parser.getTokenLocation().getLineNr()); - assertEquals(16, parser.getTokenLocation().getColumnNr()); - assertEquals(-1, parser.getCurrentLocation().getLineNr()); - assertEquals(16, parser.getCurrentLocation().getColumnNr()); + assertEquals(-1, parser.currentTokenLocation().getLineNr()); + assertEquals(16, parser.currentTokenLocation().getColumnNr()); + assertEquals(-1, parser.currentLocation().getLineNr()); + assertEquals(16, parser.currentLocation().getColumnNr()); parser.close(); parser.close(); // Intentional From 34c1d590ad1cbebd234415de6f01460ee03aa5cb Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 25 Aug 2025 20:10:06 +0200 Subject: [PATCH 395/417] Update sbt, scripted-plugin to 1.11.4 (#910) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 138bc7a55..aced30652 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.11.3 +sbt.version=1.11.4 From d8d81aa32c3ac92849291c14bd1000b2fc6bb275 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 11:10:15 -0700 Subject: [PATCH 396/417] Bump actions/checkout from 4 to 5 (#909) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 6 +++--- .github/workflows/release.yml | 2 +- .github/workflows/snapshot.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 4c49c411d..a61fb3fad 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -15,7 +15,7 @@ jobs: docs: ${{ steps.changes.outputs.docs }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - uses: dorny/paths-filter@v3 id: changes with: @@ -39,7 +39,7 @@ jobs: needs: changes if: ${{ needs.changes.outputs.code == 'true' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: jcheckstyle run: ./sbt jcheckStyle - name: scalafmtCheckAll @@ -54,7 +54,7 @@ jobs: matrix: java: ['8', '11', '17', '21', '24'] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-java@v4 with: distribution: 'zulu' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c3dca7c26..6d1aa99f1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: name: Release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 4cc858660..eac8cfbb0 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -16,7 +16,7 @@ jobs: name: Publish snapshots runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version From 75482c5aec6bfafad7e17ce4e75c7abff682eec8 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 25 Aug 2025 20:10:50 +0200 Subject: [PATCH 397/417] Update airframe-json, airspec to 2025.1.16 (#912) --- build.sbt | 184 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 107 insertions(+), 77 deletions(-) diff --git a/build.sbt b/build.sbt index 135145fdd..547e1ebe5 100644 --- a/build.sbt +++ b/build.sbt @@ -1,11 +1,9 @@ Global / onChangedBuildSource := ReloadOnSourceChanges // For performance testing, ensure each test run one-by-one -Global / concurrentRestrictions := Seq( - Tags.limit(Tags.Test, 1) -) +Global / concurrentRestrictions := Seq(Tags.limit(Tags.Test, 1)) -val AIRFRAME_VERSION = "2025.1.14" +val AIRFRAME_VERSION = "2025.1.16" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true @@ -15,37 +13,65 @@ ThisBuild / dynverSeparator := "-" // Publishing metadata ThisBuild / homepage := Some(url("https://msgpack.org/")) ThisBuild / licenses := Seq("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")) -ThisBuild / scmInfo := Some( - ScmInfo( - url("https://github.com/msgpack/msgpack-java"), - "scm:git@github.com:msgpack/msgpack-java.git" +ThisBuild / scmInfo := + Some( + ScmInfo( + url("https://github.com/msgpack/msgpack-java"), + "scm:git@github.com:msgpack/msgpack-java.git" + ) ) -) -ThisBuild / developers := List( - Developer(id = "frsyuki", name = "Sadayuki Furuhashi", email = "frsyuki@users.sourceforge.jp", url = url("https://github.com/frsyuki")), - Developer(id = "muga", name = "Muga Nishizawa", email = "muga.nishizawa@gmail.com", url = url("https://github.com/muga")), - Developer(id = "oza", name = "Tsuyoshi Ozawa", email = "ozawa.tsuyoshi@gmail.com", url = url("https://github.com/oza")), - Developer(id = "komamitsu", name = "Mitsunori Komatsu", email = "komamitsu@gmail.com", url = url("https://github.com/komamitsu")), - Developer(id = "xerial", name = "Taro L. Saito", email = "leo@xerial.org", url = url("https://github.com/xerial")) -) +ThisBuild / developers := + List( + Developer( + id = "frsyuki", + name = "Sadayuki Furuhashi", + email = "frsyuki@users.sourceforge.jp", + url = url("https://github.com/frsyuki") + ), + Developer( + id = "muga", + name = "Muga Nishizawa", + email = "muga.nishizawa@gmail.com", + url = url("https://github.com/muga") + ), + Developer( + id = "oza", + name = "Tsuyoshi Ozawa", + email = "ozawa.tsuyoshi@gmail.com", + url = url("https://github.com/oza") + ), + Developer( + id = "komamitsu", + name = "Mitsunori Komatsu", + email = "komamitsu@gmail.com", + url = url("https://github.com/komamitsu") + ), + Developer( + id = "xerial", + name = "Taro L. Saito", + email = "leo@xerial.org", + url = url("https://github.com/xerial") + ) + ) -val buildSettings = Seq[Setting[_]]( - organization := "org.msgpack", - organizationName := "MessagePack", +val buildSettings = Seq[Setting[?]]( + organization := "org.msgpack", + organizationName := "MessagePack", organizationHomepage := Some(url("http://msgpack.org/")), - description := "MessagePack for Java", - scalaVersion := "3.7.1", - Test / logBuffered := false, + description := "MessagePack for Java", + scalaVersion := "3.7.1", + Test / logBuffered := false, // msgpack-java should be a pure-java library, so remove Scala specific configurations - autoScalaLibrary := false, - crossPaths := false, + autoScalaLibrary := false, + crossPaths := false, publishMavenStyle := true, // JVM options for building scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-feature"), Test / javaOptions ++= Seq("-ea"), javacOptions ++= Seq("-source", "1.8", "-target", "1.8"), - Compile / compile / javacOptions ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation"), + Compile / compile / javacOptions ++= + Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation"), // Use lenient validation mode when generating Javadoc (for Java8) doc / javacOptions := { val opts = Seq("-source", "1.8") @@ -58,17 +84,21 @@ val buildSettings = Seq[Setting[_]]( // Add sonatype repository settings publishTo := { val centralSnapshots = "https://central.sonatype.com/repository/maven-snapshots/" - if (isSnapshot.value) Some("central-snapshots" at centralSnapshots) - else localStaging.value + if (isSnapshot.value) + Some("central-snapshots" at centralSnapshots) + else + localStaging.value }, // Style check config: (sbt-jchekcstyle) jcheckStyleConfig := "facebook", // Run jcheckstyle both for main and test codes - Compile / compile := ((Compile / compile) dependsOn (Compile / jcheckStyle)).value, - Test / compile := ((Test / compile) dependsOn (Test / jcheckStyle)).value + Compile / compile := + ((Compile / compile) dependsOn (Compile / jcheckStyle)).value, + Test / compile := + ((Test / compile) dependsOn (Test / jcheckStyle)).value ) -val junitJupiter = "org.junit.jupiter" % "junit-jupiter" % "5.11.4" % "test" +val junitJupiter = "org.junit.jupiter" % "junit-jupiter" % "5.11.4" % "test" val junitVintage = "org.junit.vintage" % "junit-vintage-engine" % "5.11.4" % "test" // Project settings @@ -77,8 +107,8 @@ lazy val root = Project(id = "msgpack-java", base = file(".")) buildSettings, // Do not publish the root project publishArtifact := false, - publish := {}, - publishLocal := {} + publish := {}, + publishLocal := {} ) .aggregate(msgpackCore, msgpackJackson) @@ -86,58 +116,58 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) .enablePlugins(SbtOsgi) .settings( buildSettings, - description := "Core library of the MessagePack for Java", + description := "Core library of the MessagePack for Java", OsgiKeys.bundleSymbolicName := "org.msgpack.msgpack-core", - OsgiKeys.exportPackage := Seq( - // TODO enumerate used packages automatically - "org.msgpack.core", - "org.msgpack.core.annotations", - "org.msgpack.core.buffer", - "org.msgpack.value", - "org.msgpack.value.impl" - ), + OsgiKeys.exportPackage := + Seq( + // TODO enumerate used packages automatically + "org.msgpack.core", + "org.msgpack.core.annotations", + "org.msgpack.core.buffer", + "org.msgpack.value", + "org.msgpack.value.impl" + ), testFrameworks += new TestFramework("wvlet.airspec.Framework"), - Test / javaOptions ++= Seq( - // --add-opens is not available in JDK8 - "-XX:+IgnoreUnrecognizedVMOptions", - "--add-opens=java.base/java.nio=ALL-UNNAMED", - "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED" - ), + Test / javaOptions ++= + Seq( + // --add-opens is not available in JDK8 + "-XX:+IgnoreUnrecognizedVMOptions", + "--add-opens=java.base/java.nio=ALL-UNNAMED", + "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED" + ), Test / fork := true, - libraryDependencies ++= Seq( - // msgpack-core should have no external dependencies - junitJupiter, - junitVintage, - "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", - "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", - // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.18.1" % "test", - // For performance comparison with msgpack v6 - "org.msgpack" % "msgpack" % "0.6.12" % "test", - // For integration test with Akka - "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.13.0" % "test" - ) + libraryDependencies ++= + Seq( + // msgpack-core should have no external dependencies + junitJupiter, + junitVintage, + "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", + "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", + // Add property testing support with forAll methods + "org.scalacheck" %% "scalacheck" % "1.18.1" % "test", + // For performance comparison with msgpack v6 + "org.msgpack" % "msgpack" % "0.6.12" % "test", + // For integration test with Akka + "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", + "org.scala-lang.modules" %% "scala-collection-compat" % "2.13.0" % "test" + ) ) -lazy val msgpackJackson = - Project(id = "msgpack-jackson", base = file("msgpack-jackson")) - .enablePlugins(SbtOsgi) - .settings( - buildSettings, - name := "jackson-dataformat-msgpack", - description := "Jackson extension that adds support for MessagePack", - OsgiKeys.bundleSymbolicName := "org.msgpack.msgpack-jackson", - OsgiKeys.exportPackage := Seq( - "org.msgpack.jackson", - "org.msgpack.jackson.dataformat" - ), - libraryDependencies ++= Seq( +lazy val msgpackJackson = Project(id = "msgpack-jackson", base = file("msgpack-jackson")) + .enablePlugins(SbtOsgi) + .settings( + buildSettings, + name := "jackson-dataformat-msgpack", + description := "Jackson extension that adds support for MessagePack", + OsgiKeys.bundleSymbolicName := "org.msgpack.msgpack-jackson", + OsgiKeys.exportPackage := Seq("org.msgpack.jackson", "org.msgpack.jackson.dataformat"), + libraryDependencies ++= + Seq( "com.fasterxml.jackson.core" % "jackson-databind" % "2.18.4", junitJupiter, junitVintage, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), - testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") - ) - .dependsOn(msgpackCore) + testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") + ) + .dependsOn(msgpackCore) From 12062270a5ee2a0c754a11cef4b0a03e0f0078e9 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 25 Aug 2025 20:11:04 +0200 Subject: [PATCH 398/417] Update scalafmt-core to 3.9.9 (#907) * Update scalafmt-core to 3.9.9 * Reformat with scalafmt 3.9.9 Executed command: scalafmt --non-interactive * Add 'Reformat with scalafmt 3.9.9' to .git-blame-ignore-revs --- .git-blame-ignore-revs | 2 ++ .scalafmt.conf | 2 +- project/plugins.sbt | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..285ed6f41 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Scala Steward: Reformat with scalafmt 3.9.9 +424ec59eb4865feb383ca53b4278dfb8b9b6c36c diff --git a/.scalafmt.conf b/.scalafmt.conf index e8563bafe..a4b995aac 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = 3.9.8 +version = 3.9.9 project.layout = StandardConvention runner.dialect = scala3 maxColumn = 100 diff --git a/project/plugins.sbt b/project/plugins.sbt index 5bc49937b..18f414eaa 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,10 +1,10 @@ -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") -addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") +addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.5") -addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.1") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.5") +addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.1") scalacOptions ++= Seq("-deprecation", "-feature") From e93fb75eed2d8ca6e41993d4dad3f9c68d33be29 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 30 Aug 2025 18:24:48 -0700 Subject: [PATCH 399/417] Bump actions/setup-java from 4 to 5 (#914) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4 to 5. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/snapshot.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a61fb3fad..091ca0deb 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -55,7 +55,7 @@ jobs: java: ['8', '11', '17', '21', '24'] steps: - uses: actions/checkout@v5 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: 'zulu' java-version: ${{ matrix.java }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d1aa99f1..16adf80f0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: # Fetch all tags so that sbt-dynver can find the previous release version - run: git fetch --tags -f # Install OpenJDK 8 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: # We need to use JDK8 for Android compatibility https://github.com/msgpack/msgpack-java/issues/516 java-version: 8 diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index eac8cfbb0..749e61759 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -21,7 +21,7 @@ jobs: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version - run: git fetch --tags - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: java-version: 11 distribution: adopt From be6f0160119eb1214449e7b8470c162df39193dc Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sun, 31 Aug 2025 03:24:57 +0200 Subject: [PATCH 400/417] Update sbt, scripted-plugin to 1.11.5 (#913) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index aced30652..d05ee0257 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.11.4 +sbt.version=1.11.5 From cab44596bf6ebe3b74198897cc77e5e7ed91bccb Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 1 Sep 2025 23:16:30 +0200 Subject: [PATCH 401/417] Update junit-jupiter to 5.13.4 (#905) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 547e1ebe5..143ef7e14 100644 --- a/build.sbt +++ b/build.sbt @@ -98,7 +98,7 @@ val buildSettings = Seq[Setting[?]]( ((Test / compile) dependsOn (Test / jcheckStyle)).value ) -val junitJupiter = "org.junit.jupiter" % "junit-jupiter" % "5.11.4" % "test" +val junitJupiter = "org.junit.jupiter" % "junit-jupiter" % "5.13.4" % "test" val junitVintage = "org.junit.vintage" % "junit-vintage-engine" % "5.11.4" % "test" // Project settings From 17dc837745ef3be60aa3f37b44230ce92fffd5e4 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 18 Sep 2025 17:18:08 +0200 Subject: [PATCH 402/417] Update sbt, scripted-plugin to 1.11.6 (#918) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index d05ee0257..73840fdda 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.11.5 +sbt.version=1.11.6 From 06cf66d77ba85ef4ad76e7a65da4b6d6b2672bbd Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 18 Sep 2025 17:18:17 +0200 Subject: [PATCH 403/417] Update airframe-json, airspec to 2025.1.18 (#920) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 143ef7e14..5e89ef1e1 100644 --- a/build.sbt +++ b/build.sbt @@ -3,7 +3,7 @@ Global / onChangedBuildSource := ReloadOnSourceChanges // For performance testing, ensure each test run one-by-one Global / concurrentRestrictions := Seq(Tags.limit(Tags.Test, 1)) -val AIRFRAME_VERSION = "2025.1.16" +val AIRFRAME_VERSION = "2025.1.18" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From 918a396fcde16987abc8a26edb126248c868c9aa Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 18 Sep 2025 17:18:36 +0200 Subject: [PATCH 404/417] Update scalacheck to 1.19.0 (#919) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 5e89ef1e1..3f8c9813c 100644 --- a/build.sbt +++ b/build.sbt @@ -144,7 +144,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.wvlet.airframe" %% "airframe-json" % AIRFRAME_VERSION % "test", "org.wvlet.airframe" %% "airspec" % AIRFRAME_VERSION % "test", // Add property testing support with forAll methods - "org.scalacheck" %% "scalacheck" % "1.18.1" % "test", + "org.scalacheck" %% "scalacheck" % "1.19.0" % "test", // For performance comparison with msgpack v6 "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka From a7a54ea6ed5710391f6f4222189690b0cc630103 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 24 Nov 2025 19:47:13 +0100 Subject: [PATCH 405/417] Update sbt-scalafmt to 2.5.6 (#932) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 18f414eaa..a7594c7a3 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1") //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.5") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.6") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.1") scalacOptions ++= Seq("-deprecation", "-feature") From 78e5b7e2cb3d50e86e276e771e5fc9f794f8240f Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 24 Nov 2025 19:47:24 +0100 Subject: [PATCH 406/417] Update airframe-json, airspec to 2025.1.21 (#929) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3f8c9813c..6e3d753d9 100644 --- a/build.sbt +++ b/build.sbt @@ -3,7 +3,7 @@ Global / onChangedBuildSource := ReloadOnSourceChanges // For performance testing, ensure each test run one-by-one Global / concurrentRestrictions := Seq(Tags.limit(Tags.Test, 1)) -val AIRFRAME_VERSION = "2025.1.18" +val AIRFRAME_VERSION = "2025.1.21" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From bfa9fd4674a3f7e92922debbf1cc04c3670243c9 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 24 Nov 2025 19:48:12 +0100 Subject: [PATCH 407/417] Update scala-collection-compat to 2.14.0 (#926) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 6e3d753d9..d70268a0f 100644 --- a/build.sbt +++ b/build.sbt @@ -149,7 +149,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) "org.msgpack" % "msgpack" % "0.6.12" % "test", // For integration test with Akka "com.typesafe.akka" %% "akka-actor" % "2.6.20" % "test", - "org.scala-lang.modules" %% "scala-collection-compat" % "2.13.0" % "test" + "org.scala-lang.modules" %% "scala-collection-compat" % "2.14.0" % "test" ) ) From f6427b4aa757aba58fd6f9788a3db0b789342e52 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 24 Nov 2025 19:48:23 +0100 Subject: [PATCH 408/417] Update sbt, scripted-plugin to 1.11.7 (#925) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 73840fdda..b1b10405c 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.11.6 +sbt.version=1.11.7 From 81a9f0d80c81a24229a2641075a9e802c0843ec2 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 24 Nov 2025 19:49:33 +0100 Subject: [PATCH 409/417] Update junit-jupiter to 5.14.1 (#930) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index d70268a0f..f8600c56f 100644 --- a/build.sbt +++ b/build.sbt @@ -98,7 +98,7 @@ val buildSettings = Seq[Setting[?]]( ((Test / compile) dependsOn (Test / jcheckStyle)).value ) -val junitJupiter = "org.junit.jupiter" % "junit-jupiter" % "5.13.4" % "test" +val junitJupiter = "org.junit.jupiter" % "junit-jupiter" % "5.14.1" % "test" val junitVintage = "org.junit.vintage" % "junit-vintage-engine" % "5.11.4" % "test" // Project settings From 9c27ee586204993dbb6348024f72405945c82108 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 2 Jan 2026 18:29:33 +0100 Subject: [PATCH 410/417] Update airframe-json, airspec to 2025.1.22 (#938) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f8600c56f..43536584d 100644 --- a/build.sbt +++ b/build.sbt @@ -3,7 +3,7 @@ Global / onChangedBuildSource := ReloadOnSourceChanges // For performance testing, ensure each test run one-by-one Global / concurrentRestrictions := Seq(Tags.limit(Tags.Test, 1)) -val AIRFRAME_VERSION = "2025.1.21" +val AIRFRAME_VERSION = "2025.1.22" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true From c9864c5e08ff34acb1831e42b63ac558ef86c670 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 09:29:42 -0800 Subject: [PATCH 411/417] Bump actions/cache from 4 to 5 (#937) Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 091ca0deb..86936f65b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -59,7 +59,7 @@ jobs: with: distribution: 'zulu' java-version: ${{ matrix.java }} - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: ~/.cache key: ${{ runner.os }}-jdk${{ matrix.java }}-${{ hashFiles('**/*.sbt') }} From 56e7bc6879b2d2184896c13046ba7ea61528ae8f Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 2 Jan 2026 18:29:53 +0100 Subject: [PATCH 412/417] Update junit-vintage-engine to 5.14.1 (#931) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 43536584d..4d72279e5 100644 --- a/build.sbt +++ b/build.sbt @@ -99,7 +99,7 @@ val buildSettings = Seq[Setting[?]]( ) val junitJupiter = "org.junit.jupiter" % "junit-jupiter" % "5.14.1" % "test" -val junitVintage = "org.junit.vintage" % "junit-vintage-engine" % "5.11.4" % "test" +val junitVintage = "org.junit.vintage" % "junit-vintage-engine" % "5.14.1" % "test" // Project settings lazy val root = Project(id = "msgpack-java", base = file(".")) From befe3b943fbdc59070acfea8feb317044096bc85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 09:30:03 -0800 Subject: [PATCH 413/417] Bump actions/checkout from 5 to 6 (#935) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/CI.yml | 6 +++--- .github/workflows/release.yml | 2 +- .github/workflows/snapshot.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 86936f65b..a427ec6f5 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -15,7 +15,7 @@ jobs: docs: ${{ steps.changes.outputs.docs }} steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - uses: dorny/paths-filter@v3 id: changes with: @@ -39,7 +39,7 @@ jobs: needs: changes if: ${{ needs.changes.outputs.code == 'true' }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: jcheckstyle run: ./sbt jcheckStyle - name: scalafmtCheckAll @@ -54,7 +54,7 @@ jobs: matrix: java: ['8', '11', '17', '21', '24'] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-java@v5 with: distribution: 'zulu' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 16adf80f0..0cec50291 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: name: Release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 749e61759..dc0fac1d6 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -16,7 +16,7 @@ jobs: name: Publish snapshots runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version From daa2ea6b2f11f500e22c70a22f689f7a9debdeae Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 2 Jan 2026 10:26:44 -0800 Subject: [PATCH 414/417] Merge commit from fork MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve readPayload(int) to use gradual memory allocation for large payloads (>64MB). This validates that sufficient data is available before completing allocation, improving robustness when handling untrusted input. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 --- .../org/msgpack/core/MessageUnpacker.java | 85 ++++++++++++- .../msgpack/core/PayloadSizeLimitTest.scala | 116 ++++++++++++++++++ 2 files changed, 197 insertions(+), 4 deletions(-) create mode 100644 msgpack-core/src/test/scala/org/msgpack/core/PayloadSizeLimitTest.scala diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 5a9a1a631..5819f6c23 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -26,6 +26,8 @@ import java.io.Closeable; import java.io.IOException; import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; @@ -150,6 +152,14 @@ public class MessageUnpacker { private static final MessageBuffer EMPTY_BUFFER = MessageBuffer.wrap(new byte[0]); + /** + * Threshold for switching from upfront allocation to gradual allocation. + * Payloads up to this size use efficient upfront allocation. + * Payloads exceeding this size use gradual allocation to detect malicious files + * that declare large payload sizes but contain little actual data. + */ + private static final int GRADUAL_ALLOCATION_THRESHOLD = 64 * 1024 * 1024; // 64 MB + private final boolean allowReadingStringAsBinary; private final boolean allowReadingBinaryAsString; private final CodingErrorAction actionOnMalformedString; @@ -1637,18 +1647,85 @@ public void readPayload(byte[] dst) * This method allocates a new byte array and consumes specified amount of bytes into the byte array. * *

      - * This method is equivalent to readPayload(new byte[length]). + * For sizes up to {@link #GRADUAL_ALLOCATION_THRESHOLD}, this method uses efficient upfront allocation. + * For larger sizes, it uses gradual allocation to protect against malicious files that declare + * large payload sizes but contain little actual data. * * @param length number of bytes to be read * @return the new byte array * @throws IOException when underlying input throws IOException + * @throws MessageSizeException when the input ends before the declared size is reached (for large payloads) */ public byte[] readPayload(int length) throws IOException { - byte[] newArray = new byte[length]; - readPayload(newArray); - return newArray; + if (length <= GRADUAL_ALLOCATION_THRESHOLD) { + // Small/moderate size: use efficient upfront allocation + byte[] newArray = new byte[length]; + readPayload(newArray); + return newArray; + } + + // Large declared size: use gradual allocation to protect against malicious files + return readPayloadGradually(length); + } + + /** + * Read payload gradually, allocating memory only as data becomes available. + * This method protects against malicious files that declare large payload sizes + * but contain little actual data. + * + * @param declaredLength the declared payload length + * @return the payload bytes + * @throws IOException when underlying input throws IOException + * @throws MessageSizeException when the input ends before the declared size is reached + */ + private byte[] readPayloadGradually(int declaredLength) + throws IOException + { + List chunks = new ArrayList<>(); + int totalRead = 0; + int remaining = declaredLength; + + while (remaining > 0) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining == 0) { + // Need more data from input + MessageBuffer next = in.next(); + if (next == null) { + // Input ended before we read the declared size + throw new MessageSizeException( + String.format("Payload declared %,d bytes but input ended after %,d bytes", + declaredLength, totalRead), + declaredLength); + } + totalReadBytes += buffer.size(); + buffer = next; + position = 0; + bufferRemaining = buffer.size(); + } + + int toRead = Math.min(remaining, bufferRemaining); + byte[] chunk = new byte[toRead]; + buffer.getBytes(position, chunk, 0, toRead); + chunks.add(chunk); + totalRead += toRead; + position += toRead; + remaining -= toRead; + } + + // All data verified to exist - combine chunks into result + if (chunks.size() == 1) { + return chunks.get(0); // Common case: single chunk, no copy needed + } + + byte[] result = new byte[declaredLength]; + int offset = 0; + for (byte[] chunk : chunks) { + System.arraycopy(chunk, 0, result, offset, chunk.length); + offset += chunk.length; + } + return result; } /** diff --git a/msgpack-core/src/test/scala/org/msgpack/core/PayloadSizeLimitTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/PayloadSizeLimitTest.scala new file mode 100644 index 000000000..e42c38a55 --- /dev/null +++ b/msgpack-core/src/test/scala/org/msgpack/core/PayloadSizeLimitTest.scala @@ -0,0 +1,116 @@ +package org.msgpack.core + +import wvlet.airspec.AirSpec + +import java.nio.ByteBuffer + +class PayloadSizeLimitTest extends AirSpec: + + test("detects malicious EXT32 file with huge declared size but tiny actual data") { + // Craft a malicious EXT32 header: + // 0xC9 = EXT32 format + // 4 bytes = declared length (100MB, which exceeds 64MB threshold) + // 1 byte = extension type + // followed by only 1 byte of actual data (not 100MB) + val declaredLength = 100 * 1024 * 1024 // 100 MB + val buffer = ByteBuffer.allocate(7) // header(1) + length(4) + type(1) + data(1) + buffer.put(0xC9.toByte) // EXT32 format code + buffer.putInt(declaredLength) // declared length (big-endian) + buffer.put(0x01.toByte) // extension type + buffer.put(0x41.toByte) // only 1 byte of actual data + val maliciousData = buffer.array() + + val unpacker = MessagePack.newDefaultUnpacker(maliciousData) + + // Should throw MessageSizeException because the declared size exceeds actual data + intercept[MessageSizeException] { + unpacker.unpackValue() + } + } + + test("detects malicious BIN32 file with huge declared size but tiny actual data") { + // Craft a malicious BIN32 header: + // 0xC6 = BIN32 format + // 4 bytes = declared length (100MB, which exceeds 64MB threshold) + // followed by only 1 byte of actual data (not 100MB) + val declaredLength = 100 * 1024 * 1024 // 100 MB + val buffer = ByteBuffer.allocate(6) // header(1) + length(4) + data(1) + buffer.put(0xC6.toByte) // BIN32 format code + buffer.putInt(declaredLength) // declared length (big-endian) + buffer.put(0x41.toByte) // only 1 byte of actual data + val maliciousData = buffer.array() + + val unpacker = MessagePack.newDefaultUnpacker(maliciousData) + + // Should throw MessageSizeException because the declared size exceeds actual data + intercept[MessageSizeException] { + unpacker.unpackValue() + } + } + + test("legitimate extension data works correctly") { + val packer = MessagePack.newDefaultBufferPacker() + val testData = Array.fill[Byte](1000)(0x42) + packer.packExtensionTypeHeader(0x01.toByte, testData.length) + packer.writePayload(testData) + val msgpack = packer.toByteArray + + val unpacker = MessagePack.newDefaultUnpacker(msgpack) + val value = unpacker.unpackValue() + + assert(value.isExtensionValue) + assert(value.asExtensionValue().getData.length == 1000) + } + + test("legitimate binary data works correctly") { + val packer = MessagePack.newDefaultBufferPacker() + val testData = Array.fill[Byte](1000)(0x42) + packer.packBinaryHeader(testData.length) + packer.writePayload(testData) + val msgpack = packer.toByteArray + + val unpacker = MessagePack.newDefaultUnpacker(msgpack) + val value = unpacker.unpackValue() + + assert(value.isBinaryValue) + assert(value.asBinaryValue().asByteArray().length == 1000) + } + + test("readPayload directly with malicious size throws exception") { + // Test readPayload(int) directly with a malicious input + val declaredLength = 100 * 1024 * 1024 // 100 MB + val buffer = ByteBuffer.allocate(6) // header(1) + length(4) + data(1) + buffer.put(0xC6.toByte) // BIN32 format code + buffer.putInt(declaredLength) // declared length (big-endian) + buffer.put(0x41.toByte) // only 1 byte of actual data + val maliciousData = buffer.array() + + val unpacker = MessagePack.newDefaultUnpacker(maliciousData) + + // First, unpack the binary header to get the declared length + val len = unpacker.unpackBinaryHeader() + assert(len == declaredLength) + + // Then try to read the payload - should throw exception + intercept[MessageSizeException] { + unpacker.readPayload(len) + } + } + + test("small payloads under threshold work with upfront allocation") { + // Payloads under 64MB should use the efficient upfront allocation path + val packer = MessagePack.newDefaultBufferPacker() + val testData = Array.fill[Byte](10000)(0x42) // 10KB, well under threshold + packer.packBinaryHeader(testData.length) + packer.writePayload(testData) + val msgpack = packer.toByteArray + + val unpacker = MessagePack.newDefaultUnpacker(msgpack) + val len = unpacker.unpackBinaryHeader() + val payload = unpacker.readPayload(len) + + assert(payload.length == 10000) + assert(payload.forall(_ == 0x42.toByte)) + } + +end PayloadSizeLimitTest From 884e9c1baec57c211253cd92fd8f81c4c899f943 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Fri, 2 Jan 2026 10:32:18 -0800 Subject: [PATCH 415/417] Fix Scala code formatting (#939) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix Scala code formatting in PayloadSizeLimitTest Apply scalafmt to align variable declarations and comments according to project style guidelines. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 --- .../msgpack/core/PayloadSizeLimitTest.scala | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/PayloadSizeLimitTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/PayloadSizeLimitTest.scala index e42c38a55..7f454c859 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/PayloadSizeLimitTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/PayloadSizeLimitTest.scala @@ -12,13 +12,13 @@ class PayloadSizeLimitTest extends AirSpec: // 4 bytes = declared length (100MB, which exceeds 64MB threshold) // 1 byte = extension type // followed by only 1 byte of actual data (not 100MB) - val declaredLength = 100 * 1024 * 1024 // 100 MB - val buffer = ByteBuffer.allocate(7) // header(1) + length(4) + type(1) + data(1) - buffer.put(0xC9.toByte) // EXT32 format code - buffer.putInt(declaredLength) // declared length (big-endian) - buffer.put(0x01.toByte) // extension type - buffer.put(0x41.toByte) // only 1 byte of actual data - val maliciousData = buffer.array() + val declaredLength = 100 * 1024 * 1024 // 100 MB + val buffer = ByteBuffer.allocate(7) // header(1) + length(4) + type(1) + data(1) + buffer.put(0xc9.toByte) // EXT32 format code + buffer.putInt(declaredLength) // declared length (big-endian) + buffer.put(0x01.toByte) // extension type + buffer.put(0x41.toByte) // only 1 byte of actual data + val maliciousData = buffer.array() val unpacker = MessagePack.newDefaultUnpacker(maliciousData) @@ -33,12 +33,12 @@ class PayloadSizeLimitTest extends AirSpec: // 0xC6 = BIN32 format // 4 bytes = declared length (100MB, which exceeds 64MB threshold) // followed by only 1 byte of actual data (not 100MB) - val declaredLength = 100 * 1024 * 1024 // 100 MB - val buffer = ByteBuffer.allocate(6) // header(1) + length(4) + data(1) - buffer.put(0xC6.toByte) // BIN32 format code - buffer.putInt(declaredLength) // declared length (big-endian) - buffer.put(0x41.toByte) // only 1 byte of actual data - val maliciousData = buffer.array() + val declaredLength = 100 * 1024 * 1024 // 100 MB + val buffer = ByteBuffer.allocate(6) // header(1) + length(4) + data(1) + buffer.put(0xc6.toByte) // BIN32 format code + buffer.putInt(declaredLength) // declared length (big-endian) + buffer.put(0x41.toByte) // only 1 byte of actual data + val maliciousData = buffer.array() val unpacker = MessagePack.newDefaultUnpacker(maliciousData) @@ -49,28 +49,28 @@ class PayloadSizeLimitTest extends AirSpec: } test("legitimate extension data works correctly") { - val packer = MessagePack.newDefaultBufferPacker() + val packer = MessagePack.newDefaultBufferPacker() val testData = Array.fill[Byte](1000)(0x42) packer.packExtensionTypeHeader(0x01.toByte, testData.length) packer.writePayload(testData) val msgpack = packer.toByteArray val unpacker = MessagePack.newDefaultUnpacker(msgpack) - val value = unpacker.unpackValue() + val value = unpacker.unpackValue() assert(value.isExtensionValue) assert(value.asExtensionValue().getData.length == 1000) } test("legitimate binary data works correctly") { - val packer = MessagePack.newDefaultBufferPacker() + val packer = MessagePack.newDefaultBufferPacker() val testData = Array.fill[Byte](1000)(0x42) packer.packBinaryHeader(testData.length) packer.writePayload(testData) val msgpack = packer.toByteArray val unpacker = MessagePack.newDefaultUnpacker(msgpack) - val value = unpacker.unpackValue() + val value = unpacker.unpackValue() assert(value.isBinaryValue) assert(value.asBinaryValue().asByteArray().length == 1000) @@ -78,12 +78,12 @@ class PayloadSizeLimitTest extends AirSpec: test("readPayload directly with malicious size throws exception") { // Test readPayload(int) directly with a malicious input - val declaredLength = 100 * 1024 * 1024 // 100 MB - val buffer = ByteBuffer.allocate(6) // header(1) + length(4) + data(1) - buffer.put(0xC6.toByte) // BIN32 format code - buffer.putInt(declaredLength) // declared length (big-endian) - buffer.put(0x41.toByte) // only 1 byte of actual data - val maliciousData = buffer.array() + val declaredLength = 100 * 1024 * 1024 // 100 MB + val buffer = ByteBuffer.allocate(6) // header(1) + length(4) + data(1) + buffer.put(0xc6.toByte) // BIN32 format code + buffer.putInt(declaredLength) // declared length (big-endian) + buffer.put(0x41.toByte) // only 1 byte of actual data + val maliciousData = buffer.array() val unpacker = MessagePack.newDefaultUnpacker(maliciousData) @@ -99,15 +99,15 @@ class PayloadSizeLimitTest extends AirSpec: test("small payloads under threshold work with upfront allocation") { // Payloads under 64MB should use the efficient upfront allocation path - val packer = MessagePack.newDefaultBufferPacker() - val testData = Array.fill[Byte](10000)(0x42) // 10KB, well under threshold + val packer = MessagePack.newDefaultBufferPacker() + val testData = Array.fill[Byte](10000)(0x42) // 10KB, well under threshold packer.packBinaryHeader(testData.length) packer.writePayload(testData) val msgpack = packer.toByteArray val unpacker = MessagePack.newDefaultUnpacker(msgpack) - val len = unpacker.unpackBinaryHeader() - val payload = unpacker.readPayload(len) + val len = unpacker.unpackBinaryHeader() + val payload = unpacker.readPayload(len) assert(payload.length == 10000) assert(payload.forall(_ == 0x42.toByte)) From ab5dc83f7039a3fe009d84d39e8b5f83addb5a45 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 2 Jan 2026 20:44:35 +0100 Subject: [PATCH 416/417] Update scalafmt-core to 3.9.10 (#921) --- .scalafmt.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index a4b995aac..8ef32eb08 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = 3.9.9 +version = 3.9.10 project.layout = StandardConvention runner.dialect = scala3 maxColumn = 100 From 580fde4766e6e6a6931cabf6062a6661377185da Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:36:02 +0100 Subject: [PATCH 417/417] Update scalafmt-core to 3.10.3 (#941) * Update scalafmt-core to 3.10.3 * Reformat with scalafmt 3.10.3 Executed command: scalafmt --non-interactive * Add 'Reformat with scalafmt 3.10.3' to .git-blame-ignore-revs --- .git-blame-ignore-revs | 3 +++ .scalafmt.conf | 2 +- .../scala/org/msgpack/core/MessagePackSpec.scala | 3 ++- .../scala/org/msgpack/core/MessagePackTest.scala | 13 +++++++++---- .../scala/org/msgpack/core/MessagePackerTest.scala | 8 ++++++-- .../org/msgpack/core/MessageUnpackerTest.scala | 7 ++++--- .../core/buffer/MessageBufferInputTest.scala | 10 +++++++--- .../scala/org/msgpack/value/ValueTypeTest.scala | 3 ++- .../test/scala/org/msgpack/value/VariableTest.scala | 4 +++- 9 files changed, 37 insertions(+), 16 deletions(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 285ed6f41..aead11725 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,2 +1,5 @@ # Scala Steward: Reformat with scalafmt 3.9.9 424ec59eb4865feb383ca53b4278dfb8b9b6c36c + +# Scala Steward: Reformat with scalafmt 3.10.3 +d8af028d2cd271ab7f3adec9842f07cce86a2ac3 diff --git a/.scalafmt.conf b/.scalafmt.conf index 8ef32eb08..d30b05371 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = 3.9.10 +version = 3.10.3 project.layout = StandardConvention runner.dialect = scala3 maxColumn = 100 diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala index 135c49216..21080f65e 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackSpec.scala @@ -16,7 +16,8 @@ package org.msgpack.core import wvlet.log.LogLevel -import wvlet.log.io.{TimeReport, Timer} +import wvlet.log.io.TimeReport +import wvlet.log.io.Timer import java.io.ByteArrayOutputStream diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index b55413934..16236c651 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -15,18 +15,23 @@ // package org.msgpack.core -import org.msgpack.core.MessagePack.{Code, PackerConfig, UnpackerConfig} +import org.msgpack.core.MessagePack.Code +import org.msgpack.core.MessagePack.PackerConfig +import org.msgpack.core.MessagePack.UnpackerConfig import org.msgpack.core.MessagePackSpec.toHex -import org.msgpack.value.{Value, Variable} +import org.msgpack.value.Value +import org.msgpack.value.Variable import org.scalacheck.Prop.propBoolean -import org.scalacheck.{Arbitrary, Gen} +import org.scalacheck.Arbitrary +import org.scalacheck.Gen import wvlet.airspec.AirSpec import wvlet.airspec.spi.PropertyCheck import java.io.ByteArrayOutputStream import java.math.BigInteger import java.nio.CharBuffer -import java.nio.charset.{CodingErrorAction, UnmappableCharacterException} +import java.nio.charset.CodingErrorAction +import java.nio.charset.UnmappableCharacterException import java.time.Instant import scala.util.Random diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index 7ff5d82ee..e31853ab9 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -16,12 +16,16 @@ package org.msgpack.core import org.msgpack.core.MessagePack.PackerConfig -import org.msgpack.core.buffer.{ChannelBufferOutput, OutputStreamBufferOutput} +import org.msgpack.core.buffer.ChannelBufferOutput +import org.msgpack.core.buffer.OutputStreamBufferOutput import org.msgpack.value.ValueFactory import wvlet.airspec.AirSpec import wvlet.log.io.IOUtil.withResource -import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream} +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.FileInputStream +import java.io.FileOutputStream import scala.util.Random /** diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index adab47089..bf43591ac 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -15,7 +15,8 @@ // package org.msgpack.core -import org.msgpack.core.MessagePackSpec.{createMessagePackData, toHex} +import org.msgpack.core.MessagePackSpec.createMessagePackData +import org.msgpack.core.MessagePackSpec.toHex import org.msgpack.core.buffer.* import org.msgpack.value.ValueType import wvlet.airspec.AirSpec @@ -67,8 +68,8 @@ class MessageUnpackerTest extends AirSpec with Benchmark: private val intSeq = ( - for (i <- 0 until 100) - yield Random.nextInt() + for i <- 0 until 100 + yield Random.nextInt() ).toArray[Int] private def testData2: Array[Byte] = diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index 5e6c1f96d..0465aa699 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -22,9 +22,13 @@ import wvlet.log.io.IOUtil.withResource import java.io.* import java.net.InetSocketAddress import java.nio.ByteBuffer -import java.nio.channels.{ServerSocketChannel, SocketChannel} -import java.util.concurrent.{Callable, Executors, TimeUnit} -import java.util.zip.{GZIPInputStream, GZIPOutputStream} +import java.nio.channels.ServerSocketChannel +import java.nio.channels.SocketChannel +import java.util.concurrent.Callable +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit +import java.util.zip.GZIPInputStream +import java.util.zip.GZIPOutputStream import scala.util.Random class MessageBufferInputTest extends AirSpec: diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala index 7b992f28b..53707c995 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala @@ -16,7 +16,8 @@ package org.msgpack.value import org.msgpack.core.MessagePack.Code.* -import org.msgpack.core.{MessageFormat, MessageFormatException} +import org.msgpack.core.MessageFormat +import org.msgpack.core.MessageFormatException import wvlet.airspec.AirSpec /** diff --git a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala index 2f3cbf9c8..d4754e832 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/VariableTest.scala @@ -15,7 +15,9 @@ // package org.msgpack.value -import org.msgpack.core.{MessagePack, MessagePacker, MessageTypeCastException} +import org.msgpack.core.MessagePack +import org.msgpack.core.MessagePacker +import org.msgpack.core.MessageTypeCastException import wvlet.airspec.AirSpec import wvlet.airspec.spi.PropertyCheck