完成了数组的输出,内置了基本类型和包装类型,String的一维数组序列化器
parent
9a4dc656da
commit
c0e7307443
|
@ -18,11 +18,6 @@ public interface JfireSE
|
|||
return new JfireSEConfig().setRefTracking(support);
|
||||
}
|
||||
|
||||
static JfireSEConfig useCompile()
|
||||
{
|
||||
return new JfireSEConfig().useCompile();
|
||||
}
|
||||
|
||||
static JfireSEConfig staticRegisterClass(Class<?> clazz)
|
||||
{
|
||||
return new JfireSEConfig().staticRegisterClass(clazz);
|
||||
|
|
|
@ -5,13 +5,13 @@ import lombok.Data;
|
|||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class JfireSEConfig
|
||||
{
|
||||
private boolean refTracking = false;
|
||||
private boolean useCompile = false;
|
||||
private short staticClassId = 0;
|
||||
private StaticClasInfo[] clasInfos = new StaticClasInfo[10];
|
||||
private List<Class<?>> list = new LinkedList<>();
|
||||
|
@ -19,18 +19,14 @@ public class JfireSEConfig
|
|||
|
||||
public JfireSEConfig()
|
||||
{
|
||||
staticRegisterClass(ArrayList.class);
|
||||
staticRegisterClass(String.class);
|
||||
staticRegisterClass(HashSet.class);
|
||||
staticRegisterClass(HashMap.class);
|
||||
staticRegisterClass(ConcurrentHashMap.class);
|
||||
staticRegisterClass(ArrayList.class);
|
||||
staticRegisterClass(LinkedList.class);
|
||||
}
|
||||
|
||||
public JfireSEConfig useCompile()
|
||||
{
|
||||
useCompile = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JfireSEConfig refTracking()
|
||||
{
|
||||
refTracking = true;
|
||||
|
|
|
@ -23,7 +23,6 @@ public class JfireSEImpl implements JfireSE
|
|||
* 用于存储逆序列化过程中的临时信息
|
||||
*/
|
||||
private ClassInfo[] deSerializedClassInfos;
|
||||
private SerializerFactory serializerFactory = new SerializerFactory();
|
||||
private ByteArray byteArray = new ByteArray(1000);
|
||||
private ClassInfo classInfoCache;
|
||||
private Map<Class<?>, ClassInfo> classInfoMap = new HashMap<>();
|
||||
|
@ -61,7 +60,7 @@ public class JfireSEImpl implements JfireSE
|
|||
DynamicClassInfo dynamicClassInfo = new DynamicClassInfo((short) dyncmicClassId, clazz, refTracking);
|
||||
serializedClassInfos[dyncmicClassId] = dynamicClassInfo;
|
||||
dyncmicClassId++;
|
||||
Serializer serializer = serializerFactory.getSerializer(clazz, this);
|
||||
Serializer serializer = SerializerFactory.getSerializer(clazz, this);
|
||||
dynamicClassInfo.setSerializer(serializer);
|
||||
classInfoCache = dynamicClassInfo;
|
||||
return dynamicClassInfo;
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.Arrays;
|
||||
|
||||
@Data
|
||||
public abstract class ClassInfo
|
||||
public abstract class ClassInfo implements RefTracking
|
||||
{
|
||||
protected final short classId;
|
||||
protected final byte[] classNameBytes;
|
||||
|
@ -29,6 +29,7 @@ public abstract class ClassInfo
|
|||
classNameBytes = clazz.getName().getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addTracking(Object instance)
|
||||
{
|
||||
if (tracking == null)
|
||||
|
@ -61,8 +62,20 @@ public abstract class ClassInfo
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 进行完整的对象实例化,并且根据初始配置情况自动决定是否放入追踪。
|
||||
*
|
||||
* @param byteArray
|
||||
* @param instance
|
||||
*/
|
||||
public abstract void write(ByteArray byteArray, Object instance);
|
||||
|
||||
/**
|
||||
* 进行完整的对象实例化,但是是在已知对象类型的情况。输出的标志位只在 3 个中可选。
|
||||
*
|
||||
* @param byteArray
|
||||
* @param instance
|
||||
*/
|
||||
public void writeKnownClazz(ByteArray byteArray, Object instance)
|
||||
{
|
||||
if (refTrack)
|
||||
|
@ -87,40 +100,30 @@ public abstract class ClassInfo
|
|||
}
|
||||
|
||||
/**
|
||||
* 读取对象的内容,并且这个对象本身要放入追踪
|
||||
* 读取对象的内容,并且这个对象本身要放入追踪。
|
||||
* 这个读取意味着标志位和标志信息已经被读取完毕,此时只是单纯读取对象实例的序列化内容。
|
||||
*
|
||||
* @param byteArray
|
||||
* @return
|
||||
*/
|
||||
public Object readWithTrack(ByteArray byteArray)
|
||||
{
|
||||
try
|
||||
{
|
||||
Object instance = UNSAFE.allocateInstance(clazz);
|
||||
addTracking(instance);
|
||||
serializer.read(byteArray, instance);
|
||||
return instance;
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return serializer.read(byteArray, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取对象的内容,但是这个对象本身不放入追踪。
|
||||
* 这个读取意味着标志位和标志信息已经被读取完毕,此时只是单纯读取对象实例的序列化内容。
|
||||
*
|
||||
* @param byteArray
|
||||
* @return
|
||||
*/
|
||||
public Object readWithoutTrack(ByteArray byteArray)
|
||||
{
|
||||
try
|
||||
{
|
||||
Object instance = UNSAFE.allocateInstance(clazz);
|
||||
serializer.read(byteArray, instance);
|
||||
return instance;
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return serializer.read(byteArray, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getInstanceById(int instanceId)
|
||||
{
|
||||
return tracking[instanceId];
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package com.jfirer.se2.classinfo;
|
||||
|
||||
public interface RefTracking
|
||||
{
|
||||
int addTracking(Object instance);
|
||||
|
||||
Object getInstanceById(int instanceId);
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.jfirer.se2.serializer;
|
||||
|
||||
import com.jfirer.se2.ByteArray;
|
||||
import com.jfirer.se2.classinfo.RefTracking;
|
||||
|
||||
public interface Serializer
|
||||
{
|
||||
|
@ -12,5 +13,13 @@ public interface Serializer
|
|||
*/
|
||||
void writeBytes(ByteArray byteArray, Object instance);
|
||||
|
||||
void read(ByteArray byteArray, Object instance);
|
||||
/**
|
||||
* 逆序列化并且输出对象实例本身。
|
||||
* 如果有传入 refTracking 对象,则创建对象实例后,需要首先通过 addTracking 方法将对象实例添加到追踪列表中
|
||||
*
|
||||
* @param byteArray
|
||||
* @param refTracking
|
||||
* @return
|
||||
*/
|
||||
Object read(ByteArray byteArray, RefTracking refTracking);
|
||||
}
|
||||
|
|
|
@ -1,19 +1,48 @@
|
|||
package com.jfirer.se2.serializer;
|
||||
|
||||
import com.jfirer.se2.JfireSEImpl;
|
||||
import com.jfirer.se2.serializer.impl.ArraySerializer;
|
||||
import com.jfirer.se2.serializer.impl.BoxedArraySerializer;
|
||||
import com.jfirer.se2.serializer.impl.ObjectSerializer.ObjectSerializer;
|
||||
import com.jfirer.se2.serializer.impl.PrimitiveArraySerializer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SerializerFactory
|
||||
{
|
||||
private Map<Class<?>, Serializer> store = new HashMap<>();
|
||||
private static Map<Class<?>, Serializer> store = new ConcurrentHashMap<>();
|
||||
|
||||
public Serializer getSerializer(Class<?> clazz, JfireSEImpl jfireSE)
|
||||
static
|
||||
{
|
||||
Serializer objectSerializer = ObjectSerializer.buildCompileVersion(clazz, jfireSE);
|
||||
store.putIfAbsent(clazz, objectSerializer);
|
||||
return objectSerializer;
|
||||
store.put(int[].class, new PrimitiveArraySerializer.IntArraySerializer());
|
||||
store.put(long[].class, new PrimitiveArraySerializer.LongArraySerializer());
|
||||
store.put(byte[].class, new PrimitiveArraySerializer.ByteArraySerializer());
|
||||
store.put(boolean[].class, new PrimitiveArraySerializer.BooleanArraySerializer());
|
||||
store.put(char[].class, new PrimitiveArraySerializer.CharArraySerializer());
|
||||
store.put(short[].class, new PrimitiveArraySerializer.ShortArraySerializer());
|
||||
store.put(double[].class, new PrimitiveArraySerializer.DoubleArraySerializer());
|
||||
store.put(float[].class, new PrimitiveArraySerializer.FloatArraySerializer());
|
||||
store.put(Integer[].class, new BoxedArraySerializer.IntegerArraySerializer());
|
||||
store.put(Long[].class, new BoxedArraySerializer.LongArraySerializer());
|
||||
store.put(Byte[].class, new BoxedArraySerializer.ByteArraySerializer());
|
||||
store.put(Boolean[].class, new BoxedArraySerializer.BooleanArraySerializer());
|
||||
store.put(Character[].class, new BoxedArraySerializer.CharArraySerializer());
|
||||
store.put(Short[].class, new BoxedArraySerializer.ShortArraySerializer());
|
||||
store.put(Double[].class, new BoxedArraySerializer.DoubleArraySerializer());
|
||||
store.put(Float[].class, new BoxedArraySerializer.FloatArraySerializer());
|
||||
store.put(String[].class, new BoxedArraySerializer.StringArraySerializer());
|
||||
}
|
||||
|
||||
public static Serializer getSerializer(Class<?> clazz, JfireSEImpl jfireSE)
|
||||
{
|
||||
if (clazz.isArray())
|
||||
{
|
||||
return store.computeIfAbsent(clazz, key -> new ArraySerializer(key, jfireSE));
|
||||
}
|
||||
else
|
||||
{
|
||||
return store.computeIfAbsent(clazz, key -> ObjectSerializer.buildCompileVersion(key, jfireSE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,14 @@ import com.jfirer.se2.ByteArray;
|
|||
import com.jfirer.se2.JfireSE;
|
||||
import com.jfirer.se2.JfireSEImpl;
|
||||
import com.jfirer.se2.classinfo.ClassInfo;
|
||||
import com.jfirer.se2.classinfo.RefTracking;
|
||||
import com.jfirer.se2.serializer.Serializer;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class ArraySerializer<T> implements Serializer
|
||||
{
|
||||
private Class<?> componentType;
|
||||
private final boolean isFinal;
|
||||
private final ClassInfo typeDefinedClassInfo;
|
||||
private JfireSEImpl jfireSE;
|
||||
|
||||
|
@ -21,7 +20,6 @@ public class ArraySerializer<T> implements Serializer
|
|||
this.jfireSE = jfireSE;
|
||||
this.componentType = clazz.getComponentType();
|
||||
typeDefinedClassInfo = jfireSE.getOrCreateClassInfo(componentType);
|
||||
isFinal = Modifier.isFinal(componentType.getModifiers());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,11 +49,17 @@ public class ArraySerializer<T> implements Serializer
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void read(ByteArray byteArray, Object instance)
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int len = byteArray.readPositiveVarInt();
|
||||
T[] arr = (T[]) Array.newInstance(componentType, len);
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
T[] arr = (T[]) Array.newInstance(componentType, length);
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
byte flag = byteArray.get();
|
||||
|
@ -69,16 +73,47 @@ public class ArraySerializer<T> implements Serializer
|
|||
{
|
||||
case JfireSE.NAME_ID_CONTENT_TRACK ->
|
||||
{
|
||||
byte[] bytes = byteArray.readBytesWithSizeEmbedded();
|
||||
int i1 = byteArray.readVarInt();
|
||||
byte[] classNameBytes = byteArray.readBytesWithSizeEmbedded();
|
||||
int classId = byteArray.readPositiveVarInt();
|
||||
ClassInfo classInfo = jfireSE.find(classNameBytes, classId);
|
||||
arr[i] = (T) classInfo.readWithTrack(byteArray);
|
||||
}
|
||||
case JfireSE.NAME_ID_CONTENT_UN_TRACK ->
|
||||
{
|
||||
byte[] classNameBytes = byteArray.readBytesWithSizeEmbedded();
|
||||
int classId = byteArray.readPositiveVarInt();
|
||||
ClassInfo classInfo = jfireSE.find(classNameBytes, classId);
|
||||
arr[i] = (T) classInfo.readWithoutTrack(byteArray);
|
||||
}
|
||||
case JfireSE.ID_INSTANCE_ID ->
|
||||
{
|
||||
int classId = byteArray.readPositiveVarInt();
|
||||
ClassInfo classInfo = jfireSE.find(classId);
|
||||
arr[i] = (T) classInfo.getInstanceById(byteArray.readPositiveVarInt());
|
||||
}
|
||||
case JfireSE.ID_CONTENT_TRACK ->
|
||||
{
|
||||
int classId = byteArray.readPositiveVarInt();
|
||||
ClassInfo classInfo = jfireSE.find(classId);
|
||||
arr[i] = (T) classInfo.readWithTrack(byteArray);
|
||||
}
|
||||
case JfireSE.ID_CONTENT_UN_TRACK ->
|
||||
{
|
||||
int classId = byteArray.readPositiveVarInt();
|
||||
ClassInfo classInfo = jfireSE.find(classId);
|
||||
arr[i] = (T) classInfo.readWithoutTrack(byteArray);
|
||||
}
|
||||
case JfireSE.INSTANCE_ID ->
|
||||
{
|
||||
int instanceId = byteArray.readPositiveVarInt();
|
||||
arr[i] = (T) typeDefinedClassInfo.getInstanceById(instanceId);
|
||||
}
|
||||
case JfireSE.CONTENT_TRACK -> arr[i] = (T) typeDefinedClassInfo.readWithTrack(byteArray);
|
||||
case JfireSE.CONTENT_UN_TRACK -> arr[i] = (T) typeDefinedClassInfo.readWithoutTrack(byteArray);
|
||||
default -> throw new RuntimeException("未知的序列化类型");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
ArraySerializer<Integer> arraySerializer = new ArraySerializer(Integer[].class, (JfireSEImpl) JfireSE.build());
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,422 @@
|
|||
package com.jfirer.se2.serializer.impl;
|
||||
|
||||
import com.jfirer.se2.ByteArray;
|
||||
import com.jfirer.se2.JfireSE;
|
||||
import com.jfirer.se2.classinfo.RefTracking;
|
||||
import com.jfirer.se2.serializer.Serializer;
|
||||
|
||||
public abstract class BoxedArraySerializer<T> implements Serializer
|
||||
{
|
||||
public static class IntegerArraySerializer extends BoxedArraySerializer<Integer[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
Integer[] arr = (Integer[]) instance;
|
||||
byteArray.writePositiveVarInt(arr.length);
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
Integer each = arr[i];
|
||||
if (each == null)
|
||||
{
|
||||
byteArray.put(JfireSE.NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteArray.put(JfireSE.NOT_NULL);
|
||||
byteArray.writeVarInt(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
Integer[] arr = new Integer[length];
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (byteArray.get() == JfireSE.NULL)
|
||||
{
|
||||
arr[i] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[i] = byteArray.readVarInt();
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LongArraySerializer extends BoxedArraySerializer<Long[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
Long[] arr = (Long[]) instance;
|
||||
byteArray.writePositiveVarInt(arr.length);
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
Long each = arr[i];
|
||||
if (each == null)
|
||||
{
|
||||
byteArray.put(JfireSE.NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteArray.put(JfireSE.NOT_NULL);
|
||||
byteArray.writeVarLong(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
Long[] arr = new Long[length];
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (byteArray.get() == JfireSE.NULL)
|
||||
{
|
||||
arr[i] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[i] = byteArray.readVarLong();
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FloatArraySerializer extends BoxedArraySerializer<Float[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
Float[] arr = (Float[]) instance;
|
||||
byteArray.writePositiveVarInt(arr.length);
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
Float each = arr[i];
|
||||
if (each == null)
|
||||
{
|
||||
byteArray.put(JfireSE.NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteArray.put(JfireSE.NOT_NULL);
|
||||
byteArray.writeFloat(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
Float[] arr = new Float[length];
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (byteArray.get() == JfireSE.NULL)
|
||||
{
|
||||
arr[i] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[i] = byteArray.readFloat();
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DoubleArraySerializer extends BoxedArraySerializer<Double[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
Double[] arr = (Double[]) instance;
|
||||
byteArray.writePositiveVarInt(arr.length);
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
Double each = arr[i];
|
||||
if (each == null)
|
||||
{
|
||||
byteArray.put(JfireSE.NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteArray.put(JfireSE.NOT_NULL);
|
||||
byteArray.writeDouble(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
Double[] arr = new Double[length];
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (byteArray.get() == JfireSE.NULL)
|
||||
{
|
||||
arr[i] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[i] = byteArray.readDouble();
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ByteArraySerializer extends BoxedArraySerializer<Byte[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
Byte[] arr = (Byte[]) instance;
|
||||
byteArray.writePositiveVarInt(arr.length);
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
Byte each = arr[i];
|
||||
if (each == null)
|
||||
{
|
||||
byteArray.put(JfireSE.NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteArray.put(JfireSE.NOT_NULL);
|
||||
byteArray.put(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
Byte[] arr = new Byte[length];
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (byteArray.get() == JfireSE.NULL)
|
||||
{
|
||||
arr[i] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[i] = byteArray.get();
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BooleanArraySerializer extends BoxedArraySerializer<Boolean[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
Boolean[] arr = (Boolean[]) instance;
|
||||
byteArray.writePositiveVarInt(arr.length);
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
Boolean each = arr[i];
|
||||
if (each == null)
|
||||
{
|
||||
byteArray.put(JfireSE.NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteArray.put(JfireSE.NOT_NULL);
|
||||
byteArray.writeBoolean(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
Boolean[] arr = new Boolean[length];
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (byteArray.get() == JfireSE.NULL)
|
||||
{
|
||||
arr[i] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[i] = byteArray.readBoolean();
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CharArraySerializer extends BoxedArraySerializer<Character[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
Character[] arr = (Character[]) instance;
|
||||
byteArray.writePositiveVarInt(arr.length);
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
Character each = arr[i];
|
||||
if (each == null)
|
||||
{
|
||||
byteArray.put(JfireSE.NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteArray.put(JfireSE.NOT_NULL);
|
||||
byteArray.writeChar(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
Character[] arr = new Character[length];
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (byteArray.get() == JfireSE.NULL)
|
||||
{
|
||||
arr[i] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[i] = byteArray.readChar();
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static class ShortArraySerializer extends PrimitiveArraySerializer<Short[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
Short[] arr = (Short[]) instance;
|
||||
byteArray.writePositiveVarInt(arr.length);
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
Short each = arr[i];
|
||||
if (each == null)
|
||||
{
|
||||
byteArray.put(JfireSE.NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteArray.put(JfireSE.NOT_NULL);
|
||||
byteArray.writeShort(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
Short[] arr = new Short[length];
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (byteArray.get() == JfireSE.NULL)
|
||||
{
|
||||
arr[i] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[i] = byteArray.readShort();
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
public static class StringArraySerializer extends BoxedArraySerializer<String[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
String[] arr = (String[]) instance;
|
||||
byteArray.writePositiveVarInt(arr.length);
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
String each = arr[i];
|
||||
if (each == null)
|
||||
{
|
||||
byteArray.put(JfireSE.NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteArray.put(JfireSE.NOT_NULL);
|
||||
byteArray.writeString(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int length = byteArray.readPositiveVarInt();
|
||||
String[] arr = new String[length];
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(arr);
|
||||
}
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (byteArray.get() == JfireSE.NULL)
|
||||
{
|
||||
arr[i] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[i] = byteArray.readString();
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import com.jfirer.se2.ByteArray;
|
|||
import com.jfirer.se2.JfireSE;
|
||||
import com.jfirer.se2.JfireSEImpl;
|
||||
import com.jfirer.se2.classinfo.ClassInfo;
|
||||
import com.jfirer.se2.classinfo.RefTracking;
|
||||
import com.jfirer.se2.serializer.Serializer;
|
||||
import io.github.karlatemp.unsafeaccessor.Unsafe;
|
||||
|
||||
|
@ -22,13 +23,15 @@ import java.util.function.Predicate;
|
|||
|
||||
public class ObjectSerializer implements Serializer
|
||||
{
|
||||
private FieldInfo[] fieldInfos;
|
||||
private final FieldInfo[] fieldInfos;
|
||||
private final Class<?> clazz;
|
||||
private static int COMPILE_COUNT = 1;
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
|
||||
public ObjectSerializer(Class<?> clazz, JfireSEImpl jfireSE)
|
||||
{
|
||||
fieldInfos = parse(clazz, jfireSE).toArray(FieldInfo[]::new);
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,11 +44,24 @@ public class ObjectSerializer implements Serializer
|
|||
}
|
||||
|
||||
@Override
|
||||
public void read(ByteArray byteArray, Object instance)
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
for (FieldInfo each : fieldInfos)
|
||||
try
|
||||
{
|
||||
each.read(byteArray, instance);
|
||||
Object instance = UNSAFE.allocateInstance(clazz);
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(instance);
|
||||
}
|
||||
for (FieldInfo each : fieldInfos)
|
||||
{
|
||||
each.read(byteArray, instance);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +113,7 @@ public class ObjectSerializer implements Serializer
|
|||
COMPILE_COUNT++;
|
||||
classModel.addInterface(Serializer.class);
|
||||
classModel.addImport(Unsafe.class);
|
||||
classModel.addImport(RefTracking.class);
|
||||
classModel.addImport(JfireSEImpl.class);
|
||||
classModel.addImport(JfireSE.class);
|
||||
classModel.addImport(Integer.class);
|
||||
|
@ -113,18 +130,21 @@ public class ObjectSerializer implements Serializer
|
|||
classModel.addImport(ByteArray.class);
|
||||
classModel.addField(new FieldModel("UNSAFE", Unsafe.class, "Unsafe.getUnsafe()", classModel));
|
||||
classModel.addField(new FieldModel("jfireSE", JfireSEImpl.class, classModel));
|
||||
classModel.addField(new FieldModel("clazz", Class.class, classModel));
|
||||
ConstructorModel constructorModel = new ConstructorModel(classModel);
|
||||
constructorModel.setParamTypes(Class.class, JfireSEImpl.class, List.class);
|
||||
constructorModel.setParamNames("clazz", "jfireSE", "list");
|
||||
StringBuilder constructorBody = new StringBuilder();
|
||||
constructorBody.append("this.jfireSE=jfireSE;\r\n");
|
||||
constructorBody.append("""
|
||||
this.jfireSE=jfireSE;
|
||||
this.clazz=clazz;""");
|
||||
try
|
||||
{
|
||||
MethodModel writeMethod = new MethodModel(Serializer.class.getDeclaredMethod("writeBytes", ByteArray.class, Object.class), classModel);
|
||||
writeMethod.setParamterNames("byteArray", "instance");
|
||||
StringBuilder writeBody = new StringBuilder();
|
||||
MethodModel readMethod = new MethodModel(Serializer.class.getDeclaredMethod("read", ByteArray.class, Object.class), classModel);
|
||||
readMethod.setParamterNames("byteArray", "instance");
|
||||
MethodModel readMethod = new MethodModel(Serializer.class.getDeclaredMethod("read", ByteArray.class, RefTracking.class), classModel);
|
||||
readMethod.setParamterNames("byteArray", "refTracking");
|
||||
StringBuilder readBody = new StringBuilder();
|
||||
int fieldIndex = 0;
|
||||
for (FieldInfo fieldInfo : parse)
|
||||
|
@ -582,7 +602,20 @@ public class ObjectSerializer implements Serializer
|
|||
constructorModel.setBody(constructorBody.toString());
|
||||
classModel.addConstructor(constructorModel);
|
||||
writeMethod.setBody(writeBody.toString());
|
||||
readMethod.setBody(readBody.toString());
|
||||
readBody.append("return instance;\r\n");
|
||||
readMethod.setBody("""
|
||||
Object instance;
|
||||
try{
|
||||
instance = UNSAFE.allocateInstance(clazz);
|
||||
}catch (InstantiationException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if(refTracking!=null)
|
||||
{
|
||||
refTracking.addTracking(instance);
|
||||
}
|
||||
""" + readBody);
|
||||
classModel.putMethodModel(writeMethod);
|
||||
classModel.putMethodModel(readMethod);
|
||||
CompileHelper compiler = new CompileHelper(Thread.currentThread().getContextClassLoader());
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
package com.jfirer.se2.serializer.impl;
|
||||
|
||||
import com.jfirer.se2.ByteArray;
|
||||
import com.jfirer.se2.classinfo.RefTracking;
|
||||
import com.jfirer.se2.serializer.Serializer;
|
||||
|
||||
public abstract class PrimitiveArraySerializer<T> implements Serializer
|
||||
{
|
||||
public static class IntArraySerializer extends PrimitiveArraySerializer<int[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
int[] arr = (int[]) instance;
|
||||
byteArray.writeIntsWithSizeEmbedded(arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
int[] ints = byteArray.readIntsWithSizeEmbedded();
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(ints);
|
||||
}
|
||||
return ints;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LongArraySerializer extends PrimitiveArraySerializer<long[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
long[] arr = (long[]) instance;
|
||||
byteArray.writeLongsWithSizeEmbedded(arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
long[] longs = byteArray.readLongsWithSizeEmbedded();
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(longs);
|
||||
}
|
||||
return longs;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FloatArraySerializer extends PrimitiveArraySerializer<float[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
float[] arr = (float[]) instance;
|
||||
byteArray.writeFloatsWithSizeEmbedded(arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
float[] floats = byteArray.readFloatsWithSizeEmbedded();
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(floats);
|
||||
}
|
||||
return floats;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DoubleArraySerializer extends PrimitiveArraySerializer<double[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
double[] arr = (double[]) instance;
|
||||
byteArray.writeDoublesWithSizeEmbedded(arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
double[] doubles = byteArray.readDoublesWithSizeEmbedded();
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(doubles);
|
||||
}
|
||||
return doubles;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BooleanArraySerializer extends PrimitiveArraySerializer<boolean[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
boolean[] arr = (boolean[]) instance;
|
||||
byteArray.writeBooleansWithSizeEmbedded(arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
boolean[] booleans = byteArray.readBooleansWithSizeEmbedded();
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(booleans);
|
||||
}
|
||||
return booleans;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ByteArraySerializer extends PrimitiveArraySerializer<byte[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
byte[] arr = (byte[]) instance;
|
||||
byteArray.writeBytesWithSizeEmbedded(arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
byte[] bytes = byteArray.readBytesWithSizeEmbedded();
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(bytes);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CharArraySerializer extends PrimitiveArraySerializer<char[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
char[] arr = (char[]) instance;
|
||||
byteArray.writeCharsWithSizeEmbedded(arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
char[] chars = byteArray.readCharsWithSizeEmbedded();
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(chars);
|
||||
}
|
||||
return chars;
|
||||
}
|
||||
}
|
||||
public static class ShortArraySerializer extends PrimitiveArraySerializer<short[]>
|
||||
{
|
||||
@Override
|
||||
public void writeBytes(ByteArray byteArray, Object instance)
|
||||
{
|
||||
short[] arr = (short[]) instance;
|
||||
byteArray.writeShortsWithSizeEmbedded(arr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(ByteArray byteArray, RefTracking refTracking)
|
||||
{
|
||||
short[] shorts = byteArray.readShortsWithSizeEmbedded();
|
||||
if (refTracking != null)
|
||||
{
|
||||
refTracking.addTracking(shorts);
|
||||
}
|
||||
return shorts;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@ import com.jfirer.fse.Fse;
|
|||
import com.jfirer.se2.JfireSE;
|
||||
import io.fury.Fury;
|
||||
import io.fury.config.Language;
|
||||
import org.example.sm.TestDataSm;
|
||||
import org.example.sm2.TestDataSm2;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.RunnerException;
|
||||
|
|
|
@ -3,6 +3,8 @@ package org.example;
|
|||
import com.jfirer.se2.ByteArray;
|
||||
import com.jfirer.se2.JfireSE;
|
||||
import io.fury.Fury;
|
||||
import org.example.sm.TestDataSm;
|
||||
import org.example.sm2.TestDataSm2;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -31,10 +33,15 @@ public class FunctionTest
|
|||
testData.setB(true);
|
||||
testData.setTestDataSm(sm);
|
||||
testData.setTestDataSm2(new TestDataSm2());
|
||||
TestDataSm[] sms = new TestDataSm[2];
|
||||
sms[0] = new TestDataSm().setC("xx");
|
||||
testData.setSms(sms);
|
||||
JfireSE jfireSE = JfireSE.build();
|
||||
byte[] bytes = jfireSE.write(testData);
|
||||
Assert.assertEquals(testData, jfireSE.read(bytes));
|
||||
Assert.assertEquals(sm, testData.getTestDataSm());
|
||||
TestData read = (TestData) jfireSE.read(bytes);
|
||||
Assert.assertEquals("xx", read.getSms()[0].getC());
|
||||
Assert.assertNull(read.getSms()[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -2,22 +2,25 @@ package org.example;
|
|||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.example.sm.TestDataSm;
|
||||
import org.example.sm2.TestDataSm2;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TestData
|
||||
{
|
||||
private int a = 213212312;
|
||||
private boolean b = false;
|
||||
private char c = 'c';
|
||||
private byte d = 0x11;
|
||||
private short e = 24;
|
||||
private long f = 1213124131312321L;
|
||||
private double g = 231321.2132;
|
||||
private float h = (float) 4986.2;
|
||||
private int a = 213212312;
|
||||
private boolean b = false;
|
||||
private char c = 'c';
|
||||
private byte d = 0x11;
|
||||
private short e = 24;
|
||||
private long f = 1213124131312321L;
|
||||
private double g = 231321.2132;
|
||||
private float h = (float) 4986.2;
|
||||
private String i = "123452312316789a";
|
||||
private TestDataSm testDataSm;
|
||||
private TestDataSm2 testDataSm2;
|
||||
private TestDataSm testDataSm;
|
||||
private TestDataSm2 testDataSm2;
|
||||
private TestDataSm[] sms;
|
||||
// private int[] j = new int[]{1, 2, 4, 5};
|
||||
// private boolean[] k = new boolean[]{true, false, true, false, false, false, true};
|
||||
// private char[] l = new char[]{'a', 'v', 'q', 'j', 'h', 'e', 'f'};
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package org.example;
|
||||
package org.example.sm;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TestDataSm
|
||||
{
|
||||
private int a = 10;
|
|
@ -1,4 +1,4 @@
|
|||
package org.example;
|
||||
package org.example.sm2;
|
||||
|
||||
import lombok.Data;
|
||||
|
Loading…
Reference in New Issue