2023-04-20 10:11:12 +02:00
|
|
|
package it.cavallium.datagen.plugin.classgen;
|
2023-01-21 01:15:05 +01:00
|
|
|
|
|
|
|
import com.squareup.javapoet.ArrayTypeName;
|
|
|
|
import com.squareup.javapoet.ClassName;
|
|
|
|
import com.squareup.javapoet.MethodSpec;
|
|
|
|
import com.squareup.javapoet.ParameterSpec;
|
|
|
|
import com.squareup.javapoet.ParameterizedTypeName;
|
|
|
|
import com.squareup.javapoet.TypeSpec;
|
|
|
|
import com.squareup.javapoet.TypeSpec.Builder;
|
2023-04-20 10:11:12 +02:00
|
|
|
import it.cavallium.datagen.DataSerializer;
|
|
|
|
import it.cavallium.datagen.NotSerializableException;
|
|
|
|
import it.cavallium.datagen.nativedata.ImmutableWrappedArrayList;
|
|
|
|
import it.cavallium.datagen.plugin.ClassGenerator;
|
|
|
|
import it.cavallium.datagen.plugin.ComputedTypeArray;
|
|
|
|
import it.cavallium.datagen.plugin.ComputedTypeArrayFixed;
|
|
|
|
import it.cavallium.datagen.plugin.ComputedTypeArrayVersioned;
|
|
|
|
import it.cavallium.datagen.plugin.ComputedVersion;
|
2023-03-03 00:13:36 +01:00
|
|
|
import it.cavallium.stream.SafeDataInput;
|
|
|
|
import it.cavallium.stream.SafeDataOutput;
|
2023-01-21 01:15:05 +01:00
|
|
|
import java.util.Objects;
|
|
|
|
import java.util.stream.Stream;
|
|
|
|
import javax.lang.model.element.Modifier;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
|
|
|
public class GenSerializerArrayX extends ClassGenerator {
|
|
|
|
|
2023-04-20 20:22:07 +02:00
|
|
|
/**
|
|
|
|
* Enabling this option can slow down deserialization updates
|
|
|
|
*/
|
|
|
|
private static final boolean USE_NATIVE_TYPED_ARRAYS = false;
|
|
|
|
|
2023-01-21 01:15:05 +01:00
|
|
|
public GenSerializerArrayX(ClassGeneratorParams params) {
|
|
|
|
super(params);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Stream<GeneratedClass> generateClasses() {
|
|
|
|
return dataModel.getVersionsSet().parallelStream().flatMap(this::generateVersionClasses);
|
|
|
|
}
|
|
|
|
|
|
|
|
private Stream<GeneratedClass> generateVersionClasses(ComputedVersion version) {
|
|
|
|
return dataModel
|
|
|
|
.getArrayTypesComputed(version)
|
2023-01-21 23:58:56 +01:00
|
|
|
.filter(type -> (type instanceof ComputedTypeArrayVersioned versioned
|
|
|
|
&& versioned.getVersion().equals(version)) || type instanceof ComputedTypeArrayFixed)
|
|
|
|
.map(type -> generateTypeVersioned(version, type));
|
2023-01-21 01:15:05 +01:00
|
|
|
}
|
|
|
|
|
2023-01-21 23:58:56 +01:00
|
|
|
private GeneratedClass generateTypeVersioned(ComputedVersion version, ComputedTypeArray typeArray) {
|
2023-01-21 01:15:05 +01:00
|
|
|
ClassName serializerClassName = typeArray.getJSerializerName(basePackageName);
|
|
|
|
var typeArrayClassName = typeArray.getJTypeName(basePackageName);
|
|
|
|
|
|
|
|
var classBuilder = TypeSpec.classBuilder(serializerClassName.simpleName());
|
|
|
|
|
|
|
|
classBuilder.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
|
|
|
|
|
|
|
|
classBuilder.addSuperinterface(ParameterizedTypeName.get(ClassName.get(DataSerializer.class), typeArrayClassName));
|
|
|
|
|
|
|
|
generateSerialize(version, typeArray, classBuilder);
|
|
|
|
|
|
|
|
generateDeserialize(version, typeArray, classBuilder);
|
|
|
|
|
|
|
|
return new GeneratedClass(serializerClassName.packageName(), classBuilder);
|
|
|
|
}
|
|
|
|
|
2023-01-21 23:58:56 +01:00
|
|
|
private void generateSerialize(ComputedVersion version, ComputedTypeArray typeArray, Builder classBuilder) {
|
2023-01-21 01:15:05 +01:00
|
|
|
var method = MethodSpec.methodBuilder("serialize");
|
|
|
|
|
|
|
|
method.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
|
|
|
|
|
2023-03-03 00:13:36 +01:00
|
|
|
method.addParameter(ParameterSpec.builder(SafeDataOutput.class, "out").build());
|
2023-01-21 01:15:05 +01:00
|
|
|
method.addParameter(ParameterSpec
|
|
|
|
.builder(typeArray.getJTypeName(basePackageName), "data")
|
|
|
|
.addAnnotation(NotNull.class)
|
|
|
|
.build());
|
|
|
|
|
2023-01-22 12:39:54 +01:00
|
|
|
if (generateOldSerializers || version.isCurrent()) {
|
2023-01-21 01:15:05 +01:00
|
|
|
method.addStatement("$T.requireNonNull(data)", Objects.class);
|
|
|
|
method.addCode("\n");
|
|
|
|
method.addStatement("final int sz = data.size()");
|
|
|
|
method.addStatement("out.writeInt(sz)");
|
|
|
|
method.addCode("\n");
|
2023-03-02 22:46:54 +01:00
|
|
|
method.beginControlFlow("for (var item : data)");
|
2023-01-21 01:15:05 +01:00
|
|
|
var baseSerializerInstance = typeArray.getBase().getJSerializerInstance(basePackageName);
|
2023-03-02 22:46:54 +01:00
|
|
|
method.addStatement("$T.$N.serialize(out, ($T) item)",
|
2023-01-21 01:15:05 +01:00
|
|
|
baseSerializerInstance.className(),
|
|
|
|
baseSerializerInstance.fieldName(),
|
|
|
|
typeArray.getBase().getJTypeName(basePackageName)
|
|
|
|
);
|
|
|
|
method.endControlFlow();
|
|
|
|
} else {
|
|
|
|
method.addStatement("throw new $T()", NotSerializableException.class);
|
|
|
|
}
|
|
|
|
|
|
|
|
classBuilder.addMethod(method.build());
|
|
|
|
}
|
|
|
|
|
2023-01-21 23:58:56 +01:00
|
|
|
private void generateDeserialize(ComputedVersion version, ComputedTypeArray typeArray, Builder classBuilder) {
|
2023-01-21 01:15:05 +01:00
|
|
|
var method = MethodSpec.methodBuilder("deserialize");
|
|
|
|
|
|
|
|
method.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
|
|
|
|
|
|
|
|
var typeArrayClassName = typeArray.getJTypeName(basePackageName);
|
2023-04-20 20:22:07 +02:00
|
|
|
|
|
|
|
var arrayComponentTypeName = typeArray.getBase().getJTypeName(basePackageName);
|
|
|
|
var typedArrayTypeName = ArrayTypeName.of(arrayComponentTypeName);
|
|
|
|
|
2023-01-21 01:15:05 +01:00
|
|
|
method.returns(typeArrayClassName);
|
|
|
|
method.addAnnotation(NotNull.class);
|
|
|
|
|
2023-03-03 00:13:36 +01:00
|
|
|
method.addParameter(ParameterSpec.builder(SafeDataInput.class, "in").build());
|
2023-01-21 01:15:05 +01:00
|
|
|
|
|
|
|
method.addStatement("int sz = in.readInt()");
|
2023-04-20 20:22:07 +02:00
|
|
|
if (USE_NATIVE_TYPED_ARRAYS) {
|
|
|
|
method.addStatement("$T a = new $T[sz]", typedArrayTypeName, arrayComponentTypeName);
|
|
|
|
} else {
|
|
|
|
method.addStatement("$T a = new $T[sz]", Object[].class, Object.class);
|
|
|
|
}
|
2023-01-21 01:15:05 +01:00
|
|
|
method.addCode("\n");
|
|
|
|
method.beginControlFlow("for (int i = 0; i < sz; ++i)");
|
|
|
|
var baseSerializerInstance = typeArray.getBase().getJSerializerInstance(basePackageName);
|
2023-04-20 20:22:07 +02:00
|
|
|
|
2023-01-21 01:15:05 +01:00
|
|
|
method.addStatement("a[i] = $T.$N.deserialize(in)", baseSerializerInstance.className(), baseSerializerInstance.fieldName());
|
|
|
|
method.endControlFlow();
|
|
|
|
|
|
|
|
method.addCode("\n");
|
2023-04-20 20:22:07 +02:00
|
|
|
if (USE_NATIVE_TYPED_ARRAYS) {
|
|
|
|
method.addStatement("return new $T(a)", ParameterizedTypeName.get(ClassName.get(ImmutableWrappedArrayList.class), arrayComponentTypeName));
|
|
|
|
} else {
|
|
|
|
method.addStatement("return ($T) new $T(a)",
|
|
|
|
ParameterizedTypeName.get(ClassName.get(ImmutableWrappedArrayList.class), arrayComponentTypeName),
|
|
|
|
ClassName.get(ImmutableWrappedArrayList.class)
|
|
|
|
);
|
|
|
|
}
|
2023-01-21 01:15:05 +01:00
|
|
|
|
|
|
|
classBuilder.addMethod(method.build());
|
|
|
|
}
|
|
|
|
}
|