Skip to content

Commit

Permalink
Java Record serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
apangin committed Sep 7, 2020
1 parent cb4b45f commit 459d5b5
Show file tree
Hide file tree
Showing 11 changed files with 311 additions and 143 deletions.
3 changes: 1 addition & 2 deletions src/one/nio/gen/BytecodeGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,8 @@ public static void emitInvoke(MethodVisitor mv, Method m) {

public static void emitInvoke(MethodVisitor mv, Constructor c) {
String holder = Type.getInternalName(c.getDeclaringClass());
String name = c.getName();
String sig = Type.getConstructorDescriptor(c);
mv.visitMethodInsn(INVOKESPECIAL, holder, name, sig);
mv.visitMethodInsn(INVOKESPECIAL, holder, "<init>", sig);
}

public static void emitThrow(MethodVisitor mv, String exceptionClass, String message) {
Expand Down
24 changes: 7 additions & 17 deletions src/one/nio/serial/FieldDescriptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ public class FieldDescriptor {
private TypeDescriptor typeDescriptor;
private Field ownField;
private Field parentField;
private boolean useGetter;
private boolean useSetter;
private int index;

// Ad-hoc linked list
public FieldDescriptor next;
Expand All @@ -37,11 +36,11 @@ public class FieldDescriptor {
this.typeDescriptor = typeDescriptor;
}

FieldDescriptor(Field ownField, Field parentField) {
FieldDescriptor(Field ownField, Field parentField, int index) {
Renamed renamed = ownField.getAnnotation(Renamed.class);
this.nameDescriptor = renamed == null ? ownField.getName() : ownField.getName() + '|' + renamed.from();
this.typeDescriptor = new TypeDescriptor(ownField.getType());
assignField(ownField, parentField);
assignField(ownField, parentField, index);
}

@Override
Expand All @@ -65,27 +64,18 @@ public Field parentField() {
return parentField;
}

public boolean useGetter() {
return useGetter;
}

public boolean useSetter() {
return useSetter;
public int index() {
return index;
}

public boolean is(String nameDescriptor, String typeDescriptor) {
return nameDescriptor.equals(this.nameDescriptor) && typeDescriptor.equals(this.typeDescriptor.toString());
}

public void assignField(Field ownField, Field parentField) {
public void assignField(Field ownField, Field parentField, int index) {
this.ownField = ownField;
this.parentField = parentField;

SerializeWith serializeWith = ownField.getAnnotation(SerializeWith.class);
if (serializeWith != null) {
this.useGetter = !serializeWith.getter().isEmpty();
this.useSetter = !serializeWith.setter().isEmpty();
}
this.index = index;
}

public static FieldDescriptor read(ObjectInput in) throws IOException {
Expand Down
20 changes: 10 additions & 10 deletions src/one/nio/serial/GeneratedSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

import java.io.Externalizable;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.Field;
Expand All @@ -41,7 +40,7 @@ public class GeneratedSerializer extends Serializer {
static final AtomicInteger unsupportedFields = new AtomicInteger();

private FieldDescriptor[] fds;
private ArrayList<Field> defaultFields;
private FieldDescriptor[] defaultFields;
private Delegate delegate;

GeneratedSerializer(Class cls) {
Expand All @@ -50,8 +49,9 @@ public class GeneratedSerializer extends Serializer {
Field[] ownFields = getSerializableFields();
this.fds = new FieldDescriptor[ownFields.length / 2];
for (int i = 0; i < ownFields.length; i += 2) {
fds[i / 2] = new FieldDescriptor(ownFields[i], ownFields[i + 1]);
fds[i / 2] = new FieldDescriptor(ownFields[i], ownFields[i + 1], i / 2);
}
this.defaultFields = new FieldDescriptor[0];

checkFieldTypes();
this.delegate = BytecodeGenerator.INSTANCE.instantiate(code(), Delegate.class);
Expand Down Expand Up @@ -89,7 +89,7 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundExcept
Field[] ownFields = getSerializableFields();
assignFields(ownFields, true);
assignFields(ownFields, false);
assignDefaultFields(ownFields);
this.defaultFields = assignDefaultFields(ownFields);

checkFieldTypes();
this.delegate = BytecodeGenerator.INSTANCE.instantiate(code(), Delegate.class);
Expand Down Expand Up @@ -181,26 +181,26 @@ private void assignFields(Field[] ownFields, boolean exactType) {
if (fd.ownField() == null) {
int found = findField(fd, ownFields, exactType);
if (found >= 0) {
fd.assignField(ownFields[found], ownFields[found + 1]);
fd.assignField(ownFields[found], ownFields[found + 1], found / 2);
ownFields[found] = null;
}
}
}
}

private void assignDefaultFields(Field[] ownFields) {
defaultFields = new ArrayList<>();
private FieldDescriptor[] assignDefaultFields(Field[] ownFields) {
ArrayList<FieldDescriptor> defaultFields = new ArrayList<>();

for (int i = 0; i < ownFields.length; i += 2) {
Field f = ownFields[i];
if (f != null) {
logFieldMismatch("Local field is missed in stream", f.getType(), f.getDeclaringClass(), f.getName());
missedLocalFields.incrementAndGet();
if (f.getAnnotation(Default.class) != null) {
defaultFields.add(f);
}
defaultFields.add(new FieldDescriptor(f, null, i / 2));
}
}

return defaultFields.toArray(new FieldDescriptor[0]);
}

private int findField(FieldDescriptor fd, Field[] ownFields, boolean exactType) {
Expand Down
2 changes: 1 addition & 1 deletion src/one/nio/serial/JsonReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,6 @@ private static Number parseNumber(String number) {
}
}
long n = Long.parseLong(number);
return n == (int) n ? Integer.valueOf((int) n) : Long.valueOf(n);
return n == (int) n ? (int) n : (Number) n;
}
}
Loading

0 comments on commit 459d5b5

Please sign in to comment.