This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 8ed6644 MessagePack improvements.
8ed6644 is described below
commit 8ed6644bb0420b1f3db910e410d9abdd23b9431e
Author: JamesBognar <[email protected]>
AuthorDate: Sun May 9 11:13:14 2021 -0400
MessagePack improvements.
1) Byte array serialized to bin entries.
2) Strings serialized without intermediate byte array allocations.
---
.../apache/juneau/msgpack/MsgPackOutputStream.java | 113 +++++++++++++++++++--
.../juneau/msgpack/MsgPackParserSession.java | 2 +-
.../juneau/msgpack/MsgPackSerializerSession.java | 3 +
3 files changed, 109 insertions(+), 9 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackOutputStream.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackOutputStream.java
index 4ded995..8436050 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackOutputStream.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackOutputStream.java
@@ -12,12 +12,15 @@
//
***************************************************************************************************************************
package org.apache.juneau.msgpack;
+import static org.apache.juneau.internal.ExceptionUtils.*;
import static org.apache.juneau.msgpack.DataType.*;
import java.io.*;
import java.math.*;
import java.util.concurrent.atomic.*;
+import org.apache.juneau.internal.*;
+
/**
* Specialized output stream for serializing MessagePack streams.
*
@@ -214,14 +217,22 @@ public final class MsgPackOutputStream extends
OutputStream {
// * AAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA is a 32-bit big-endian
unsigned integer which represents N
// * N is the length of data
- byte[] b = cs.toString().getBytes("UTF-8");
- if (b.length < 32)
- return append1(0xA0 + b.length).append(b);
- if (b.length < (1<<8))
- return append1(STR8).append1(b.length).append(b);
- if (b.length < (1<<16))
- return append1(STR16).append2(b.length).append(b);
- return append1(STR32).append4(b.length).append(b);
+ int length = getUtf8ByteLength(cs);
+ if (length < 32)
+ append1(0xA0 + length);
+ else if (length < (1<<8))
+ append1(STR8).append1(length);
+ else if (length < (1<<16))
+ append1(STR16).append2(length);
+ else
+ append1(STR32).append4(length);
+
+ int length2 = writeUtf8To(cs, os);
+
+ if (length != length2)
+ throw ioException("Unexpected length. Expected={0},
Actual={1}", length, length2);
+
+ return this;
}
/**
@@ -257,6 +268,44 @@ public final class MsgPackOutputStream extends
OutputStream {
}
/**
+ * Appends a binary field to the stream.
+ */
+ final MsgPackOutputStream appendBinary(InputStream is) throws
IOException {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ IOUtils.pipe(is, baos);
+
+ byte[] b = baos.toByteArray();
+
+ // bin 8 stores a byte array whose length is up to (2^8)-1
bytes:
+ // +--------+--------+========+
+ // | 0xc4 |XXXXXXXX| data |
+ // +--------+--------+========+
+ //
+ // bin 16 stores a byte array whose length is up to (2^16)-1
bytes:
+ // +--------+--------+--------+========+
+ // | 0xc5 |YYYYYYYY|YYYYYYYY| data |
+ // +--------+--------+--------+========+
+ //
+ // bin 32 stores a byte array whose length is up to (2^32)-1
bytes:
+ // +--------+--------+--------+--------+--------+========+
+ // | 0xc6 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| data |
+ // +--------+--------+--------+--------+--------+========+
+ //
+ // where
+ // * XXXXXXXX is a 8-bit unsigned integer which represents N
+ // * YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer
which represents N
+ // * ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian
unsigned integer which represents N
+ // * N is the length of data
+
+ if (b.length < (1<<8))
+ return append1(BIN8).append1(b.length).append(b);
+ if (b.length < (1<<16))
+ return append1(BIN16).append2(b.length).append(b);
+ return append1(BIN32).append4(b.length).append(b);
+ }
+
+ /**
* Appends an array data type flag to the stream.
*/
final MsgPackOutputStream startArray(int size) throws IOException {
@@ -321,4 +370,52 @@ public final class MsgPackOutputStream extends
OutputStream {
return append1(MAP16).append2(size);
return append1(MAP32).append4(size);
}
+
+ private int writeUtf8To(CharSequence in, OutputStream out) throws
IOException {
+ int count = 0;
+ for (int i = 0, len = in.length(); i < len; i++) {
+ int c = (in.charAt(i) & 0xFFFF);
+ if (c <= 0x7F) {
+ out.write((byte) (c & 0xFF));
+ count++;
+ } else if (c <= 0x7FF) {
+ out.write((byte) (0xC0 + ((c>>6) & 0x1F)));
+ out.write((byte) (0x80 + (c & 0x3F)));
+ count += 2;
+ } else if (c >= 0xD800 && c <= 0xDFFF) {
+ int jchar2 = in.charAt(++i) & 0xFFFF;
+ int n = (c<<10) + jchar2 + 0xFCA02400;
+ out.write((byte) (0xF0 + ((n>>18) & 0x07)));
+ out.write((byte) (0x80 + ((n>>12) & 0x3F)));
+ out.write((byte) (0x80 + ((n>>6) & 0x3F)));
+ out.write((byte) (0x80 + (n & 0x3F)));
+ count += 4;
+ } else {
+ out.write((byte) (0xE0 + ((c>>12) & 0x0F)));
+ out.write((byte) (0x80 + ((c>>6) & 0x3F)));
+ out.write((byte) (0x80 + (c & 0x3F)));
+ count += 3;
+ }
+ }
+ return count;
+ }
+
+ private int getUtf8ByteLength(CharSequence cs) {
+ int count = 0;
+ for (int i = 0, len = cs.length(); i < len; i++) {
+ char ch = cs.charAt(i);
+ if (ch <= 0x7F) {
+ count++;
+ } else if (ch <= 0x7FF) {
+ count += 2;
+ } else if (Character.isHighSurrogate(ch)) {
+ count += 4;
+ ++i;
+ } else {
+ count += 3;
+ }
+ }
+ return count;
+ }
+
}
\ No newline at end of file
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
index 16c5156..11b9cf5 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
@@ -107,7 +107,7 @@ public final class MsgPackParserSession extends
InputStreamParserSession {
if (sType.isObject()) {
// Do nothing.
- } else if (sType.isBoolean() || sType.isCharSequence()
|| sType.isChar() || sType.isNumber()) {
+ } else if (sType.isBoolean() || sType.isCharSequence()
|| sType.isChar() || sType.isNumber() || sType.isByteArray()) {
o = convertToType(o, sType);
} else if (sType.isMap()) {
if (dt == MAP) {
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
index 71adf86..b931890 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
@@ -132,6 +132,9 @@ public final class MsgPackSerializerSession extends
OutputStreamSerializerSessio
else if (sType.isCollection()) {
serializeCollection(out, (Collection) o, eType);
}
+ else if (sType.isByteArray()) {
+ out.appendBinary((byte[])o);
+ }
else if (sType.isArray()) {
serializeCollection(out, toList(sType.getInnerClass(),
o), eType);
}