deployed 2.0.5.RELEASE,修复集合类型长度域BUG

master
剑器近 2021-09-19 16:00:16 +08:00
parent b7a938ff4a
commit 44050e72ce
11 changed files with 154 additions and 82 deletions

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.yezhihao</groupId>
<artifactId>protostar</artifactId>
<version>2.0.4.RELEASE</version>
<version>2.0.5.RELEASE</version>
<packaging>jar</packaging>
<name>Protostar</name>

View File

@ -1,10 +1,7 @@
package io.github.yezhihao.protostar;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.field.BasicField;
import io.github.yezhihao.protostar.field.DynamicLengthField;
import io.github.yezhihao.protostar.field.FixedField;
import io.github.yezhihao.protostar.field.FixedLengthField;
import io.github.yezhihao.protostar.field.*;
import io.github.yezhihao.protostar.schema.*;
import java.nio.ByteBuffer;
@ -65,7 +62,7 @@ public abstract class FieldFactory {
fieldSchema = ConvertSchema.getInstance(field.converter());
break;
case LIST:
fieldSchema = CollectionSchema.getInstance(schema, field.lengthSize());
fieldSchema = CollectionSchema.getInstance(schema);
break;
case MAP:
fieldSchema = ConvertSchema.getInstance(field.converter());
@ -78,15 +75,21 @@ public abstract class FieldFactory {
BasicField result;
if (EXPLAIN) {
if (field.lengthSize() > 0) {
result = new DynamicLengthField.Logger(field, f, fieldSchema);
if (fieldSchema instanceof CollectionSchema)
result = new DynamicTotalField.Logger(field, f, fieldSchema);
else
result = new DynamicLengthField.Logger(field, f, fieldSchema);
} else if (field.length() > 0) {
result = new FixedLengthField.Logger(field, f, fieldSchema);
} else {
result = new FixedField.Logger(field, f, fieldSchema);
}
} else {
if (field.lengthSize() > 0 && !(fieldSchema instanceof CollectionSchema)) {
result = new DynamicLengthField(field, f, fieldSchema);
if (field.lengthSize() > 0) {
if (fieldSchema instanceof CollectionSchema)
result = new DynamicTotalField(field, f, fieldSchema);
else
result = new DynamicLengthField(field, f, fieldSchema);
} else if (field.length() > 0) {
result = new FixedLengthField(field, f, fieldSchema);
} else {

View File

@ -70,10 +70,10 @@ public abstract class MapConverter<K, V> extends PrepareLoadStrategy implements
if (schema != null) {
int lengthSize = valueSize();
int begin = output.writerIndex();
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
ByteBufUtils.writeInt(output, lengthSize, 0);
schema.writeTo(output, value);
int length = output.writerIndex() - begin - lengthSize;
ByteBufUtils.setInt(output, lengthSize, begin, length);
ByteBufUtils.setInt(output, begin, lengthSize, length);
} else {
log.warn("未注册的信息:ID[{}], VALUE[{}]", key, value);
}

View File

@ -30,9 +30,9 @@ public abstract class BasicField<T> implements Comparable<BasicField<T>> {
}
}
public abstract boolean readFrom(ByteBuf input, Object message) throws Exception;
public abstract boolean readFrom(ByteBuf input, T message) throws Exception;
public abstract void writeTo(ByteBuf output, Object message) throws Exception;
public abstract void writeTo(ByteBuf output, T message) throws Exception;
public void println(int index, String desc, String hex, Object value) {
if (value != null)

View File

@ -13,11 +13,11 @@ import io.netty.buffer.ByteBufUtil;
*/
public class DynamicLengthField<T> extends BasicField<T> {
protected final Schema<T> schema;
protected final Schema schema;
protected final int lengthSize;
public DynamicLengthField(Field field, java.lang.reflect.Field f, Schema<T> schema) {
public DynamicLengthField(Field field, java.lang.reflect.Field f, Schema schema) {
super(field, f);
this.schema = schema;
this.lengthSize = field.lengthSize();
@ -36,10 +36,10 @@ public class DynamicLengthField<T> extends BasicField<T> {
Object value = f.get(message);
if (value != null) {
int begin = output.writerIndex();
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
schema.writeTo(output, (T) value);
ByteBufUtils.writeInt(output, lengthSize, 0);
schema.writeTo(output, value);
int length = output.writerIndex() - begin - lengthSize;
ByteBufUtils.setInt(output, lengthSize, begin, length);
ByteBufUtils.setInt(output, begin, lengthSize, length);
}
}
@ -78,10 +78,10 @@ public class DynamicLengthField<T> extends BasicField<T> {
Object value = f.get(message);
if (value != null) {
int begin = output.writerIndex();
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
schema.writeTo(output, (T) value);
ByteBufUtils.writeInt(output, lengthSize, 0);
schema.writeTo(output, value);
int length = output.writerIndex() - begin - lengthSize;
ByteBufUtils.setInt(output, lengthSize, begin, length);
ByteBufUtils.setInt(output, begin, lengthSize, length);
}
int after = output.writerIndex();

View File

@ -0,0 +1,76 @@
package io.github.yezhihao.protostar.field;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.util.ByteBufUtils;
import io.github.yezhihao.protostar.util.StrUtils;
import io.netty.buffer.ByteBuf;
import java.util.Collection;
/**
*
* @author yezhihao
* home https://gitee.com/yezhihao/jt808-server
*/
public class DynamicTotalField<T> extends BasicField<T> {
protected final Schema<Collection<?>> schema;
protected final int totalSize;
public DynamicTotalField(Field field, java.lang.reflect.Field f, Schema schema) {
super(field, f);
this.schema = schema;
this.totalSize = field.lengthSize();
}
public boolean readFrom(ByteBuf input, Object message) throws Exception {
Object value = schema.readFrom(input, totalSize);
f.set(message, value);
return true;
}
public void writeTo(ByteBuf output, Object message) throws Exception {
Collection value = (Collection) f.get(message);
if (value != null)
schema.writeTo(output, totalSize, value);
}
@Override
public int compareTo(BasicField<T> that) {
int r = Integer.compare(this.index, that.index);
if (r == 0)
r = (that instanceof DynamicTotalField) ? 1 : -1;
return r;
}
public static class Logger<T> extends DynamicTotalField<T> {
public Logger(Field field, java.lang.reflect.Field f, Schema<T> schema) {
super(field, f, schema);
}
public boolean readFrom(ByteBuf input, Object message) throws Exception {
int total = ByteBufUtils.getInt(input, input.readerIndex(), totalSize);
String hex = StrUtils.leftPad(Integer.toHexString(total), totalSize << 1, '0');
println(this.index, this.field.desc() + "总数", hex, total);
Collection value = schema.readFrom(input, totalSize);
f.set(message, value);
return true;
}
public void writeTo(ByteBuf output, Object message) throws Exception {
Collection value = (Collection) f.get(message);
if (value != null) {
int total = value.size();
String hex = StrUtils.leftPad(Integer.toHexString(total), totalSize << 1, '0');
println(this.index, this.field.desc() + "总数", hex, total);
schema.writeTo(output, totalSize, value);
}
}
}
}

View File

@ -12,9 +12,9 @@ import io.netty.buffer.ByteBufUtil;
*/
public class FixedField<T> extends BasicField<T> {
protected final Schema<T> schema;
protected final Schema schema;
public FixedField(Field field, java.lang.reflect.Field f, Schema<T> schema) {
public FixedField(Field field, java.lang.reflect.Field f, Schema schema) {
super(field, f);
this.schema = schema;
}
@ -28,7 +28,7 @@ public class FixedField<T> extends BasicField<T> {
public void writeTo(ByteBuf output, Object message) throws Exception {
Object value = f.get(message);
if (value != null)
schema.writeTo(output, (T) value);
schema.writeTo(output, value);
}
public static class Logger<T> extends FixedField<T> {
@ -54,7 +54,7 @@ public class FixedField<T> extends BasicField<T> {
Object value = f.get(message);
if (value != null)
schema.writeTo(output, (T) value);
schema.writeTo(output, value);
int after = output.writerIndex();
String hex = ByteBufUtil.hexDump(output.slice(before, after - before));

View File

@ -12,7 +12,7 @@ import io.netty.buffer.ByteBufUtil;
*/
public class FixedLengthField<T> extends BasicField<T> {
protected final Schema<T> schema;
protected final Schema schema;
public FixedLengthField(Field field, java.lang.reflect.Field f, Schema<T> schema) {
super(field, f);
@ -28,7 +28,7 @@ public class FixedLengthField<T> extends BasicField<T> {
public void writeTo(ByteBuf output, Object message) throws Exception {
Object value = f.get(message);
if (value != null)
schema.writeTo(output, length, (T) value);
schema.writeTo(output, length, value);
}
public static class Logger<T> extends FixedLengthField<T> {
@ -54,7 +54,7 @@ public class FixedLengthField<T> extends BasicField<T> {
Object value = f.get(message);
if (value != null)
schema.writeTo(output, length, (T) value);
schema.writeTo(output, length, value);
int after = output.writerIndex();
String hex = ByteBufUtil.hexDump(output.slice(before, after - before));

View File

@ -6,77 +6,64 @@ import io.github.yezhihao.protostar.util.Cache;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
import java.util.Collection;
public class CollectionSchema<T> implements Schema<List<T>> {
public class CollectionSchema<T> implements Schema<Collection<T>> {
private static final Cache<String, CollectionSchema> CACHE = new Cache<>();
private static final Cache<Schema, CollectionSchema> CACHE = new Cache<>();
public static CollectionSchema getInstance(Schema schema, int lengthSize) {
return CACHE.get(schema.hashCode() + "_" + lengthSize, key -> new CollectionSchema(schema, lengthSize));
public static CollectionSchema getInstance(Schema schema) {
return CACHE.get(schema, key -> new CollectionSchema(key));
}
private final Schema<T> schema;
private final int lengthSize;
private CollectionSchema(Schema<T> schema, int lengthSize) {
private CollectionSchema(Schema<T> schema) {
this.schema = schema;
this.lengthSize = lengthSize;
}
@Override
public List<T> readFrom(ByteBuf input) {
public Collection<T> readFrom(ByteBuf input) {
if (!input.isReadable())
return null;
List<T> list;
if (lengthSize > 0) {
int length = ByteBufUtils.readInt(input, lengthSize);
list = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
T obj = schema.readFrom(input);
if (obj == null) break;
list.add(obj);
}
} else {
list = new ArrayList<>(2);
do {
T obj = schema.readFrom(input);
if (obj == null) break;
list.add(obj);
} while (input.isReadable());
Collection<T> list = new ArrayList<>(2);
do {
T obj = schema.readFrom(input);
if (obj == null) break;
list.add(obj);
} while (input.isReadable());
return list;
}
@Override
public Collection<T> readFrom(ByteBuf input, int totalSize) {
int total = ByteBufUtils.readInt(input, totalSize);
Collection<T> list = new ArrayList<>(total);
for (int i = 0; i < total; i++) {
T obj = schema.readFrom(input);
list.add(obj);
}
return list;
}
@Override
public List<T> readFrom(ByteBuf input, int length) {
int writerIndex = input.writerIndex();
input.writerIndex(input.readerIndex() + length);
List<T> result = this.readFrom(input);
input.writerIndex(writerIndex);
return result;
}
@Override
public void writeTo(ByteBuf output, List<T> list) {
public void writeTo(ByteBuf output, Collection<T> list) {
if (list == null || list.isEmpty())
return;
if (lengthSize > 0)
ByteBufUtils.writeInt(output, lengthSize, list.size());
for (T obj : list) {
schema.writeTo(output, obj);
}
}
@Override
public void writeTo(ByteBuf output, int length, List<T> list) {
public void writeTo(ByteBuf output, int totalSize, Collection<T> list) {
if (list == null || list.isEmpty())
return;
ByteBufUtils.writeInt(output, totalSize, list.size());
for (T obj : list) {
schema.writeTo(output, length, obj);
schema.writeTo(output, totalSize, obj);
}
}
}

View File

@ -9,13 +9,6 @@ import io.netty.buffer.ByteBuf;
*/
public class ByteBufUtils {
/** 长度域占位数据块 */
public static final byte[][] BLOCKS = new byte[][]{
new byte[0],
new byte[1], new byte[2],
new byte[3], new byte[4]};
public static int readInt(ByteBuf input, int length) {
int value;
switch (length) {
@ -56,20 +49,20 @@ public class ByteBufUtils {
}
}
public static int getInt(ByteBuf output, int length, int index) {
public static int getInt(ByteBuf input, int index, int length) {
int value;
switch (length) {
case 1:
value = output.getUnsignedByte(index);
value = input.getUnsignedByte(index);
break;
case 2:
value = output.getUnsignedShort(index);
value = input.getUnsignedShort(index);
break;
case 3:
value = output.getUnsignedMedium(index);
value = input.getUnsignedMedium(index);
break;
case 4:
value = output.getInt(index);
value = input.getInt(index);
break;
default:
throw new RuntimeException("unsupported length: " + length + " (expected: 1, 2, 3, 4)");
@ -77,7 +70,7 @@ public class ByteBufUtils {
return value;
}
public static void setInt(ByteBuf output, int length, int index, int value) {
public static void setInt(ByteBuf output, int index, int length, int value) {
switch (length) {
case 1:
output.setByte(index, value);

View File

@ -90,4 +90,17 @@ public class StrUtils {
return false;
return componentType.isArray();
}
public static String leftPad(String str, int size, char ch) {
int length = str.length();
int pads = size - length;
if (pads > 0) {
char[] result = new char[size];
str.getChars(0, length, result, pads);
while (pads > 0)
result[--pads] = ch;
return new String(result);
}
return str;
}
}