master
linbin 2024-04-11 18:04:16 +08:00
commit 41f69f0769
12 changed files with 1296 additions and 0 deletions

38
.gitignore vendored 100644
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

6
.idea/.gitignore vendored 100644
View File

@ -0,0 +1,6 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

48
pom.xml 100644
View File

@ -0,0 +1,48 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>JfireSE</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>JfireSE</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jfirer</groupId>
<artifactId>baseutil</artifactId>
<version>1.1.7-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,103 @@
package com.jfirer.se;
public class ByteArray
{
protected byte[] array;
protected int writePosi = 0;
protected int readIndex = 0;
protected boolean needCheck = true;
protected ByteArray(int size)
{
array = new byte[size];
}
protected ByteArray(byte[] array)
{
this.array = array;
}
public static ByteArray allocate(int size)
{
return new InternalByteArray(size);
}
public static ByteArray allocate()
{
return new InternalByteArray(1024);
}
public static ByteArray wrap(byte[] array)
{
return new InternalByteArray(array);
}
public void setNeedCheck(boolean needCheck)
{
this.needCheck = needCheck;
}
protected void ensureCapacity(int len)
{
if (needCheck && len > array.length - writePosi)
{
int newLen = len + writePosi > (array.length << 1) ? len + writePosi + array.length : (array.length << 1);
byte[] tmp = new byte[newLen];
System.arraycopy(array, 0, tmp, 0, array.length);
array = tmp;
}
}
public void clear()
{
writePosi = readIndex = 0;
}
public void put(byte value)
{
ensureCapacity(1);
array[writePosi] = value;
writePosi += 1;
}
public void setByte(int off, byte b)
{
array[off] = b;
}
public void put(byte[] data)
{
ensureCapacity(data.length);
System.arraycopy(data, 0, array, writePosi, data.length);
writePosi += data.length;
}
public byte get()
{
byte result = array[readIndex];
readIndex += 1;
return result;
}
public byte[] toArray()
{
byte[] result = new byte[writePosi];
System.arraycopy(array, 0, result, 0, writePosi);
return result;
}
public int getWritePosi()
{
return writePosi;
}
public void setWritePosi(int writePosi)
{
this.writePosi = writePosi;
}
public void setReadPosi(int readPosi)
{
this.readIndex = readPosi;
}
}

View File

@ -0,0 +1,130 @@
package com.jfirer.se;
import com.jfirer.se.serializer.Serializer;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class ClassInfo
{
private int classId = ClassInfoResolver.NO_CLASS_ID;
private Class clazz;
private String className;
private Serializer serializer;
private JfireSE jfireSE;
private Object[] refTracking;
private int refTrackingIndex = 0;
public void writeBytes(InternalByteArray byteArray, Object instance, boolean knownClazz)
{
if (instance == null)
{
byteArray.put(JfireSE.NULL);
return;
}
if (serializer == null)
{
serializer = jfireSE.getSerializer(clazz);
}
if (knownClazz)
{
if (jfireSE.isCycleSupport())
{
int tracking = addTracking(instance);
if (tracking == -1)
{
byteArray.put((byte) 7);
serializer.writeBytes(byteArray, instance);
}
else
{
byteArray.put((byte) 9);
byteArray.writeVarInt(tracking);
}
}
else
{
byteArray.put((byte) 8);
serializer.writeBytes(byteArray, instance);
}
}
else
{
if (jfireSE.isCycleSupport())
{
if (classId == ClassInfoResolver.NO_CLASS_ID)
{
byteArray.put((byte) 1);
byteArray.writeString(className);
jfireSE.getClassId(this);
addTracking(instance);
serializer.writeBytes(byteArray, instance);
}
else
{
int tracking = addTracking(instance);
if (tracking == -1)
{
byteArray.put((byte) 4);
byteArray.writeVarInt(classId);
serializer.writeBytes(byteArray, instance);
}
else
{
byteArray.put((byte) 6);
byteArray.writeVarInt(classId);
byteArray.writeVarInt(tracking);
}
}
}
else
{
jfireSE.incrDepth();
if (classId == ClassInfoResolver.NO_CLASS_ID)
{
byteArray.put((byte) 2);
byteArray.writeString(className);
jfireSE.getClassId(this);
serializer.writeBytes(byteArray, instance);
}
else
{
byteArray.put((byte) 5);
byteArray.writeVarInt(classId);
serializer.writeBytes(byteArray, instance);
}
jfireSE.reduceDepth();
}
}
}
public void reset()
{
classId = ClassInfoResolver.NO_CLASS_ID;
refTrackingIndex = 0;
}
public int addTracking(Object instance)
{
if (refTracking == null)
{
refTracking = new Object[4];
}
for (int i = 0; i < refTrackingIndex; i++)
{
if (refTracking[i] == instance)
{
return i;
}
}
if (refTrackingIndex == refTracking.length)
{
Object[] newRefTracking = new Object[refTracking.length * 2];
System.arraycopy(refTracking, 0, newRefTracking, 0, refTracking.length);
refTracking = newRefTracking;
}
refTracking[refTrackingIndex++] = instance;
return -1;
}
}

View File

@ -0,0 +1,83 @@
package com.jfirer.se;
import com.jfirer.se.serializer.SerializerResolver;
import java.util.IdentityHashMap;
import java.util.Map;
public class ClassInfoResolver
{
public static int NO_CLASS_ID = 0;
private Map<Class, ClassInfo> store = new IdentityHashMap<>();
private int currentClassId = 1;
private int fixedClassId = 1;
private ClassInfo[] tracking = new ClassInfo[32];
private JfireSE jfireSE;
private SerializerResolver resolver;
public ClassInfoResolver(SerializerResolver resolver, JfireSE jfireSE)
{
this.resolver = resolver;
this.jfireSE = jfireSE;
}
public void getClassId(ClassInfo classInfo)
{
if (currentClassId > tracking.length)
{
ClassInfo[] newTracking = new ClassInfo[tracking.length << 1];
System.arraycopy(tracking, 0, newTracking, 0, tracking.length);
tracking = newTracking;
}
tracking[currentClassId] = classInfo;
classInfo.setClassId(currentClassId);
currentClassId += 1;
}
public void reset()
{
for (int i = currentClassId - 1; i > fixedClassId; i--)
{
tracking[i].reset();
}
currentClassId = fixedClassId;
}
public ClassInfo getClassInfo(Class clazz)
{
ClassInfo classInfo = store.get(clazz);
if (classInfo == null)
{
classInfo = new ClassInfo().setClassName(clazz.getName()).setJfireSE(jfireSE).setClazz(clazz);
store.put(clazz, classInfo);
return classInfo;
}
return classInfo;
}
public void registerClass(Class clazz)
{
ClassInfo classInfo = getClassInfo(clazz);
if (classInfo == null)
{
classInfo = new ClassInfo().setClassName(clazz.getName()).setJfireSE(jfireSE).setClazz(clazz);
store.put(clazz, classInfo);
}
for (int i = 1; i < fixedClassId; i++)
{
if (tracking[i].getClazz() == clazz)
{
return;
}
}
if (fixedClassId > tracking.length)
{
ClassInfo[] newTracking = new ClassInfo[tracking.length << 1];
System.arraycopy(tracking, 0, newTracking, 0, tracking.length);
tracking = newTracking;
}
tracking[fixedClassId] = classInfo;
classInfo.setClassId(fixedClassId++);
currentClassId = fixedClassId;
}
}

View File

@ -0,0 +1,539 @@
package com.jfirer.se;
public class InternalByteArray extends ByteArray
{
public InternalByteArray(int size)
{
super(size);
}
public InternalByteArray(byte[] array)
{
super(array);
}
public void writeVarInt(int i)
{
if (i >= -120 && i <= 127)
{
ensureCapacity(1);
array[writePosi] = (byte) i;
writePosi += 1;
}
else
{
int head = -120;
if (i < 0)
{
i = ~i;
head = -124;
}
if (i <= 255)
{
ensureCapacity(2);
array[writePosi] = (byte) (head - 1);
array[writePosi + 1] = (byte) i;
writePosi += 2;
}
else if (i <= 65535)
{
ensureCapacity(3);
array[writePosi] = (byte) (head - 2);
array[writePosi + 1] = (byte) (i >>> 8);
array[writePosi + 2] = (byte) i;
writePosi += 3;
}
else if (i <= 16777215)
{
ensureCapacity(4);
array[writePosi] = (byte) (head - 3);
array[writePosi + 1] = (byte) (i >>> 16);
array[writePosi + 2] = (byte) (i >>> 8);
array[writePosi + 3] = (byte) i;
writePosi += 4;
}
else
{
ensureCapacity(5);
array[writePosi] = (byte) (head - 4);
array[writePosi + 1] = (byte) (i >>> 24);
array[writePosi + 2] = (byte) (i >>> 16);
array[writePosi + 3] = (byte) (i >>> 8);
array[writePosi + 4] = (byte) i;
writePosi += 5;
}
}
}
public int readVarInt()
{
byte b = array[readIndex++];
if (b >= -120 && b <= 127)
{
return b;
}
else
{
switch (b)
{
case -128:
return ~((array[readIndex++] & 255) << 24 | (array[readIndex++] & 255) << 16 | (array[readIndex++] & 255) << 8 | array[readIndex++] & 255);
case -127:
return ~((array[readIndex++] & 255) << 16 | (array[readIndex++] & 255) << 8 | array[readIndex++] & 255);
case -126:
return ~((array[readIndex++] & 255) << 8 | array[readIndex++] & 255);
case -125:
return ~(array[readIndex++] & 255);
case -124:
return (array[readIndex++] & 255) << 24 | (array[readIndex++] & 255) << 16 | (array[readIndex++] & 255) << 8 | array[readIndex++] & 255;
case -123:
return (array[readIndex++] & 255) << 16 | (array[readIndex++] & 255) << 8 | array[readIndex++] & 255;
case -122:
return (array[readIndex++] & 255) << 8 | array[readIndex++] & 255;
case -121:
return array[readIndex++] & 255;
default:
throw new IllegalArgumentException("not here");
}
}
}
public void writeVarLong(long i)
{
if (i >= -112L && i <= 127L)
{
ensureCapacity(1);
array[writePosi] = (byte) ((int) i);
writePosi += 1;
}
else
{
int head = -112;
if (i < 0L)
{
i = ~i;
head = -120;
}
if (i <= 255L)
{
ensureCapacity(2);
array[writePosi] = (byte) (head - 1);
array[writePosi + 1] = (byte) ((int) i);
writePosi += 2;
}
else if (i <= 65535L)
{
ensureCapacity(3);
array[writePosi] = (byte) (head - 2);
array[writePosi + 1] = (byte) ((int) (i >>> 8));
array[writePosi + 2] = (byte) ((int) i);
writePosi += 3;
}
else if (i <= 16777215L)
{
ensureCapacity(4);
array[writePosi] = (byte) (head - 3);
array[writePosi + 1] = (byte) ((int) (i >>> 16));
array[writePosi + 2] = (byte) ((int) (i >>> 8));
array[writePosi + 3] = (byte) ((int) i);
writePosi += 4;
}
else if (i <= -1L)
{
ensureCapacity(5);
array[writePosi] = (byte) (head - 4);
array[writePosi + 1] = (byte) ((int) (i >>> 24));
array[writePosi + 2] = (byte) ((int) (i >>> 16));
array[writePosi + 3] = (byte) ((int) (i >>> 8));
array[writePosi + 4] = (byte) ((int) i);
writePosi += 5;
}
else if (i <= 1099511627775L)
{
ensureCapacity(6);
array[writePosi] = (byte) (head - 5);
array[writePosi + 1] = (byte) ((int) (i >>> 32));
array[writePosi + 2] = (byte) ((int) (i >>> 24));
array[writePosi + 3] = (byte) ((int) (i >>> 16));
array[writePosi + 4] = (byte) ((int) (i >>> 8));
array[writePosi + 5] = (byte) ((int) i);
writePosi += 6;
}
else if (i <= 281474976710655L)
{
ensureCapacity(7);
array[writePosi] = (byte) (head - 6);
array[writePosi + 1] = (byte) ((int) (i >>> 40));
array[writePosi + 2] = (byte) ((int) (i >>> 32));
array[writePosi + 3] = (byte) ((int) (i >>> 24));
array[writePosi + 4] = (byte) ((int) (i >>> 16));
array[writePosi + 5] = (byte) ((int) (i >>> 8));
array[writePosi + 6] = (byte) ((int) i);
writePosi += 7;
}
else if (i <= 72057594037927935L)
{
ensureCapacity(8);
array[writePosi] = (byte) (head - 7);
array[writePosi + 1] = (byte) ((int) (i >>> 48));
array[writePosi + 2] = (byte) ((int) (i >>> 40));
array[writePosi + 3] = (byte) ((int) (i >>> 32));
array[writePosi + 4] = (byte) ((int) (i >>> 24));
array[writePosi + 5] = (byte) ((int) (i >>> 16));
array[writePosi + 6] = (byte) ((int) (i >>> 8));
array[writePosi + 7] = (byte) ((int) i);
writePosi += 8;
}
else
{
ensureCapacity(9);
array[writePosi] = (byte) (head - 8);
array[writePosi + 1] = (byte) ((int) (i >>> 56));
array[writePosi + 2] = (byte) ((int) (i >>> 48));
array[writePosi + 3] = (byte) ((int) (i >>> 40));
array[writePosi + 4] = (byte) ((int) (i >>> 32));
array[writePosi + 5] = (byte) ((int) (i >>> 24));
array[writePosi + 6] = (byte) ((int) (i >>> 16));
array[writePosi + 7] = (byte) ((int) (i >>> 8));
array[writePosi + 8] = (byte) ((int) i);
writePosi += 9;
}
}
}
public long readVarLong()
{
byte b = array[readIndex++];
if (b >= -112 && b <= 127)
{
return (long) b;
}
else
{
switch (b)
{
case -128:
return ~(((long) array[readIndex++] & 255L) << 56 | ((long) array[readIndex++] & 255L) << 48 | ((long) array[readIndex++] & 255L) << 40 | ((long) array[readIndex++] & 255L) << 32 | ((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L);
case -127:
return ~(((long) array[readIndex++] & 255L) << 48 | ((long) array[readIndex++] & 255L) << 40 | ((long) array[readIndex++] & 255L) << 32 | ((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L);
case -126:
return ~(((long) array[readIndex++] & 255L) << 40 | ((long) array[readIndex++] & 255L) << 32 | ((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L);
case -125:
return ~(((long) array[readIndex++] & 255L) << 32 | ((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L);
case -124:
return ~(((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L);
case -123:
return ~(((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L);
case -122:
return ~(((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L);
case -121:
return ~((long) array[readIndex++] & 255L);
case -120:
return ((long) array[readIndex++] & 255L) << 56 | ((long) array[readIndex++] & 255L) << 48 | ((long) array[readIndex++] & 255L) << 40 | ((long) array[readIndex++] & 255L) << 32 | ((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L;
case -119:
return ((long) array[readIndex++] & 255L) << 48 | ((long) array[readIndex++] & 255L) << 40 | ((long) array[readIndex++] & 255L) << 32 | ((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L;
case -118:
return ((long) array[readIndex++] & 255L) << 40 | ((long) array[readIndex++] & 255L) << 32 | ((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L;
case -117:
return ((long) array[readIndex++] & 255L) << 32 | ((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L;
case -116:
return ((long) array[readIndex++] & 255L) << 24 | ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L;
case -115:
return ((long) array[readIndex++] & 255L) << 16 | ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L;
case -114:
return ((long) array[readIndex++] & 255L) << 8 | (long) array[readIndex++] & 255L;
case -113:
return (long) array[readIndex++] & 255L;
default:
throw new IllegalArgumentException("not here");
}
}
}
public void writeVarCharWithoutCheck(char c)
{
if (c <= 251)
{
array[writePosi] = (byte) c;
writePosi += 1;
}
else if (c <= 255)
{
array[writePosi] = -4;
array[writePosi + 1] = (byte) c;
writePosi += 2;
}
else if (c <= '\uffff')
{
array[writePosi] = -3;
array[writePosi + 1] = (byte) (c >>> 8);
array[writePosi + 2] = (byte) c;
writePosi += 3;
}
}
public void writeVarChar(char c)
{
if (c <= 251)
{
ensureCapacity(1);
array[writePosi] = (byte) c;
++writePosi;
}
else if (c <= 255)
{
ensureCapacity(2);
array[writePosi] = -4;
array[writePosi + 1] = (byte) c;
writePosi += 2;
}
else if (c <= '\uffff')
{
ensureCapacity(3);
array[writePosi] = -3;
array[writePosi + 1] = (byte) (c >>> 8);
array[writePosi + 2] = (byte) c;
writePosi += 3;
}
}
public char readVarChar()
{
int length = array[readIndex++] & 255;
if (length <= 251)
{
return (char) length;
}
else if (length == 252)
{
length = array[readIndex++] & 255;
return (char) length;
}
else if (length == 253)
{
length = (array[readIndex++] & 255) << 8;
length |= array[readIndex++] & 255;
return (char) length;
}
else
{
throw new IllegalArgumentException("not here");
}
}
public void writePositive(int positive)
{
if (positive < 0)
{
throw new UnsupportedOperationException();
}
else
{
if (positive <= 251)
{
ensureCapacity(1);
array[writePosi] = (byte) positive;
++writePosi;
}
else if (positive <= 255)
{
ensureCapacity(2);
array[writePosi] = -4;
array[writePosi + 1] = (byte) positive;
writePosi += 2;
}
else if (positive <= 65535)
{
ensureCapacity(3);
array[writePosi] = -3;
array[writePosi + 1] = (byte) (positive >>> 8);
array[writePosi + 2] = (byte) positive;
writePosi += 3;
}
else if (positive <= 16777215)
{
ensureCapacity(4);
array[writePosi] = -2;
array[writePosi + 1] = (byte) (positive >>> 16);
array[writePosi + 2] = (byte) (positive >>> 8);
array[writePosi + 3] = (byte) positive;
writePosi += 4;
}
else
{
ensureCapacity(5);
array[writePosi] = -1;
array[writePosi + 1] = (byte) (positive >>> 24);
array[writePosi + 2] = (byte) (positive >>> 16);
array[writePosi + 3] = (byte) (positive >>> 8);
array[writePosi + 4] = (byte) positive;
writePosi += 5;
}
}
}
public int readPositive()
{
int length = array[readIndex++] & 255;
if (length <= 251)
{
return length;
}
else if (length == 252)
{
length = array[readIndex++] & 255;
return length;
}
else if (length == 253)
{
length = (array[readIndex++] & 255) << 8;
length |= array[readIndex++] & 255;
return length;
}
else if (length == 254)
{
length = (array[readIndex++] & 255) << 16;
length |= (array[readIndex++] & 255) << 8;
length |= array[readIndex++] & 255;
return length;
}
else if (length == 255)
{
length = (array[readIndex++] & 255) << 24;
length |= (array[readIndex++] & 255) << 16;
length |= (array[readIndex++] & 255) << 8;
length |= array[readIndex++] & 255;
return length;
}
else
{
throw new RuntimeException("wrong data");
}
}
public void writeInt(int i)
{
ensureCapacity(4);
array[writePosi] = (byte) (i >> 24);
array[writePosi + 1] = (byte) (i >> 16);
array[writePosi + 2] = (byte) (i >> 8);
array[writePosi + 3] = (byte) i;
writePosi += 4;
}
public void writeShort(short s)
{
ensureCapacity(2);
array[writePosi] = (byte) (s >> 8);
array[writePosi + 1] = (byte) s;
writePosi += 2;
}
public void writeLong(long l)
{
ensureCapacity(8);
array[writePosi] = (byte) ((int) (l >> 56));
array[writePosi + 1] = (byte) ((int) (l >> 48));
array[writePosi + 2] = (byte) ((int) (l >> 40));
array[writePosi + 3] = (byte) ((int) (l >> 32));
array[writePosi + 4] = (byte) ((int) (l >> 24));
array[writePosi + 5] = (byte) ((int) (l >> 16));
array[writePosi + 6] = (byte) ((int) (l >> 8));
array[writePosi + 7] = (byte) ((int) l);
writePosi += 8;
}
public int readInt()
{
int i = (array[readIndex] & 255) << 24;
i |= (array[readIndex + 1] & 255) << 16;
i |= (array[readIndex + 2] & 255) << 8;
i |= array[readIndex + 3] & 255;
this.readIndex += 4;
return i;
}
public short readShort()
{
short s = (short) ((array[readIndex] & 255) << 8);
s = (short) (s | array[readIndex + 1] & 255);
this.readIndex += 2;
return s;
}
public long readLong()
{
long l = (long) array[readIndex] << 56 | ((long) array[readIndex + 1] & 255L) << 48 | ((long) array[readIndex + 2] & 255L) << 40 | ((long) array[readIndex + 3] & 255L) << 32 | ((long) array[readIndex + 4] & 255L) << 24 | ((long) array[readIndex + 5] & 255L) << 16 | ((long) array[readIndex + 6] & 255L) << 8 | (long) array[readIndex + 7] & 255L;
this.readIndex += 8;
return l;
}
public void writeFloat(float f)
{
writeInt(Float.floatToRawIntBits(f));
}
public void writeDouble(double d)
{
writeLong(Double.doubleToRawLongBits(d));
}
public float readFloat()
{
int i = readInt();
return Float.intBitsToFloat(i);
}
public double readDouble()
{
long l = readLong();
return Double.longBitsToDouble(l);
}
public void skipWrite(int len)
{
ensureCapacity(len);
writePosi += len;
}
public void writeString(String value)
{
if (value == null)
{
writeVarInt(-1);
}
else
{
int length = value.length();
writeVarInt(length);
ensureCapacity(3 * length);
for (int i = 0; i < length; ++i)
{
writeVarCharWithoutCheck(value.charAt(i));
}
}
}
public String readString()
{
int length = readVarInt();
if (length == -1)
{
return null;
}
else
{
char[] src = new char[length];
for (int i = 0; i < length; ++i)
{
src[i] = this.readVarChar();
}
return new String(src);
}
}
public boolean remainRead()
{
return readIndex < writePosi;
}
}

View File

@ -0,0 +1,46 @@
package com.jfirer.se;
import com.jfirer.se.serializer.Serializer;
import com.jfirer.se.serializer.SerializerResolver;
public class JfireSE
{
public static final byte NULL = 0;
private boolean CYCLE_SUPPORT = true;
private SerializerResolver serializerResolver;
private ClassInfoResolver classInfoResolver;
private int depth = 1;
public boolean isCycleSupport()
{
return CYCLE_SUPPORT;
}
public Serializer getSerializer(Class clazz)
{
return serializerResolver.getSerializer(clazz, this);
}
public ClassInfo getClassInfo(Class clazz)
{
return classInfoResolver.getClassInfo(clazz);
}
public void getClassId(ClassInfo classInfo)
{
classInfoResolver.getClassId(classInfo);
}
public void incrDepth()
{
if (depth++ > 256)
{
throw new IllegalStateException("序列化深度超过256可能存在循环引用请开启循环引用设置");
}
}
public void reduceDepth()
{
depth--;
}
}

View File

@ -0,0 +1,8 @@
package com.jfirer.se.serializer;
import com.jfirer.se.InternalByteArray;
public interface Serializer
{
void writeBytes(InternalByteArray byteArray, Object instance);
}

View File

@ -0,0 +1,25 @@
package com.jfirer.se.serializer;
import com.jfirer.se.JfireSE;
import java.util.IdentityHashMap;
import java.util.Map;
public class SerializerResolver
{
private Map<Class, Serializer> store = new IdentityHashMap<>();
public Serializer getSerializer(Class clazz, JfireSE jfireSE)
{
Serializer serializer = store.get(clazz);
if (serializer != null)
{
return serializer;
}
}
public void registerSerializer(Class clazz, Serializer serializer)
{
store.put(clazz, serializer);
}
}

View File

@ -0,0 +1,232 @@
package com.jfirer.se.serializer.impl;
import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.baseutil.reflect.ValueAccessor;
import com.jfirer.se.ClassInfo;
import com.jfirer.se.InternalByteArray;
import com.jfirer.se.JfireSE;
import com.jfirer.se.serializer.Serializer;
import lombok.Data;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
public class ObjectSerializer implements Serializer
{
private FieldInfo[] primitiveFieldInfos;
private FieldInfo[] boxFieldInfos;
private FinalFieldInfo[] finalFieldInfos;
private JfireSE jfireSE;
private Class clazz;
public ObjectSerializer(Class clazz, JfireSE jfireSE)
{
this.clazz = clazz;
this.jfireSE = jfireSE;
Class type = clazz;
List<Field> fields = new ArrayList<>();
while (type != Object.class)
{
fields.addAll(Arrays.stream(type.getDeclaredFields()).filter(Predicate.not(field -> Modifier.isStatic(field.getModifiers()))).toList());
type = type.getComponentType();
}
primitiveFieldInfos = fields.stream().filter(field -> field.getType().isPrimitive()).sorted(Comparator.comparing(o -> o.getType().getName())).map(FieldInfo::new).toArray(FieldInfo[]::new);
boxFieldInfos = fields.stream().filter(field -> ReflectUtil.isPrimitiveBox(field.getType()) || field.getType() == String.class).sorted(Comparator.comparing(o -> o.getType().getName())).map(FieldInfo::new).toArray(FieldInfo[]::new);
finalFieldInfos = fields.stream().filter(Predicate.not(field -> ReflectUtil.isPrimitiveBox(field.getType())))//
.filter(Predicate.not(field -> ReflectUtil.isPrimitive(field.getType())))//
.filter(field -> field.getType() != void.class && field.getType() != Void.class)//
.filter(field -> Modifier.isFinal(field.getType().getModifiers())).sorted(Comparator.comparing(o -> o.getType().getName())).map(FinalFieldInfo::new).toArray(FinalFieldInfo[]::new);
}
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
}
@Data
class FieldInfo
{
int classId;
ValueAccessor accessor;
FieldInfo(Field field)
{
classId = ReflectUtil.getClassId(field.getType());
accessor = new ValueAccessor(field);
}
void write(InternalByteArray byteArray, Object instance)
{
switch (classId)
{
case ReflectUtil.PRIMITIVE_INT -> byteArray.writeVarInt(accessor.getInt(instance));
case ReflectUtil.PRIMITIVE_LONG -> byteArray.writeVarLong(accessor.getLong(instance));
case ReflectUtil.PRIMITIVE_FLOAT -> byteArray.writeFloat(accessor.getFloat(instance));
case ReflectUtil.PRIMITIVE_DOUBLE -> byteArray.writeDouble(accessor.getDouble(instance));
case ReflectUtil.PRIMITIVE_BOOL -> byteArray.writePositive(accessor.getBoolean(instance) ? 1 : 0);
case ReflectUtil.PRIMITIVE_CHAR -> byteArray.writeVarChar(accessor.getChar(instance));
case ReflectUtil.PRIMITIVE_SHORT -> byteArray.writeShort(accessor.getShort(instance));
case ReflectUtil.PRIMITIVE_BYTE -> byteArray.put(accessor.getByte(instance));
case ReflectUtil.CLASS_INT ->
{
Integer value = accessor.getIntObject(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 01);
byteArray.writeVarInt(value);
}
}
case ReflectUtil.CLASS_LONG ->
{
Long value = accessor.getLongObject(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 01);
byteArray.writeVarLong(value);
}
}
case ReflectUtil.CLASS_FLOAT ->
{
Float value = accessor.getFloatObject(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 01);
byteArray.writeFloat(value);
}
}
case ReflectUtil.CLASS_DOUBLE ->
{
Double value = accessor.getDoubleObject(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 01);
byteArray.writeDouble(value);
}
}
case ReflectUtil.CLASS_BOOL ->
{
Boolean value = accessor.getBooleanObject(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 01);
byteArray.writePositive(value ? 1 : 0);
}
}
case ReflectUtil.CLASS_CHAR ->
{
Character value = accessor.getCharObject(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 01);
byteArray.writeVarChar(value);
}
}
case ReflectUtil.CLASS_SHORT ->
{
Short value = accessor.getShortObject(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 01);
byteArray.writeShort(value);
}
}
case ReflectUtil.CLASS_BYTE ->
{
Byte value = accessor.getByteObject(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 01);
byteArray.put(value);
}
}
case ReflectUtil.CLASS_STRING ->
{
String value = (String) accessor.get(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 01);
byteArray.writeString(value);
}
}
}
}
}
class FinalFieldInfo
{
ValueAccessor accessor;
ClassInfo classInfo;
FinalFieldInfo(Field field)
{
accessor = new ValueAccessor(field);
classInfo = jfireSE.getClassInfo(field.getType());
}
void write(InternalByteArray byteArray, Object instance)
{
Object value = accessor.get(instance);
if (value == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put((byte) 07);
}
}
}
class VariableFieldInfo
{
ValueAccessor accessor;
ClassInfo classInfo;
VariableFieldInfo(Field field)
{
accessor = new ValueAccessor(field);
}
}
}

View File

@ -0,0 +1,38 @@
package org.example;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}