mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-05-21 00:25:16 +00:00
feat[protocol]: kotlin protocol support
This commit is contained in:
@@ -19,6 +19,7 @@ import com.zfoo.protocol.serializer.gdscript.CodeGenerateGdScript;
|
||||
import com.zfoo.protocol.serializer.golang.CodeGenerateGolang;
|
||||
import com.zfoo.protocol.serializer.java.CodeGenerateJava;
|
||||
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.typescript.CodeGenerateTypeScript;
|
||||
@@ -35,7 +36,7 @@ public enum CodeLanguage {
|
||||
|
||||
Java(1<<1, CodeGenerateJava.class),
|
||||
|
||||
Kotlin(1<<2, null),
|
||||
Kotlin(1<<2, CodeGenerateKotlin.class),
|
||||
|
||||
Scala(1<<3, null),
|
||||
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* 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.kotlin;
|
||||
|
||||
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 CodeGenerateKotlin implements ICodeGenerate {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CodeGenerateKotlin.class);
|
||||
|
||||
// custom configuration
|
||||
public static String protocolOutputRootPath = "zfookt";
|
||||
private static String protocolOutputPath = StringUtils.EMPTY;
|
||||
public static String protocolPackage = "com.zfoo.java";
|
||||
|
||||
private static final Map<ISerializer, IKtSerializer> kotlinSerializerMap = new HashMap<>();
|
||||
|
||||
public static IKtSerializer kotlinSerializer(ISerializer serializer) {
|
||||
return kotlinSerializerMap.get(serializer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(GenerateOperation generateOperation) {
|
||||
protocolOutputPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
|
||||
FileUtils.deleteFile(new File(protocolOutputPath));
|
||||
|
||||
kotlinSerializerMap.put(BooleanSerializer.INSTANCE, new KtBooleanSerializer());
|
||||
kotlinSerializerMap.put(ByteSerializer.INSTANCE, new KtByteSerializer());
|
||||
kotlinSerializerMap.put(ShortSerializer.INSTANCE, new KtShortSerializer());
|
||||
kotlinSerializerMap.put(IntSerializer.INSTANCE, new KtIntSerializer());
|
||||
kotlinSerializerMap.put(LongSerializer.INSTANCE, new KtLongSerializer());
|
||||
kotlinSerializerMap.put(FloatSerializer.INSTANCE, new KtFloatSerializer());
|
||||
kotlinSerializerMap.put(DoubleSerializer.INSTANCE, new KtDoubleSerializer());
|
||||
kotlinSerializerMap.put(StringSerializer.INSTANCE, new KtStringSerializer());
|
||||
kotlinSerializerMap.put(ArraySerializer.INSTANCE, new KtArraySerializer());
|
||||
kotlinSerializerMap.put(ListSerializer.INSTANCE, new KtListSerializer());
|
||||
kotlinSerializerMap.put(SetSerializer.INSTANCE, new KtSetSerializer());
|
||||
kotlinSerializerMap.put(MapSerializer.INSTANCE, new KtMapSerializer());
|
||||
kotlinSerializerMap.put(ObjectProtocolSerializer.INSTANCE, new KtObjectProtocolSerializer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergerProtocol(List<ProtocolRegistration> registrations) throws IOException {
|
||||
createTemplateFile();
|
||||
var protocol_root_path = StringUtils.format("package {};", protocolPackage);
|
||||
|
||||
var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("java/ProtocolManagerTemplate.java");
|
||||
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[{}] = Protocols.registration{};", protocol_id, protocol_name)).append(LS);
|
||||
protocol_manager_registrations.append(StringUtils.format("protocolIdMap.put(Protocols.{}.class, (short){});", 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.java"));
|
||||
FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true);
|
||||
logger.info("Generated Kotlin 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("java/ProtocolsTemplate.java");
|
||||
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().replace("public class", "public static class")
|
||||
, CodeTemplatePlaceholder.protocol_registration, protocol_registration.toString()
|
||||
));
|
||||
var outputPath = StringUtils.format("{}/Protocols.java", protocolOutputPath);
|
||||
var file = new File(outputPath);
|
||||
FileUtils.writeStringToFile(file, formatProtocolTemplate, true);
|
||||
logger.info("Generated Kotlin protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void foldProtocol(List<ProtocolRegistration> registrations) throws IOException {
|
||||
createTemplateFile();
|
||||
|
||||
var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("java/ProtocolManagerTemplate.java");
|
||||
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_manager_registrations.append(StringUtils.format("protocols[{}] = {}.registration{};", protocol_id, protocol_name, protocol_name)).append(LS);
|
||||
protocol_manager_registrations.append(StringUtils.format("protocolIdMap.put({}.class, (short){});", 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.java"));
|
||||
FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true);
|
||||
logger.info("Generated Kotlin 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("java/ProtocolTemplate.java");
|
||||
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.Kotlin)
|
||||
, CodeTemplatePlaceholder.protocol_name, protocol_name
|
||||
, CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration)
|
||||
, CodeTemplatePlaceholder.protocol_registration, protocol_registration(registration)
|
||||
));
|
||||
var outputPath = StringUtils.format("{}/{}/{}.java", protocolOutputPath, GenerateProtocolPath.protocolPathSlash(protocol_id), protocol_name);
|
||||
var file = new File(outputPath);
|
||||
FileUtils.writeStringToFile(file, formatProtocolTemplate, true);
|
||||
logger.info("Generated Kotlin 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("kotlin/ProtocolManagerTemplate.kt");
|
||||
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, protocol_name)).append(LS);
|
||||
protocol_manager_registrations.append(StringUtils.format("protocolIdMap[{}::class.java] = {}.toShort()", 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.kt"));
|
||||
FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true);
|
||||
logger.info("Generated Kotlin 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("kotlin/ProtocolTemplate.kt");
|
||||
var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of(
|
||||
CodeTemplatePlaceholder.protocol_root_path, protocol_root_path
|
||||
, CodeTemplatePlaceholder.protocol_imports, StringUtils.EMPTY
|
||||
, CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Kotlin)
|
||||
, CodeTemplatePlaceholder.protocol_name, protocol_name
|
||||
, CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration)
|
||||
, CodeTemplatePlaceholder.protocol_registration, protocol_registration(registration)
|
||||
));
|
||||
var outputPath = StringUtils.format("{}/{}.kt", protocolOutputPath, protocol_name);
|
||||
var file = new File(outputPath);
|
||||
FileUtils.writeStringToFile(file, formatProtocolTemplate, true);
|
||||
logger.info("Generated Kotlin protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
private void createTemplateFile() {
|
||||
var rootPackage = StringUtils.format("package {}", protocolPackage);
|
||||
var list = List.of("kotlin/IProtocolRegistration.kt"
|
||||
, "kotlin/ByteBuffer.kt");
|
||||
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, "kotlin/")));
|
||||
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("kotlin/ProtocolClassTemplate.kt");
|
||||
var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of(
|
||||
CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Kotlin)
|
||||
, CodeTemplatePlaceholder.protocol_name, protocol_name
|
||||
, CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id)
|
||||
, CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration)
|
||||
, CodeTemplatePlaceholder.protocol_registration, protocol_registration(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("kotlin/ProtocolRegistrationTemplate.kt");
|
||||
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 ktBuilder = new StringBuilder();
|
||||
for (var subProtocolId : subProtocols) {
|
||||
var protocolName = EnhanceObjectProtocolSerializer.getProtocolClassSimpleName(subProtocolId);
|
||||
var subProtocolPath = StringUtils.format("import {}.{}.{}", protocolPackage, GenerateProtocolPath.protocolPathPeriod(subProtocolId), protocolName);
|
||||
ktBuilder.append(subProtocolPath).append(LS);
|
||||
}
|
||||
ktBuilder.append(StringUtils.format("import {}.IProtocolRegistration", protocolPackage)).append(LS);
|
||||
ktBuilder.append(StringUtils.format("import {}.ByteBuffer", protocolPackage)).append(LS);
|
||||
return ktBuilder.toString();
|
||||
}
|
||||
|
||||
private String protocol_field_definition(ProtocolRegistration registration) {
|
||||
var protocolId = registration.getId();
|
||||
var fields = registration.getFields();
|
||||
var fieldRegistrations = registration.getFieldRegistrations();
|
||||
var ktBuilder = 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.Kotlin);
|
||||
for (var fieldNote : fieldNotes) {
|
||||
ktBuilder.append(fieldNote).append(LS);
|
||||
}
|
||||
var pair = kotlinSerializer(fieldRegistration.serializer()).field(field, fieldRegistration);
|
||||
ktBuilder.append(StringUtils.format("{}: {} = {}", fieldName, pair.getKey(), pair.getValue())).append(LS);
|
||||
}
|
||||
return ktBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
private String protocol_write_serialization(ProtocolRegistration registration) {
|
||||
GenerateProtocolFile.localVariableId = 0;
|
||||
var fields = registration.getFields();
|
||||
var fieldRegistrations = registration.getFieldRegistrations();
|
||||
var ktBuilder = new StringBuilder();
|
||||
if (registration.isCompatible()) {
|
||||
ktBuilder.append("val beforeWriteIndex = buffer.writeOffset()").append(LS);
|
||||
ktBuilder.append(StringUtils.format("buffer.writeInt({})", registration.getPredictionLength())).append(LS);
|
||||
} else {
|
||||
ktBuilder.append("buffer.writeInt(-1)").append(LS);
|
||||
}
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
var field = fields[i];
|
||||
var fieldRegistration = fieldRegistrations[i];
|
||||
kotlinSerializer(fieldRegistration.serializer()).writeObject(ktBuilder, "message." + field.getName(), 0, field, fieldRegistration);
|
||||
}
|
||||
if (registration.isCompatible()) {
|
||||
ktBuilder.append(StringUtils.format("buffer.adjustPadding({}, beforeWriteIndex)", registration.getPredictionLength())).append(LS);
|
||||
}
|
||||
return ktBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
private String protocol_read_deserialization(ProtocolRegistration registration) {
|
||||
GenerateProtocolFile.localVariableId = 0;
|
||||
var fields = registration.getFields();
|
||||
var fieldRegistrations = registration.getFieldRegistrations();
|
||||
var ktBuilder = new StringBuilder();
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
var field = fields[i];
|
||||
var fieldRegistration = fieldRegistrations[i];
|
||||
|
||||
if (field.isAnnotationPresent(Compatible.class)) {
|
||||
ktBuilder.append("if (buffer.compatibleRead(beforeReadIndex, length)) {").append(LS);
|
||||
var compatibleReadObject = kotlinSerializer(fieldRegistration.serializer()).readObject(ktBuilder, 1, field, fieldRegistration);
|
||||
ktBuilder.append(TAB).append(StringUtils.format("packet.{} = {}", field.getName(), compatibleReadObject)).append(LS);
|
||||
ktBuilder.append("}").append(LS);
|
||||
continue;
|
||||
}
|
||||
var readObject = kotlinSerializer(fieldRegistration.serializer()).readObject(ktBuilder, 0, field, fieldRegistration);
|
||||
ktBuilder.append(StringUtils.format("packet.{} = {}", field.getName(), readObject)).append(LS);
|
||||
}
|
||||
return ktBuilder.toString();
|
||||
}
|
||||
|
||||
public static String toKotlinClassName(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<", "Array<");
|
||||
|
||||
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.kotlin;
|
||||
|
||||
import com.zfoo.protocol.model.Pair;
|
||||
import com.zfoo.protocol.registration.field.IFieldRegistration;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
*/
|
||||
public interface IKtSerializer {
|
||||
/**
|
||||
* 获取属性的类型,默认值
|
||||
*/
|
||||
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,115 @@
|
||||
/*
|
||||
* 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.kotlin;
|
||||
|
||||
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 KtArraySerializer implements IKtSerializer {
|
||||
|
||||
@Override
|
||||
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
|
||||
var type = StringUtils.format("Array<{}>", CodeGenerateKotlin.toKotlinClassName(field.getType().getComponentType().getSimpleName()));
|
||||
return new Pair<>(type, "emptyArray()");
|
||||
}
|
||||
|
||||
@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.Kotlin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayField arrayField = (ArrayField) fieldRegistration;
|
||||
|
||||
builder.append(StringUtils.format("if (({} == null) || ({}.length == 0)) {", objectStr, objectStr)).append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append("buffer.writeInt(0);").append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
|
||||
builder.append("} else {").append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append(StringUtils.format("buffer.writeInt({}.length);", objectStr)).append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
String length = "length" + GenerateProtocolFile.localVariableId++;
|
||||
builder.append(StringUtils.format("int {} = {}.length;", length, objectStr)).append(LS);
|
||||
|
||||
String i = "i" + GenerateProtocolFile.localVariableId++;
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append(StringUtils.format("for (int {} = 0; {} < {}; {}++) {", i, i, length, i)).append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep + 2);
|
||||
String element = "element" + GenerateProtocolFile.localVariableId++;
|
||||
builder.append(StringUtils.format("{} {} = {}[{}];", CodeGenerateKotlin.toKotlinClassName(arrayField.getType().getSimpleName()), element, objectStr, i)).append(LS);
|
||||
|
||||
CodeGenerateKotlin.kotlinSerializer(arrayField.getArrayElementRegistration().serializer())
|
||||
.writeObject(builder, element, deep + 2, field, arrayField.getArrayElementRegistration());
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append("}").append(LS);
|
||||
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.Kotlin);
|
||||
if (cutDown != null) {
|
||||
return cutDown;
|
||||
}
|
||||
|
||||
|
||||
var arrayField = (ArrayField) fieldRegistration;
|
||||
var result = "result" + GenerateProtocolFile.localVariableId++;
|
||||
|
||||
var typeName = CodeGenerateKotlin.toKotlinClassName(arrayField.getType().getSimpleName());
|
||||
|
||||
var i = "index" + GenerateProtocolFile.localVariableId++;
|
||||
var size = "size" + GenerateProtocolFile.localVariableId++;
|
||||
builder.append(StringUtils.format("int {} = buffer.readInt();", size)).append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
builder.append(StringUtils.format("{}[] {} = new {}[{}];", typeName, result, typeName, size)).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 (int {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS);
|
||||
var readObject = CodeGenerateKotlin.kotlinSerializer(arrayField.getArrayElementRegistration().serializer())
|
||||
.readObject(builder, deep + 2, field, arrayField.getArrayElementRegistration());
|
||||
GenerateProtocolFile.addTab(builder, deep + 2);
|
||||
builder.append(StringUtils.format("{}[{}] = {};", result, i, readObject));
|
||||
builder.append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append("}").append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
builder.append("}").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.kotlin;
|
||||
|
||||
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 KtBooleanSerializer implements IKtSerializer {
|
||||
|
||||
@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("boolean {} = 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.kotlin;
|
||||
|
||||
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 KtByteSerializer implements IKtSerializer {
|
||||
|
||||
@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("byte {} = 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.kotlin;
|
||||
|
||||
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 KtDoubleSerializer implements IKtSerializer {
|
||||
|
||||
@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.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("double {} = 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.kotlin;
|
||||
|
||||
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 KtFloatSerializer implements IKtSerializer {
|
||||
|
||||
@Override
|
||||
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
|
||||
return new Pair<>("Double", "0.0");
|
||||
}
|
||||
|
||||
@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("float {} = 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.kotlin;
|
||||
|
||||
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 KtIntSerializer implements IKtSerializer {
|
||||
|
||||
@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("int {} = buffer.readInt();", result)).append(LS);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.kotlin;
|
||||
|
||||
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 KtListSerializer implements IKtSerializer {
|
||||
|
||||
@Override
|
||||
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
|
||||
var type = StringUtils.format("{}", CodeGenerateKotlin.toKotlinClassName(field.getGenericType().toString()));
|
||||
return new Pair<>(type, "emptyList()");
|
||||
}
|
||||
|
||||
@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.Kotlin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ListField listField = (ListField) fieldRegistration;
|
||||
builder.append(StringUtils.format("if ({} == null) {", objectStr)).append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append("buffer.writeInt(0);").append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
builder.append("}").append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
builder.append("else {").append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append(StringUtils.format("buffer.writeInt({}.size());", objectStr)).append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
String length = "length" + GenerateProtocolFile.localVariableId++;
|
||||
builder.append(StringUtils.format("int {} = {}.size();", length, objectStr)).append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
String element = "element" + GenerateProtocolFile.localVariableId++;
|
||||
builder.append(StringUtils.format("for (var {} : {}) {", element, objectStr)).append(LS);
|
||||
|
||||
CodeGenerateKotlin.kotlinSerializer(listField.getListElementRegistration().serializer())
|
||||
.writeObject(builder, element, deep + 2, field, listField.getListElementRegistration());
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append("}").append(LS);
|
||||
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.Kotlin);
|
||||
if (cutDown != null) {
|
||||
return cutDown;
|
||||
}
|
||||
|
||||
var listField = (ListField) fieldRegistration;
|
||||
var result = "result" + GenerateProtocolFile.localVariableId++;
|
||||
|
||||
var typeName = CodeGenerateKotlin.toKotlinClassName(listField.getType().toString());
|
||||
|
||||
var i = "index" + GenerateProtocolFile.localVariableId++;
|
||||
var size = "size" + GenerateProtocolFile.localVariableId++;
|
||||
|
||||
builder.append(StringUtils.format("int {} = buffer.readInt();", size)).append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
builder.append(StringUtils.format("var {} = new Array{}({});", result, typeName, size)).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 (int {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS);
|
||||
var readObject = CodeGenerateKotlin.kotlinSerializer(listField.getListElementRegistration().serializer())
|
||||
.readObject(builder, deep + 2, field, listField.getListElementRegistration());
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.kotlin;
|
||||
|
||||
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 KtLongSerializer implements IKtSerializer {
|
||||
|
||||
@Override
|
||||
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
|
||||
return new Pair<>("Long", "0");
|
||||
}
|
||||
|
||||
@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("long {} = buffer.readLong();", result)).append(LS);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.kotlin;
|
||||
|
||||
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 KtMapSerializer implements IKtSerializer {
|
||||
|
||||
@Override
|
||||
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
|
||||
var type = StringUtils.format("{}", CodeGenerateKotlin.toKotlinClassName(field.getGenericType().toString()));
|
||||
return new Pair<>(type, "emptyMap()");
|
||||
}
|
||||
|
||||
@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.Kotlin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MapField mapField = (MapField) fieldRegistration;
|
||||
|
||||
builder.append(StringUtils.format("if ({} == null) {", objectStr, objectStr)).append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append("buffer.writeInt(0);").append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
builder.append("} else {").append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append(StringUtils.format("buffer.writeInt({}.size());", objectStr)).append(LS);
|
||||
|
||||
|
||||
String i = "i" + GenerateProtocolFile.localVariableId++;
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append(StringUtils.format("for (var {} : {}.entrySet()) {", i, objectStr)).append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 2);
|
||||
String key = "keyElement" + GenerateProtocolFile.localVariableId++;
|
||||
String value = "valueElement" + GenerateProtocolFile.localVariableId++;
|
||||
builder.append(StringUtils.format("var {} = {}.getKey();", key, i)).append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 2);
|
||||
builder.append(StringUtils.format("var {} = {}.getValue();", value, i)).append(LS);
|
||||
|
||||
CodeGenerateKotlin.kotlinSerializer(mapField.getMapKeyRegistration().serializer())
|
||||
.writeObject(builder, key, deep + 2, field, mapField.getMapKeyRegistration());
|
||||
CodeGenerateKotlin.kotlinSerializer(mapField.getMapValueRegistration().serializer())
|
||||
.writeObject(builder, value, deep + 2, field, mapField.getMapValueRegistration());
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append("}").append(LS);
|
||||
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.Kotlin);
|
||||
if (cutDown != null) {
|
||||
return cutDown;
|
||||
}
|
||||
|
||||
MapField mapField = (MapField) fieldRegistration;
|
||||
String result = "result" + GenerateProtocolFile.localVariableId++;
|
||||
|
||||
var typeName = CodeGenerateKotlin.toKotlinClassName(mapField.getType().toString());
|
||||
|
||||
String size = "size" + GenerateProtocolFile.localVariableId++;
|
||||
builder.append(StringUtils.format("int {} = buffer.readInt();", size)).append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
builder.append(StringUtils.format("var {} = new Hash{}({});", result, typeName, size)).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 (var {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS);
|
||||
|
||||
String keyObject = CodeGenerateKotlin.kotlinSerializer(mapField.getMapKeyRegistration().serializer())
|
||||
.readObject(builder, deep + 2, field, mapField.getMapKeyRegistration());
|
||||
|
||||
|
||||
String valueObject = CodeGenerateKotlin.kotlinSerializer(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;
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.kotlin;
|
||||
|
||||
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 KtObjectProtocolSerializer implements IKtSerializer {
|
||||
|
||||
@Override
|
||||
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
|
||||
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
|
||||
var protocolSimpleName = EnhanceObjectProtocolSerializer.getProtocolClassSimpleName(objectProtocolField.getProtocolId());
|
||||
var type = StringUtils.format("{}?", protocolSimpleName);
|
||||
return new Pair<>(type, "null");
|
||||
}
|
||||
|
||||
@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({}, (short){});", 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("{} {} = ({}) buffer.readPacket((short) {});", protocolSimpleName, result, protocolSimpleName, objectProtocolField.getProtocolId()))
|
||||
.append(LS);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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.kotlin;
|
||||
|
||||
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 KtSetSerializer implements IKtSerializer {
|
||||
|
||||
@Override
|
||||
public Pair<String, String> field(Field field, IFieldRegistration fieldRegistration) {
|
||||
var type = StringUtils.format("{}", CodeGenerateKotlin.toKotlinClassName(field.getGenericType().toString()));
|
||||
return new Pair<>(type, "emptySet()");
|
||||
}
|
||||
|
||||
@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.Kotlin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetField setField = (SetField) fieldRegistration;
|
||||
|
||||
builder.append(StringUtils.format("if ({} == null) {", objectStr)).append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append("buffer.writeInt(0);").append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
builder.append("} else {").append(LS);
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append(StringUtils.format("buffer.writeInt({}.size());", objectStr)).append(LS);
|
||||
|
||||
String element = "i" + GenerateProtocolFile.localVariableId++;
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append(StringUtils.format("for (var {} : {}) {", element, objectStr)).append(LS);
|
||||
|
||||
CodeGenerateKotlin.kotlinSerializer(setField.getSetElementRegistration().serializer())
|
||||
.writeObject(builder, element, deep + 2, field, setField.getSetElementRegistration());
|
||||
|
||||
GenerateProtocolFile.addTab(builder, deep + 1);
|
||||
builder.append("}").append(LS);
|
||||
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.Kotlin);
|
||||
if (cutDown != null) {
|
||||
return cutDown;
|
||||
}
|
||||
|
||||
SetField setField = (SetField) fieldRegistration;
|
||||
var result = "result" + GenerateProtocolFile.localVariableId++;
|
||||
|
||||
var typeName = CodeGenerateKotlin.toKotlinClassName(setField.getType().toString());
|
||||
|
||||
var i = "index" + GenerateProtocolFile.localVariableId++;
|
||||
var size = "size" + GenerateProtocolFile.localVariableId++;
|
||||
builder.append(StringUtils.format("int {} = buffer.readInt();", size)).append(LS);
|
||||
GenerateProtocolFile.addTab(builder, deep);
|
||||
// unity里不支持HashSet的初始化大小
|
||||
// builder.append("var " + result + " = new " + typeName + "(" + size + ");" + LS);
|
||||
builder.append(StringUtils.format("var {} = new Hash{}();", 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 (int {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS);
|
||||
|
||||
var readObject = CodeGenerateKotlin.kotlinSerializer(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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.kotlin;
|
||||
|
||||
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 KtShortSerializer implements IKtSerializer {
|
||||
|
||||
@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("short {} = 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.kotlin;
|
||||
|
||||
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 KtStringSerializer implements IKtSerializer {
|
||||
|
||||
@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("String {} = buffer.readString();", result)).append(LS);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+4
-4
@@ -265,19 +265,19 @@ public class CodeGenerateTypeScript implements ICodeGenerate {
|
||||
var fieldRegistrations = registration.getFieldRegistrations();
|
||||
// when generate source code fields, use origin fields sort
|
||||
var sequencedFields = ReflectionUtils.notStaticAndTransientFields(registration.getConstructor().getDeclaringClass());
|
||||
var fieldDefinitionBuilder = new StringBuilder();
|
||||
var tsBuilder = new StringBuilder();
|
||||
for (var field : sequencedFields) {
|
||||
var fieldRegistration = fieldRegistrations[GenerateProtocolFile.indexOf(fields, field)];
|
||||
var fieldName = field.getName();
|
||||
// 生成注释
|
||||
var fieldNotes = GenerateProtocolNote.fieldNotes(protocolId, fieldName, CodeLanguage.TypeScript);
|
||||
for (var fieldNote : fieldNotes) {
|
||||
fieldDefinitionBuilder.append(fieldNote).append(LS);
|
||||
tsBuilder.append(fieldNote).append(LS);
|
||||
}
|
||||
var triple = tsSerializer(fieldRegistration.serializer()).field(field, fieldRegistration);
|
||||
fieldDefinitionBuilder.append(StringUtils.format("{}{} = {};", triple.getMiddle(), triple.getLeft(), triple.getRight())).append(LS);
|
||||
tsBuilder.append(StringUtils.format("{}{} = {};", triple.getMiddle(), triple.getLeft(), triple.getRight())).append(LS);
|
||||
}
|
||||
return fieldDefinitionBuilder.toString();
|
||||
return tsBuilder.toString();
|
||||
}
|
||||
|
||||
private String protocol_write_serialization(ProtocolRegistration registration) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
${protocol_root_path}
|
||||
|
||||
interface IProtocolRegistration {
|
||||
fun protocolId(): Short
|
||||
fun write(buffer: ByteBuffer, packet: Any?)
|
||||
fun read(buffer: ByteBuffer): Any?
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
${protocol_note}
|
||||
class ${protocol_name} {
|
||||
${protocol_field_definition}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
${protocol_root_path}
|
||||
${protocol_imports}
|
||||
class ProtocolManager {
|
||||
val protocols = arrayOfNulls<IProtocolRegistration>(Short.MAX_VALUE.toInt())
|
||||
var protocolIdMap: MutableMap<Class<*>, Short> = HashMap()
|
||||
fun initProtocol() {
|
||||
// initProtocol
|
||||
${protocol_manager_registrations}
|
||||
}
|
||||
|
||||
fun getProtocolId(clazz: Class<*>): Short {
|
||||
return protocolIdMap[clazz]!!
|
||||
}
|
||||
|
||||
fun getProtocol(protocolId: Short): IProtocolRegistration {
|
||||
return protocols[protocolId.toInt()]
|
||||
?: throw RuntimeException("[protocolId:$protocolId] not exist")
|
||||
}
|
||||
|
||||
fun write(buffer: ByteBuffer, packet: Any) {
|
||||
val protocolId = getProtocolId(packet.javaClass)
|
||||
// write protocol id to buffer
|
||||
buffer.writeShort(protocolId)
|
||||
// write packet
|
||||
getProtocol(protocolId).write(buffer, packet)
|
||||
}
|
||||
|
||||
fun read(buffer: ByteBuffer): Any? {
|
||||
val protocolId = buffer.readShort()
|
||||
return getProtocol(protocolId).read(buffer)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
companion object {
|
||||
@JvmField
|
||||
val registration${protocol_name}: IProtocolRegistration = object : IProtocolRegistration {
|
||||
override fun protocolId(): Short {
|
||||
return ${protocol_id}
|
||||
}
|
||||
|
||||
override fun write(buffer: ByteBuffer, packet: Any?) {
|
||||
if (packet == null) {
|
||||
buffer.writeInt(0)
|
||||
return
|
||||
}
|
||||
val message = packet as ${protocol_name}
|
||||
${protocol_write_serialization}
|
||||
}
|
||||
|
||||
override fun read(buffer: ByteBuffer): Any? {
|
||||
val length = buffer.readInt()
|
||||
if (length == 0) {
|
||||
return null
|
||||
}
|
||||
val beforeReadIndex = buffer.readOffset()
|
||||
val packet = ${protocol_name}()
|
||||
${protocol_read_deserialization}
|
||||
if (length > 0) {
|
||||
buffer.setReadOffset(beforeReadIndex + length)
|
||||
}
|
||||
return packet
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
${protocol_root_path}
|
||||
${protocol_imports}
|
||||
${protocol_note}
|
||||
class ${protocol_name} {
|
||||
${protocol_field_definition}
|
||||
|
||||
${protocol_registration}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
${protocol_root_path}
|
||||
${protocol_imports}
|
||||
import java.util.*;
|
||||
public class Protocols {
|
||||
${protocol_class}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
${protocol_registration}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
import com.zfoo.java.ByteBuffer;
|
||||
import com.zfoo.java.ProtocolManager;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author godotg
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println("zfoo test");
|
||||
ProtocolManager.initProtocol();
|
||||
byteBufferTest();
|
||||
compatibleTest();
|
||||
normalReadTest();
|
||||
}
|
||||
|
||||
|
||||
public static void byteBufferTest() {
|
||||
byteTest();
|
||||
bytesTest();
|
||||
shortTest();
|
||||
intTest();
|
||||
longTest();
|
||||
floatTest();
|
||||
doubleTest();
|
||||
stringTest();
|
||||
}
|
||||
|
||||
public static void byteTest() {
|
||||
byte value = 9;
|
||||
ByteBuffer writerByteBuffer = new ByteBuffer();
|
||||
writerByteBuffer.writeByte(value);
|
||||
byte[] bytes = writerByteBuffer.toBytes();
|
||||
|
||||
ByteBuffer readerByteBuffer = new ByteBuffer();
|
||||
readerByteBuffer.writeBytes(bytes);
|
||||
byte readValue = readerByteBuffer.readByte();
|
||||
assertEquals(value, readValue);
|
||||
}
|
||||
|
||||
public static void bytesTest() {
|
||||
var value = new byte[]{1, 2, 3};
|
||||
ByteBuffer writerByteBuffer = new ByteBuffer();
|
||||
writerByteBuffer.writeBytes(value);
|
||||
byte[] bytes = writerByteBuffer.toBytes();
|
||||
|
||||
ByteBuffer readerByteBuffer = new ByteBuffer();
|
||||
readerByteBuffer.writeBytes(bytes);
|
||||
var readValue = readerByteBuffer.readBytes(3);
|
||||
assertEquals(value, readValue);
|
||||
}
|
||||
|
||||
public static void shortTest() {
|
||||
short value = 9999;
|
||||
ByteBuffer writerByteBuffer = new ByteBuffer();
|
||||
writerByteBuffer.writeShort(value);
|
||||
byte[] bytes = writerByteBuffer.toBytes();
|
||||
|
||||
ByteBuffer readerByteBuffer = new ByteBuffer();
|
||||
readerByteBuffer.writeBytes(bytes);
|
||||
short readValue = readerByteBuffer.readShort();
|
||||
assertEquals(value, readValue);
|
||||
}
|
||||
|
||||
public static void intTest() {
|
||||
int value = 99999999;
|
||||
ByteBuffer writerByteBuffer = new ByteBuffer();
|
||||
writerByteBuffer.writeInt(value);
|
||||
byte[] bytes = writerByteBuffer.toBytes();
|
||||
|
||||
ByteBuffer readerByteBuffer = new ByteBuffer();
|
||||
readerByteBuffer.writeBytes(bytes);
|
||||
int readValue = readerByteBuffer.readInt();
|
||||
assertEquals(value, readValue);
|
||||
}
|
||||
|
||||
public static void longTest() {
|
||||
long value = 9999999999999999L;
|
||||
ByteBuffer writerByteBuffer = new ByteBuffer();
|
||||
writerByteBuffer.writeLong(value);
|
||||
byte[] bytes = writerByteBuffer.toBytes();
|
||||
|
||||
ByteBuffer readerByteBuffer = new ByteBuffer();
|
||||
readerByteBuffer.writeBytes(bytes);
|
||||
long readValue = readerByteBuffer.readLong();
|
||||
assertEquals(value, readValue);
|
||||
}
|
||||
|
||||
public static void floatTest() {
|
||||
float value = 999999.56F;
|
||||
ByteBuffer writerByteBuffer = new ByteBuffer();
|
||||
writerByteBuffer.writeFloat(value);
|
||||
byte[] bytes = writerByteBuffer.toBytes();
|
||||
|
||||
ByteBuffer readerByteBuffer = new ByteBuffer();
|
||||
readerByteBuffer.writeBytes(bytes);
|
||||
float readValue = readerByteBuffer.readFloat();
|
||||
assertEquals(value, readValue);
|
||||
}
|
||||
|
||||
public static void doubleTest() {
|
||||
double value = 999999.56;
|
||||
ByteBuffer writerByteBuffer = new ByteBuffer();
|
||||
writerByteBuffer.writeDouble(value);
|
||||
byte[] bytes = writerByteBuffer.toBytes();
|
||||
|
||||
ByteBuffer readerByteBuffer = new ByteBuffer();
|
||||
readerByteBuffer.writeBytes(bytes);
|
||||
double readValue = readerByteBuffer.readDouble();
|
||||
assertEquals(value, readValue);
|
||||
}
|
||||
|
||||
public static void stringTest() {
|
||||
String value = "aaa";
|
||||
ByteBuffer writerByteBuffer = new ByteBuffer();
|
||||
writerByteBuffer.writeString(value);
|
||||
byte[] bytes = writerByteBuffer.toBytes();
|
||||
|
||||
ByteBuffer readerByteBuffer = new ByteBuffer();
|
||||
readerByteBuffer.writeBytes(bytes);
|
||||
String readValue = readerByteBuffer.readString();
|
||||
assertEquals(value, readValue);
|
||||
}
|
||||
|
||||
public static void assertEquals(Object a, Object b) {
|
||||
if (a.equals(b)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("a is not equals b");
|
||||
}
|
||||
|
||||
public static void assertEquals(byte[] a, byte[] b) {
|
||||
if (a == b) {
|
||||
return;
|
||||
}
|
||||
if (a != null && b != null && a.length == b.length) {
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
assertEquals(a[i], b[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("a is not equals b");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
public static void compatibleTest() throws IOException {
|
||||
var bytes = toByteArray(new FileInputStream("D:\\Project\\zfoo\\protocol\\src\\test\\resources\\complexObject.bytes"));
|
||||
var buffer = new ByteBuffer();
|
||||
buffer.writeBytes(bytes);
|
||||
|
||||
var packet = ProtocolManager.read(buffer);
|
||||
|
||||
var newBuffer = new ByteBuffer();
|
||||
ProtocolManager.write(newBuffer, packet);
|
||||
|
||||
buffer.setReadOffset(0);
|
||||
newBuffer.setReadOffset(0);
|
||||
|
||||
var equal = 0;
|
||||
var notEqual = 0;
|
||||
for (int i = 0; i < buffer.writeOffset(); i++) {
|
||||
var a = buffer.readByte();
|
||||
var b = newBuffer.readByte();
|
||||
if (a == b) {
|
||||
equal++;
|
||||
} else {
|
||||
notEqual++;
|
||||
}
|
||||
}
|
||||
System.out.println(format("equal [{}], not equal [{}]", equal, notEqual));
|
||||
}
|
||||
|
||||
|
||||
public static void normalReadTest() throws IOException {
|
||||
|
||||
// var bytes = toByteArray(new FileInputStream("D:\\Project\\zfoo\\protocol\\src\\test\\resources\\compatible\\normal-inner-compatible.bytes"));
|
||||
// var bytes = toByteArray(new FileInputStream("D:\\Project\\zfoo\\protocol\\src\\test\\resources\\compatible\\normal-out-compatible.bytes"));
|
||||
// var bytes = toByteArray(new FileInputStream("D:\\Project\\zfoo\\protocol\\src\\test\\resources\\compatible\\normal-inner-compatible.bytes"));
|
||||
// var bytes = toByteArray(new FileInputStream("D:\\Project\\zfoo\\protocol\\src\\test\\resources\\compatible\\normal-out-inner-compatible.bytes"));
|
||||
var bytes = toByteArray(new FileInputStream("D:\\Project\\zfoo\\protocol\\src\\test\\resources\\compatible\\normal-out-inner-inner-compatible.bytes"));
|
||||
|
||||
var buffer = new ByteBuffer();
|
||||
buffer.writeBytes(bytes);
|
||||
var packet = ProtocolManager.read(buffer);
|
||||
|
||||
System.out.println(packet);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
public static byte[] toByteArray(final InputStream input) throws IOException {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
copy(input, output);
|
||||
var bytes = output.toByteArray();
|
||||
return bytes;
|
||||
}
|
||||
public static final int EOF = -1;
|
||||
|
||||
// The number of bytes in a byte
|
||||
public static final int ONE_BYTE = 1;
|
||||
// The number of bytes in a kilobyte
|
||||
public static final int BYTES_PER_KB = ONE_BYTE * 1024;
|
||||
// The number of bytes in a megabyte
|
||||
public static final int BYTES_PER_MB = BYTES_PER_KB * 1024;
|
||||
// The number of bytes in a gigabyte
|
||||
public static final long BYTES_PER_GB = BYTES_PER_MB * 1024;
|
||||
public static int copy(final InputStream input, final OutputStream output) throws IOException {
|
||||
byte[] buffer = new byte[BYTES_PER_KB];
|
||||
long count = 0;
|
||||
int n;
|
||||
while (EOF != (n = input.read(buffer))) {
|
||||
output.write(buffer, 0, n);
|
||||
count += n;
|
||||
}
|
||||
|
||||
if (count > BYTES_PER_GB * 2L) {
|
||||
return -1;
|
||||
}
|
||||
return (int) count;
|
||||
}
|
||||
|
||||
public static String format(final String template, final Object... args) {
|
||||
// 初始化定义好的长度以获得更好的性能
|
||||
var builder = new StringBuilder(template.length() + 50);
|
||||
|
||||
// 记录已经处理到的位置
|
||||
var readIndex = 0;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
// 占位符所在位置
|
||||
var placeholderIndex = template.indexOf("{}", readIndex);
|
||||
// 剩余部分无占位符
|
||||
if (placeholderIndex == -1) {
|
||||
// 不带占位符的模板直接返回
|
||||
if (readIndex == 0) {
|
||||
return template;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
builder.append(template, readIndex, placeholderIndex);
|
||||
builder.append(args[i]);
|
||||
readIndex = placeholderIndex + 2;
|
||||
}
|
||||
|
||||
// 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
|
||||
builder.append(template, readIndex, template.length());
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user