diff --git a/pom.xml b/pom.xml
index 6b386bb..364a4fb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
io.netty
netty-buffer
- 4.1.65.Final
+ 4.1.66.Final
provided
diff --git a/src/main/java/io/github/yezhihao/protostar/DataType.java b/src/main/java/io/github/yezhihao/protostar/DataType.java
index 98a1b33..124230b 100644
--- a/src/main/java/io/github/yezhihao/protostar/DataType.java
+++ b/src/main/java/io/github/yezhihao/protostar/DataType.java
@@ -19,6 +19,8 @@ public enum DataType {
BYTES(-1),
/** BCD8421码 */
BCD8421(-1),
+ /** 十六进制字符串 */
+ HEX(-1),
/** 字符串 */
STRING(-1),
/** 对象 */
diff --git a/src/main/java/io/github/yezhihao/protostar/DefaultLoadStrategy.java b/src/main/java/io/github/yezhihao/protostar/DefaultLoadStrategy.java
index ece7b6e..ef90f5c 100644
--- a/src/main/java/io/github/yezhihao/protostar/DefaultLoadStrategy.java
+++ b/src/main/java/io/github/yezhihao/protostar/DefaultLoadStrategy.java
@@ -14,7 +14,7 @@ import java.util.Map;
*/
public class DefaultLoadStrategy extends LoadStrategy {
- private Map>> typeClassMapping = new HashMap(140);
+ private Map>> typeClassMapping = new HashMap(256);
public DefaultLoadStrategy() {
}
diff --git a/src/main/java/io/github/yezhihao/protostar/FieldFactory.java b/src/main/java/io/github/yezhihao/protostar/FieldFactory.java
index 63d34f9..794a0e8 100644
--- a/src/main/java/io/github/yezhihao/protostar/FieldFactory.java
+++ b/src/main/java/io/github/yezhihao/protostar/FieldFactory.java
@@ -52,6 +52,9 @@ public abstract class FieldFactory {
else
fieldSchema = ArraySchema.ByteArraySchema.INSTANCE;
break;
+ case HEX:
+ fieldSchema = StringSchema.HEX.INSTANCE;
+ break;
case STRING:
fieldSchema = StringSchema.Chars.getInstance(field.pad(), field.charset());
break;
diff --git a/src/main/java/io/github/yezhihao/protostar/Schema.java b/src/main/java/io/github/yezhihao/protostar/Schema.java
index b2b3c98..8bbe21a 100644
--- a/src/main/java/io/github/yezhihao/protostar/Schema.java
+++ b/src/main/java/io/github/yezhihao/protostar/Schema.java
@@ -1,8 +1,6 @@
package io.github.yezhihao.protostar;
import io.netty.buffer.ByteBuf;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* 消息结构
@@ -11,8 +9,6 @@ import org.slf4j.LoggerFactory;
*/
public interface Schema {
- Logger log = LoggerFactory.getLogger(Schema.class.getSimpleName());
-
T readFrom(ByteBuf input);
void writeTo(ByteBuf output, T message);
diff --git a/src/main/java/io/github/yezhihao/protostar/schema/StringSchema.java b/src/main/java/io/github/yezhihao/protostar/schema/StringSchema.java
index f86971f..01478e8 100644
--- a/src/main/java/io/github/yezhihao/protostar/schema/StringSchema.java
+++ b/src/main/java/io/github/yezhihao/protostar/schema/StringSchema.java
@@ -1,15 +1,20 @@
package io.github.yezhihao.protostar.schema;
import io.github.yezhihao.protostar.Schema;
-import io.github.yezhihao.protostar.util.Bcd;
import io.github.yezhihao.protostar.util.Cache;
+import io.github.yezhihao.protostar.util.CharsBuilder;
import io.netty.buffer.ByteBuf;
+import io.netty.util.internal.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.nio.charset.Charset;
import java.util.Arrays;
public class StringSchema {
+ private static final Logger log = LoggerFactory.getLogger(StringSchema.class.getSimpleName());
+
public static class Chars implements Schema {
private static final Cache cache = new Cache<>();
@@ -65,7 +70,7 @@ public class StringSchema {
output.writeBytes(bytes);
} else if (srcPos < 0) {
output.writeBytes(bytes, -srcPos, length);
- log.error("字符长度超出限制: 长度[{}],数据长度[{}],{}", length, bytes.length, value);
+ log.info("字符长度超出限制: 长度[{}],数据长度[{}],{}", length, bytes.length, value);
} else {
output.writeBytes(bytes);
}
@@ -75,7 +80,6 @@ public class StringSchema {
}
}
-
public static class BCD implements Schema {
public static final Schema INSTANCE = new BCD();
@@ -91,12 +95,10 @@ public class StringSchema {
public String readFrom(ByteBuf input, int length) {
byte[] bytes = new byte[length];
input.readBytes(bytes);
- char[] chars = Bcd.toChars(bytes);
- int i = Bcd.indexOf(chars, '0');
- if (i == 0)
- return new String(chars);
- return new String(chars, i, chars.length - i);
+ CharsBuilder cb = new CharsBuilder(length << 1);
+ StringUtil.toHexStringPadded(cb, bytes);
+ return cb.leftStrip('0');
}
@Override
@@ -115,9 +117,53 @@ public class StringSchema {
chars[--i] = '0';
} else {
value.getChars(-i, charLength - i, chars, 0);
- log.warn("字符长度超出限制: 长度[{}],[{}]", charLength, value);
+ log.info("字符长度超出限制: 长度[{}],[{}]", charLength, value);
}
- byte[] src = Bcd.from(chars);
+ byte[] src = StringUtil.decodeHexDump(new CharsBuilder(chars));
+ output.writeBytes(src);
+ }
+ }
+
+ public static class HEX implements Schema {
+ public static final Schema INSTANCE = new HEX();
+
+ private HEX() {
+ }
+
+ @Override
+ public String readFrom(ByteBuf input) {
+ return readFrom(input, input.readableBytes());
+ }
+
+ @Override
+ public String readFrom(ByteBuf input, int length) {
+ byte[] bytes = new byte[length];
+ input.readBytes(bytes);
+
+ CharsBuilder cb = new CharsBuilder(length << 1);
+ StringUtil.toHexStringPadded(cb, bytes);
+ return cb.toString();
+ }
+
+ @Override
+ public void writeTo(ByteBuf output, String value) {
+ writeTo(output, value.length() >> 1, value);
+ }
+
+ @Override
+ public void writeTo(ByteBuf output, int length, String value) {
+ int charLength = length << 1;
+ char[] chars = new char[charLength];
+ int i = charLength - value.length();
+ if (i >= 0) {
+ value.getChars(0, charLength - i, chars, i);
+ while (i > 0)
+ chars[--i] = '0';
+ } else {
+ value.getChars(-i, charLength - i, chars, 0);
+ log.info("字符长度超出限制: 长度[{}],[{}]", charLength, value);
+ }
+ byte[] src = StringUtil.decodeHexDump(new CharsBuilder(chars));
output.writeBytes(src);
}
}
diff --git a/src/main/java/io/github/yezhihao/protostar/util/Bcd.java b/src/main/java/io/github/yezhihao/protostar/util/Bcd.java
index 01ba79d..04435da 100644
--- a/src/main/java/io/github/yezhihao/protostar/util/Bcd.java
+++ b/src/main/java/io/github/yezhihao/protostar/util/Bcd.java
@@ -17,35 +17,6 @@ public class Bcd {
public static final int YEAR_RANGE = YEAR - 30;
public static final int HUNDRED_YEAR = YEAR_RANGE / 100 * 100;
- /** BCD转String */
- public static String toString(byte[] bcd) {
- return new String(toChars(bcd));
- }
-
- /** BCD转char[] */
- public static char[] toChars(byte[] bcd) {
- char[] chars = new char[bcd.length * 2];
- for (int i = 0, j = 0; i < bcd.length; i++) {
- chars[j++] = (char) (48 + (bcd[i] >> 4 & 0xf));
- chars[j++] = (char) (48 + (bcd[i] & 0xf));
- }
- return chars;
- }
-
- /** String转BCD */
- public static byte[] from(String str) {
- return from(str.toCharArray());
- }
-
- /** char[]转BCD */
- public static byte[] from(char[] chars) {
- byte[] bcd = new byte[chars.length / 2];
- for (int i = 0, j = 0; i < bcd.length; i++) {
- bcd[i] = (byte) ((chars[j++] - 48 << 4) | ((chars[j++] - 48 & 0xf)));
- }
- return bcd;
- }
-
/** 时间转BCD (yyMMddHHmmss) */
public static byte[] from(LocalDateTime dateTime) {
byte[] bcd = new byte[6];
@@ -113,10 +84,4 @@ public class Bcd {
public static int num(byte bcd) {
return (bcd >> 4 & 0xf) * 10 + (bcd & 0xf);
}
-
- public static int indexOf(char[] chars, char pad) {
- int i = 0, len = chars.length;
- while (i < len && chars[i] == pad) i++;
- return i;
- }
}
\ No newline at end of file
diff --git a/src/main/java/io/github/yezhihao/protostar/util/CharsBuilder.java b/src/main/java/io/github/yezhihao/protostar/util/CharsBuilder.java
new file mode 100644
index 0000000..e278b79
--- /dev/null
+++ b/src/main/java/io/github/yezhihao/protostar/util/CharsBuilder.java
@@ -0,0 +1,82 @@
+package io.github.yezhihao.protostar.util;
+
+import java.util.Arrays;
+
+public class CharsBuilder implements CharSequence, Appendable {
+
+ private char[] value;
+ private int pos;
+
+ public CharsBuilder(int length) {
+ this.value = new char[length];
+ }
+
+ public CharsBuilder(char[] chars) {
+ this.value = chars;
+ }
+
+ @Override
+ public Appendable append(CharSequence s) {
+ return append(s, 0, s.length());
+ }
+
+ @Override
+ public Appendable append(CharSequence s, int start, int end) {
+ int len = end - start;
+ for (int i = start, j = pos; i < end; i++, j++)
+ value[j] = s.charAt(i);
+ pos += len;
+ return this;
+ }
+
+ @Override
+ public Appendable append(char c) {
+ value[pos++] = c;
+ return this;
+ }
+
+ @Override
+ public char charAt(int index) {
+ return value[index];
+ }
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ if (start == end) {
+ return new CharsBuilder(Math.min(16, value.length));
+ }
+ return new CharsBuilder(Arrays.copyOfRange(value, start, end));
+ }
+
+ @Override
+ public int length() {
+ return value.length;
+ }
+
+ @Override
+ public String toString() {
+ return new String(value);
+ }
+
+ public String leftStrip(char c) {
+ int i = leftOf(value, c);
+ return new String(value, i, value.length - i);
+ }
+
+ public String rightStrip(char c) {
+ int i = rightOf(value, c);
+ return new String(value, 0, i);
+ }
+
+ public static int leftOf(char[] chars, char pad) {
+ int i = 0, len = chars.length;
+ while (i < len && chars[i] == pad) i++;
+ return i;
+ }
+
+ public static int rightOf(char[] chars, char pad) {
+ int i = 0, len = chars.length;
+ while ((i < len) && (chars[len - 1] <= pad)) len--;
+ return len;
+ }
+}
diff --git a/src/test/java/io/github/yezhihao/protostar/convert/AttributeConverterV2.java b/src/test/java/io/github/yezhihao/protostar/convert/AttributeConverterV2.java
new file mode 100644
index 0000000..51318e1
--- /dev/null
+++ b/src/test/java/io/github/yezhihao/protostar/convert/AttributeConverterV2.java
@@ -0,0 +1,35 @@
+package io.github.yezhihao.protostar.convert;
+
+import io.github.yezhihao.protostar.PrepareLoadStrategy;
+import io.github.yezhihao.protostar.converter.MapConverter;
+import io.github.yezhihao.protostar.schema.NumberSchema;
+import io.github.yezhihao.protostar.schema.StringSchema;
+import io.netty.buffer.ByteBuf;
+
+public class AttributeConverterV2 extends MapConverter {
+
+ @Override
+ protected void addSchemas(PrepareLoadStrategy schemaRegistry) {
+ schemaRegistry
+ .addSchema(1, NumberSchema.Int32.INSTANCE)
+ .addSchema(2, StringSchema.Chars.getInstance((byte) 0, "UTF-8"))
+
+ .addSchema(3, Attr1.class)
+ .addSchema(4, Attr2.Schema.INSTANCE);
+ }
+
+ @Override
+ protected Integer readKey(ByteBuf input) {
+ return (int) input.readUnsignedByte();
+ }
+
+ @Override
+ protected void writeKey(ByteBuf output, Integer key) {
+ output.writeByte(key);
+ }
+
+ @Override
+ protected int valueSize() {
+ return 1;
+ }
+}
\ No newline at end of file