feat[protocol]: scala support

This commit is contained in:
godotg
2024-07-07 10:48:59 +08:00
parent 747ab9dbb3
commit 829be3207c
23 changed files with 2632 additions and 3 deletions
@@ -22,6 +22,7 @@ import com.zfoo.protocol.serializer.javascript.CodeGenerateJavaScript;
import com.zfoo.protocol.serializer.kotlin.CodeGenerateKotlin;
import com.zfoo.protocol.serializer.lua.CodeGenerateLua;
import com.zfoo.protocol.serializer.python.CodeGeneratePython;
import com.zfoo.protocol.serializer.scala.CodeGenerateScala;
import com.zfoo.protocol.serializer.typescript.CodeGenerateTypeScript;
/**
@@ -34,11 +35,11 @@ public enum CodeLanguage {
*/
Enhance(1, null),
Java(1<<1, CodeGenerateJava.class),
Java(1 << 1, CodeGenerateJava.class),
Kotlin(1<<2, CodeGenerateKotlin.class),
Kotlin(1 << 2, CodeGenerateKotlin.class),
Scala(1<<3, null),
Scala(1 << 3, CodeGenerateScala.class),
Cpp(1 << 7, CodeGenerateCpp.class),
@@ -0,0 +1,428 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.anno.Compatible;
import com.zfoo.protocol.generate.GenerateOperation;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.generate.GenerateProtocolNote;
import com.zfoo.protocol.generate.GenerateProtocolPath;
import com.zfoo.protocol.registration.ProtocolAnalysis;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.serializer.CodeTemplatePlaceholder;
import com.zfoo.protocol.serializer.ICodeGenerate;
import com.zfoo.protocol.serializer.enhance.EnhanceObjectProtocolSerializer;
import com.zfoo.protocol.serializer.reflect.*;
import com.zfoo.protocol.util.ClassUtils;
import com.zfoo.protocol.util.FileUtils;
import com.zfoo.protocol.util.ReflectionUtils;
import com.zfoo.protocol.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.zfoo.protocol.util.FileUtils.LS;
import static com.zfoo.protocol.util.StringUtils.TAB;
/**
* @author godotg
*/
public class CodeGenerateScala implements ICodeGenerate {
private static final Logger logger = LoggerFactory.getLogger(CodeGenerateScala.class);
// custom configuration
public static String protocolOutputRootPath = "zfooscala";
private static String protocolOutputPath = StringUtils.EMPTY;
public static String protocolPackage = "com.zfoo.scala";
private static final Map<ISerializer, IScalaSerializer> scalaSerializerMap = new HashMap<>();
public static IScalaSerializer scalaSerializer(ISerializer serializer) {
return scalaSerializerMap.get(serializer);
}
@Override
public void init(GenerateOperation generateOperation) {
protocolOutputPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
FileUtils.deleteFile(new File(protocolOutputPath));
scalaSerializerMap.put(BooleanSerializer.INSTANCE, new ScalaBooleanSerializer());
scalaSerializerMap.put(ByteSerializer.INSTANCE, new ScalaByteSerializer());
scalaSerializerMap.put(ShortSerializer.INSTANCE, new ScalaShortSerializer());
scalaSerializerMap.put(IntSerializer.INSTANCE, new ScalaIntSerializer());
scalaSerializerMap.put(LongSerializer.INSTANCE, new ScalaLongSerializer());
scalaSerializerMap.put(FloatSerializer.INSTANCE, new ScalaFloatSerializer());
scalaSerializerMap.put(DoubleSerializer.INSTANCE, new ScalaDoubleSerializer());
scalaSerializerMap.put(StringSerializer.INSTANCE, new ScalaStringSerializer());
scalaSerializerMap.put(ArraySerializer.INSTANCE, new ScalaArraySerializer());
scalaSerializerMap.put(ListSerializer.INSTANCE, new ScalaListSerializer());
scalaSerializerMap.put(SetSerializer.INSTANCE, new ScalaSetSerializer());
scalaSerializerMap.put(MapSerializer.INSTANCE, new ScalaMapSerializer());
scalaSerializerMap.put(ObjectProtocolSerializer.INSTANCE, new ScalaObjectProtocolSerializer());
}
@Override
public void mergerProtocol(List<ProtocolRegistration> registrations) throws IOException {
createTemplateFile();
var protocol_root_path = StringUtils.format("package {}", protocolPackage);
var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("scala/ProtocolManagerTemplate.scala");
var protocol_manager_registrations = new StringBuilder();
for (var registration : registrations) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
protocol_manager_registrations.append(StringUtils.format("protocols({}) = Registration{}", protocol_id, protocol_name)).append(LS);
protocol_manager_registrations.append(StringUtils.format("protocolIdMap.put(classOf[{}], {})", protocol_name, protocol_id)).append(LS);
}
var placeholderMap = Map.of(CodeTemplatePlaceholder.protocol_root_path, protocol_root_path
, CodeTemplatePlaceholder.protocol_imports, StringUtils.EMPTY
, CodeTemplatePlaceholder.protocol_manager_registrations, protocol_manager_registrations.toString());
var formatProtocolManagerTemplate = CodeTemplatePlaceholder.formatTemplate(protocolManagerTemplate, placeholderMap);
var protocolManagerFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.scala"));
FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true);
logger.info("Generated Scala protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath());
var protocol_class = new StringBuilder();
var protocol_registration = new StringBuilder();
for (var registration : GenerateProtocolFile.subProtocolFirst(registrations)) {
var protocol_id = registration.protocolId();
// protocol
protocol_class.append(protocol_class(registration)).append(LS);
// registration
protocol_registration.append(protocol_registration(registration)).append(LS);
}
var protocolTemplate = ClassUtils.getFileFromClassPathToString("scala/ProtocolsTemplate.scala");
var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of(
CodeTemplatePlaceholder.protocol_root_path, protocol_root_path
, CodeTemplatePlaceholder.protocol_imports, StringUtils.EMPTY
, CodeTemplatePlaceholder.protocol_class, protocol_class.toString()
, CodeTemplatePlaceholder.protocol_registration, protocol_registration.toString()
));
var outputPath = StringUtils.format("{}/Protocols.scala", protocolOutputPath);
var file = new File(outputPath);
FileUtils.writeStringToFile(file, formatProtocolTemplate, true);
logger.info("Generated Scala protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
}
@Override
public void foldProtocol(List<ProtocolRegistration> registrations) throws IOException {
createTemplateFile();
var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("scala/ProtocolManagerTemplate.scala");
var protocol_manager_registrations = new StringBuilder();
var protocol_imports = new StringBuilder();
for (var registration : registrations) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
protocol_imports.append(StringUtils.format("import {}.{}.{}", protocolPackage, GenerateProtocolPath.protocolPathPeriod(protocol_id), protocol_name)).append(LS);
protocol_imports.append(StringUtils.format("import {}.{}.Registration{}", protocolPackage, GenerateProtocolPath.protocolPathPeriod(protocol_id), protocol_name)).append(LS);
protocol_manager_registrations.append(StringUtils.format("protocols({}) = Registration{}", protocol_id, protocol_name)).append(LS);
protocol_manager_registrations.append(StringUtils.format("protocolIdMap.put(classOf[{}], {})", protocol_name, protocol_id)).append(LS);
}
var placeholderMap = Map.of(CodeTemplatePlaceholder.protocol_root_path, StringUtils.format("package {}", protocolPackage)
, CodeTemplatePlaceholder.protocol_imports, protocol_imports.toString()
, CodeTemplatePlaceholder.protocol_manager_registrations, protocol_manager_registrations.toString());
var formatProtocolManagerTemplate = CodeTemplatePlaceholder.formatTemplate(protocolManagerTemplate, placeholderMap);
var protocolManagerFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.scala"));
FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true);
logger.info("Generated Scala protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath());
for (var registration : registrations) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
var protocolTemplate = ClassUtils.getFileFromClassPathToString("scala/ProtocolTemplate.scala");
var protocol_root_path = StringUtils.format("package {}.{}", protocolPackage, GenerateProtocolPath.protocolPathPeriod(protocol_id));
var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of(
CodeTemplatePlaceholder.protocol_root_path, protocol_root_path
, CodeTemplatePlaceholder.protocol_imports, protocol_imports_fold(registration)
, CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Scala)
, CodeTemplatePlaceholder.protocol_name, protocol_name
, CodeTemplatePlaceholder.protocol_class, protocol_class(registration)
, CodeTemplatePlaceholder.protocol_registration, protocol_registration(registration)
));
var outputPath = StringUtils.format("{}/{}/{}.scala", protocolOutputPath, GenerateProtocolPath.protocolPathSlash(protocol_id), protocol_name);
var file = new File(outputPath);
FileUtils.writeStringToFile(file, formatProtocolTemplate, true);
logger.info("Generated Scala protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
}
}
@Override
public void defaultProtocol(List<ProtocolRegistration> registrations) throws IOException {
createTemplateFile();
var protocol_root_path = StringUtils.format("package {}", protocolPackage);
var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("scala/ProtocolManagerTemplate.scala");
var protocol_manager_registrations = new StringBuilder();
for (var registration : registrations) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
protocol_manager_registrations.append(StringUtils.format("protocols({}) = Registration{}", protocol_id, protocol_name)).append(LS);
protocol_manager_registrations.append(StringUtils.format("protocolIdMap.put(classOf[{}], {})", protocol_name, protocol_id)).append(LS);
}
var placeholderMap = Map.of(CodeTemplatePlaceholder.protocol_root_path, protocol_root_path
, CodeTemplatePlaceholder.protocol_imports, StringUtils.EMPTY
, CodeTemplatePlaceholder.protocol_manager_registrations, protocol_manager_registrations.toString());
var formatProtocolManagerTemplate = CodeTemplatePlaceholder.formatTemplate(protocolManagerTemplate, placeholderMap);
var protocolManagerFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.scala"));
FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true);
logger.info("Generated Scala protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath());
for (var registration : registrations) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
var protocolTemplate = ClassUtils.getFileFromClassPathToString("scala/ProtocolTemplate.scala");
var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of(
CodeTemplatePlaceholder.protocol_root_path, protocol_root_path
, CodeTemplatePlaceholder.protocol_imports, StringUtils.EMPTY
, CodeTemplatePlaceholder.protocol_class, protocol_class(registration)
, CodeTemplatePlaceholder.protocol_registration, protocol_registration(registration)
));
var outputPath = StringUtils.format("{}/{}.scala", protocolOutputPath, protocol_name);
var file = new File(outputPath);
FileUtils.writeStringToFile(file, formatProtocolTemplate, true);
logger.info("Generated Scala protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
}
}
private void createTemplateFile() {
var rootPackage = StringUtils.format("package {}", protocolPackage);
var list = List.of("scala/IProtocolRegistration.scala"
, "scala/ByteBuffer.scala");
for (var fileName : list) {
// IProtocolRegistration
var template = ClassUtils.getFileFromClassPathToString(fileName);
var formatTemplate = CodeTemplatePlaceholder.formatTemplate(template, Map.of(
CodeTemplatePlaceholder.protocol_root_path, rootPackage
, CodeTemplatePlaceholder.protocol_imports, StringUtils.EMPTY
));
var createFile = new File(StringUtils.format("{}/{}", protocolOutputPath, StringUtils.substringAfterFirst(fileName, "scala/")));
FileUtils.writeStringToFile(createFile, formatTemplate, false);
}
}
private String protocol_class(ProtocolRegistration registration) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
var protocolTemplate = ClassUtils.getFileFromClassPathToString("scala/ProtocolClassTemplate.scala");
var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of(
CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Scala)
, CodeTemplatePlaceholder.protocol_name, protocol_name
, CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id)
, CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration)
));
return formatProtocolTemplate;
}
private String protocol_registration(ProtocolRegistration registration) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
var protocolTemplate = ClassUtils.getFileFromClassPathToString("scala/ProtocolRegistrationTemplate.scala");
var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of(
CodeTemplatePlaceholder.protocol_name, protocol_name
, CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id)
, CodeTemplatePlaceholder.protocol_write_serialization, protocol_write_serialization(registration)
, CodeTemplatePlaceholder.protocol_read_deserialization, protocol_read_deserialization(registration)
));
return formatProtocolTemplate;
}
private String protocol_imports_fold(ProtocolRegistration registration) {
var protocolId = registration.getId();
var subProtocols = ProtocolAnalysis.getAllSubProtocolIds(protocolId);
var scalaBuilder = new StringBuilder();
for (var subProtocolId : subProtocols) {
var protocolName = EnhanceObjectProtocolSerializer.getProtocolClassSimpleName(subProtocolId);
var subProtocolPath = StringUtils.format("import {}.{}.{}", protocolPackage, GenerateProtocolPath.protocolPathPeriod(subProtocolId), protocolName);
scalaBuilder.append(subProtocolPath).append(LS);
}
scalaBuilder.append(StringUtils.format("import {}.IProtocolRegistration", protocolPackage)).append(LS);
scalaBuilder.append(StringUtils.format("import {}.ByteBuffer", protocolPackage)).append(LS);
return scalaBuilder.toString();
}
private String protocol_field_definition(ProtocolRegistration registration) {
var protocolId = registration.getId();
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var scalaBuilder = new StringBuilder();
var sequencedFields = ReflectionUtils.notStaticAndTransientFields(registration.getConstructor().getDeclaringClass());
for (int i = 0; i < sequencedFields.size(); i++) {
var field = sequencedFields.get(i);
IFieldRegistration fieldRegistration = fieldRegistrations[GenerateProtocolFile.indexOf(fields, field)];
var fieldName = field.getName();
// 生成注释
var fieldNotes = GenerateProtocolNote.fieldNotes(protocolId, fieldName, CodeLanguage.Scala);
for (var fieldNote : fieldNotes) {
scalaBuilder.append(fieldNote).append(LS);
}
var pair = scalaSerializer(fieldRegistration.serializer()).field(field, fieldRegistration);
scalaBuilder.append(StringUtils.format("var {}: {} = {}", fieldName, pair.getKey(), pair.getValue())).append(LS);
}
return scalaBuilder.toString();
}
private String protocol_write_serialization(ProtocolRegistration registration) {
GenerateProtocolFile.localVariableId = 0;
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var scalaBuilder = new StringBuilder();
if (registration.isCompatible()) {
scalaBuilder.append("val beforeWriteIndex = buffer.getWriteOffset").append(LS);
scalaBuilder.append(StringUtils.format("buffer.writeInt({})", registration.getPredictionLength())).append(LS);
} else {
scalaBuilder.append("buffer.writeInt(-1)").append(LS);
}
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
scalaSerializer(fieldRegistration.serializer()).writeObject(scalaBuilder, "message." + field.getName(), 0, field, fieldRegistration);
}
if (registration.isCompatible()) {
scalaBuilder.append(StringUtils.format("buffer.adjustPadding({}, beforeWriteIndex)", registration.getPredictionLength())).append(LS);
}
return scalaBuilder.toString();
}
private String protocol_read_deserialization(ProtocolRegistration registration) {
GenerateProtocolFile.localVariableId = 0;
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var scalaBuilder = new StringBuilder();
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
if (field.isAnnotationPresent(Compatible.class)) {
scalaBuilder.append("if (buffer.compatibleRead(beforeReadIndex, length)) {").append(LS);
var compatibleReadObject = scalaSerializer(fieldRegistration.serializer()).readObject(scalaBuilder, 1, field, fieldRegistration);
scalaBuilder.append(TAB).append(StringUtils.format("packet.{} = {}", field.getName(), compatibleReadObject)).append(LS);
scalaBuilder.append("}").append(LS);
continue;
}
var readObject = scalaSerializer(fieldRegistration.serializer()).readObject(scalaBuilder, 0, field, fieldRegistration);
scalaBuilder.append(StringUtils.format("packet.{} = {}", field.getName(), readObject)).append(LS);
}
return scalaBuilder.toString();
}
public static String toScalaClassName(String typeName) {
typeName = typeName.replaceAll("java.util.|java.lang.", StringUtils.EMPTY);
typeName = typeName.replaceAll("[a-zA-Z0-9_.]*\\.", StringUtils.EMPTY);
switch (typeName) {
case "boolean":
case "Boolean":
typeName = "Boolean";
return typeName;
case "byte":
case "Byte":
typeName = "Byte";
return typeName;
case "short":
case "Short":
typeName = "Short";
return typeName;
case "int":
case "Integer":
typeName = "Int";
return typeName;
case "long":
case "Long":
typeName = "Long";
return typeName;
case "float":
case "Float":
typeName = "Float";
return typeName;
case "double":
case "Double":
typeName = "Double";
return typeName;
case "char":
case "Character":
case "String":
typeName = "String";
return typeName;
default:
}
// 将boolean转为bool
typeName = typeName.replaceAll("[B|b]oolean\\[", "Boolean");
typeName = typeName.replace("<Boolean", "[Boolean");
typeName = typeName.replace("Boolean>", "Boolean]");
// 将Byte转为byte
typeName = typeName.replace("Byte[", "Byte");
typeName = typeName.replace("Byte>", "Byte]");
typeName = typeName.replace("<Byte", "[Byte");
// 将Short转为short
typeName = typeName.replace("Short[", "Short");
typeName = typeName.replace("Short>", "Short]");
typeName = typeName.replace("<Short", "[Short");
// 将Integer转为int
typeName = typeName.replace("Integer[", "Int");
typeName = typeName.replace("Integer>", "Int]");
typeName = typeName.replace("<Integer", "[Int");
// 将Long转为long
typeName = typeName.replace("Long[", "Long");
typeName = typeName.replace("Long>", "Long]");
typeName = typeName.replace("<Long", "[Long");
// 将Float转为float
typeName = typeName.replace("Float[", "Float");
typeName = typeName.replace("Float>", "Float]");
typeName = typeName.replace("<Float", "[Float");
// 将Double转为double
typeName = typeName.replace("Double[", "Double");
typeName = typeName.replace("Double>", "Double]");
typeName = typeName.replace("<Double", "[Double");
// 将Character转为Char
typeName = typeName.replace("Character[", "String");
typeName = typeName.replace("Character>", "String]");
typeName = typeName.replace("<Character", "[String");
// 将String转为string
typeName = typeName.replace("String[", "String");
typeName = typeName.replace("String>", "String]");
typeName = typeName.replace("<String", "[String");
typeName = typeName.replace("Map<", "Map[");
typeName = typeName.replace("Set<", "Set[");
typeName = typeName.replace("List<", "List[");
typeName = typeName.replace(">", "]");
return typeName;
}
}
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import java.lang.reflect.Field;
/**
* @author godotg
*/
public interface IScalaSerializer {
/**
* 获取属性的类型,默认值
*/
Pair<String, String> field(Field field, IFieldRegistration fieldRegistration);
void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration);
String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration);
}
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.ArrayField;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.serializer.CutDownArraySerializer;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaArraySerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
var type = StringUtils.format("Array[{}]", CodeGenerateScala.toScalaClassName(field.getType().getComponentType().getSimpleName()));
return new Pair<>(type, "_");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
if (CutDownArraySerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.Scala)) {
return;
}
ArrayField arrayField = (ArrayField) fieldRegistration;
builder.append(StringUtils.format("buffer.writeInt({}.length)", objectStr)).append(LS);
GenerateProtocolFile.addTab(builder, deep);
String length = "length" + GenerateProtocolFile.localVariableId++;
builder.append(StringUtils.format("val {} = {}.length", length, objectStr)).append(LS);
String i = "i" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("for ({} <- 0 until {}) {", i, length)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
String element = "element" + GenerateProtocolFile.localVariableId++;
builder.append(StringUtils.format("val {} = {}({})", element, objectStr, i)).append(LS);
CodeGenerateScala.scalaSerializer(arrayField.getArrayElementRegistration().serializer())
.writeObject(builder, element, deep + 1, field, arrayField.getArrayElementRegistration());
GenerateProtocolFile.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
var cutDown = CutDownArraySerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.Scala);
if (cutDown != null) {
return cutDown;
}
var arrayField = (ArrayField) fieldRegistration;
var result = "result" + GenerateProtocolFile.localVariableId++;
var typeName = CodeGenerateScala.toScalaClassName(arrayField.getType().getSimpleName());
var i = "index" + GenerateProtocolFile.localVariableId++;
var init = "init" + GenerateProtocolFile.localVariableId++;
var size = "size" + GenerateProtocolFile.localVariableId++;
builder.append(StringUtils.format("val {} = buffer.readInt", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep);
var pair = CodeGenerateScala.scalaSerializer(arrayField.getArrayElementRegistration().serializer()).field(field, arrayField.getArrayElementRegistration());
var defaultValue = pair.getValue();
if (defaultValue.equals("null")) {
defaultValue = StringUtils.format("{}()", typeName);
}
builder.append(StringUtils.format("val {} = new mutable.ArrayBuffer[{}]()", result, typeName)).append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for ({} <- 0 until {}) {", i, size)).append(LS);
var readObject = CodeGenerateScala.scalaSerializer(arrayField.getArrayElementRegistration().serializer())
.readObject(builder, deep + 2, field, arrayField.getArrayElementRegistration());
GenerateProtocolFile.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.addOne({})", result, readObject));
builder.append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append("}").append(LS);
return result + ".toArray";
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaBooleanSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
return new Pair<>("Boolean", "false");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.writeBool({})", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = buffer.readBool", result)).append(LS);
return result;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaByteSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
return new Pair<>("Byte", "0");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.writeByte({})", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = buffer.readByte", result)).append(LS);
return result;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaDoubleSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
return new Pair<>("Double", "0D");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.writeDouble({})", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = buffer.readDouble", result)).append(LS);
return result;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaFloatSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
return new Pair<>("Float", "0f");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.writeFloat({})", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = buffer.readFloat", result)).append(LS);
return result;
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaIntSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
return new Pair<>("Int", "0");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.writeInt({})", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = buffer.readInt", result)).append(LS);
return result;
}
}
@@ -0,0 +1,98 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ListField;
import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.serializer.CutDownListSerializer;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaListSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
var type = StringUtils.format("{}", CodeGenerateScala.toScalaClassName(field.getGenericType().toString()));
return new Pair<>(type, "_");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
if (CutDownListSerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.Scala)) {
return;
}
ListField listField = (ListField) fieldRegistration;
builder.append(StringUtils.format("buffer.writeInt({}.size)", objectStr)).append(LS);
GenerateProtocolFile.addTab(builder, deep);
String element = "element" + GenerateProtocolFile.localVariableId++;
builder.append(StringUtils.format("for ({} <- {}) {", element, objectStr)).append(LS);
CodeGenerateScala.scalaSerializer(listField.getListElementRegistration().serializer())
.writeObject(builder, element, deep + 1, field, listField.getListElementRegistration());
GenerateProtocolFile.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
var cutDown = CutDownListSerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.Scala);
if (cutDown != null) {
return cutDown;
}
var listField = (ListField) fieldRegistration;
var result = "result" + GenerateProtocolFile.localVariableId++;
var typeName = CodeGenerateScala.toScalaClassName(listField.getType().toString());
var i = "index" + GenerateProtocolFile.localVariableId++;
var size = "size" + GenerateProtocolFile.localVariableId++;
builder.append(StringUtils.format("val {} = buffer.readInt", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = new mutable.ListBuffer{}()", result, StringUtils.substringAfterFirst(typeName, "List"))).append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for ({} <- 0 until {}) {", i, size)).append(LS);
var readObject = CodeGenerateScala.scalaSerializer(listField.getListElementRegistration().serializer())
.readObject(builder, deep + 2, field, listField.getListElementRegistration());
GenerateProtocolFile.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.addOne({})", result, readObject)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append("}").append(LS);
return result + ".toList";
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaLongSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
return new Pair<>("Long", "0L");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.writeLong({})", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = buffer.readLong", result)).append(LS);
return result;
}
}
@@ -0,0 +1,107 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.MapField;
import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.serializer.CutDownMapSerializer;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaMapSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
var type = StringUtils.format("{}", CodeGenerateScala.toScalaClassName(field.getGenericType().toString()));
return new Pair<>(type, "_");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
if (CutDownMapSerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.Scala)) {
return;
}
MapField mapField = (MapField) fieldRegistration;
builder.append(StringUtils.format("buffer.writeInt({}.size)", objectStr)).append(LS);
GenerateProtocolFile.addTab(builder, deep);
String key = "keyElement" + GenerateProtocolFile.localVariableId++;
String value = "valueElement" + GenerateProtocolFile.localVariableId++;
builder.append(StringUtils.format("for (({}, {}) <- {}) {", key,value, objectStr)).append(LS);
CodeGenerateScala.scalaSerializer(mapField.getMapKeyRegistration().serializer())
.writeObject(builder, key, deep + 1, field, mapField.getMapKeyRegistration());
CodeGenerateScala.scalaSerializer(mapField.getMapValueRegistration().serializer())
.writeObject(builder, value, deep + 1, field, mapField.getMapValueRegistration());
GenerateProtocolFile.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
var cutDown = CutDownMapSerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.Scala);
if (cutDown != null) {
return cutDown;
}
MapField mapField = (MapField) fieldRegistration;
String result = "result" + GenerateProtocolFile.localVariableId++;
var typeName = CodeGenerateScala.toScalaClassName(mapField.getType().toString());
String size = "size" + GenerateProtocolFile.localVariableId++;
builder.append(StringUtils.format("val {} = buffer.readInt", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = new mutable.HashMap{}()", result, StringUtils.substringAfterFirst(typeName, "Map"))).append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS);
String i = "index" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for ({} <- 0 until {}) {", i, size)).append(LS);
String keyObject = CodeGenerateScala.scalaSerializer(mapField.getMapKeyRegistration().serializer())
.readObject(builder, deep + 2, field, mapField.getMapKeyRegistration());
String valueObject = CodeGenerateScala.scalaSerializer(mapField.getMapValueRegistration().serializer())
.readObject(builder, deep + 2, field, mapField.getMapValueRegistration());
GenerateProtocolFile.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.put({}, {})", result, keyObject, valueObject)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append("}").append(LS);
return result + ".toMap";
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ObjectProtocolField;
import com.zfoo.protocol.serializer.enhance.EnhanceObjectProtocolSerializer;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaObjectProtocolSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
var protocolSimpleName = EnhanceObjectProtocolSerializer.getProtocolClassSimpleName(objectProtocolField.getProtocolId());
return new Pair<>(protocolSimpleName, "_");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.writePacket({}, {})", objectStr, objectProtocolField.getProtocolId()))
.append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
String result = "result" + GenerateProtocolFile.localVariableId++;
var protocolSimpleName = EnhanceObjectProtocolSerializer.getProtocolClassSimpleName(objectProtocolField.getProtocolId());
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = buffer.readPacket({}).asInstanceOf[{}]", result, objectProtocolField.getProtocolId(), protocolSimpleName))
.append(LS);
return result;
}
}
@@ -0,0 +1,98 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.SetField;
import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.serializer.CutDownSetSerializer;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaSetSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
var type = StringUtils.format("{}", CodeGenerateScala.toScalaClassName(field.getGenericType().toString()));
return new Pair<>(type, "_");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
if (CutDownSetSerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.Scala)) {
return;
}
SetField setField = (SetField) fieldRegistration;
builder.append(StringUtils.format("buffer.writeInt({}.size)", objectStr)).append(LS);
String element = "i" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep );
builder.append(StringUtils.format("for ({} <- {}) {", element, objectStr)).append(LS);
CodeGenerateScala.scalaSerializer(setField.getSetElementRegistration().serializer())
.writeObject(builder, element, deep + 1, field, setField.getSetElementRegistration());
GenerateProtocolFile.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
var cutDown = CutDownSetSerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.Scala);
if (cutDown != null) {
return cutDown;
}
SetField setField = (SetField) fieldRegistration;
var result = "result" + GenerateProtocolFile.localVariableId++;
var typeName = CodeGenerateScala.toScalaClassName(setField.getType().toString());
var i = "index" + GenerateProtocolFile.localVariableId++;
var size = "size" + GenerateProtocolFile.localVariableId++;
builder.append(StringUtils.format("val {} = buffer.readInt", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = new mutable.HashSet{}()", result, StringUtils.substringAfterFirst(typeName, "Set"))).append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for ({} <- 0 until {}) {", i, size)).append(LS);
var readObject = CodeGenerateScala.scalaSerializer(setField.getSetElementRegistration().serializer())
.readObject(builder, deep + 2, field, setField.getSetElementRegistration());
GenerateProtocolFile.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.add({})", result, readObject)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateProtocolFile.addTab(builder, deep);
builder.append("}").append(LS);
return result + ".toSet";
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaShortSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
return new Pair<>("Short", "0");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.writeShort({})", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = buffer.readShort", result)).append(LS);
return result;
}
}
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.scala;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class ScalaStringSerializer implements IScalaSerializer {
@Override
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
return new Pair<>("String", "_");
}
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.writeString({})", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("val {} = buffer.readString", result)).append(LS);
return result;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
${protocol_root_path}
trait IProtocolRegistration {
def protocolId: Short
def write(buffer: ByteBuffer, packet: Any): Unit
def read(buffer: ByteBuffer): Any
}
@@ -0,0 +1,4 @@
${protocol_note}
class ${protocol_name} {
${protocol_field_definition}
}
@@ -0,0 +1,35 @@
${protocol_root_path}
${protocol_imports}
import scala.collection.mutable
object ProtocolManager {
val MAX_PROTOCOL_NUM: Short = Short.MaxValue
val protocols = new Array[IProtocolRegistration](MAX_PROTOCOL_NUM)
val protocolIdMap = mutable.Map[Class[_], Short]()
def initProtocol(): Unit = {
// initProtocol
${protocol_manager_registrations}
}
def getProtocolId(clazz: Class[_]): Short = protocolIdMap.getOrElse(clazz, -1)
def getProtocol(protocolId: Short): IProtocolRegistration = {
val protocol = protocols(protocolId)
if (protocol == null) throw new RuntimeException("[protocolId:" + protocolId + "] not exist")
protocol
}
def write(buffer: ByteBuffer, packet: Any): Unit = {
val protocolId = getProtocolId(packet.getClass)
// write protocol id to buffer
buffer.writeShort(protocolId)
// write packet
getProtocol(protocolId).write(buffer, packet)
}
def read(buffer: ByteBuffer): Any = {
val protocolId = buffer.readShort
getProtocol(protocolId).read(buffer)
}
}
@@ -0,0 +1,22 @@
object Registration${protocol_name} extends IProtocolRegistration {
override def protocolId: Short = ${protocol_id}
override def write(buffer: ByteBuffer, packet: Any): Unit = {
if (packet == null) {
buffer.writeInt(0)
return
}
val message = packet.asInstanceOf[${protocol_name}]
${protocol_write_serialization}
}
override def read(buffer: ByteBuffer): AnyRef = {
val length: Int = buffer.readInt
if (length == 0) return null
val beforeReadIndex: Int = buffer.getReadOffset
val packet: ${protocol_name} = new ${protocol_name}
${protocol_read_deserialization}
if (length > 0) buffer.setReadOffset(beforeReadIndex + length)
packet
}
}
@@ -0,0 +1,7 @@
${protocol_root_path}
${protocol_imports}
import scala.collection.mutable
${protocol_class}
${protocol_registration}
@@ -0,0 +1,9 @@
${protocol_root_path}
${protocol_imports}
import scala.collection.mutable
${protocol_class}
// -----------------------------------------------------------------------------------------------------------------
${protocol_registration}