ref[Python]: refactor generate python protocol

This commit is contained in:
godotg committed 2024-05-29 14:32:57 +08:00
1 parent bd45c610ca
commit 2682257b4d
20 files changed
+492 -441

No files matched your search

@@ -21,8 +21,6 @@ import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.serializer.gdscript.GenerateGdUtils;
import com.zfoo.protocol.serializer.go.GenerateGoUtils;
import com.zfoo.protocol.serializer.python.GeneratePyUtils;
import com.zfoo.protocol.serializer.typescript.CodeGenerateTypeScript;
import com.zfoo.protocol.util.FileUtils;
import com.zfoo.protocol.util.ReflectionUtils;
import com.zfoo.protocol.util.StringUtils;
@@ -136,15 +134,6 @@ public abstract class GenerateProtocolFile {
}
}
// 生成Python协议
if (generateLanguages.contains(CodeLanguage.Python)) {
GeneratePyUtils.init(generateOperation);
GeneratePyUtils.createProtocolManager(generateProtocols);
for (var protocolRegistration : generateProtocols) {
GeneratePyUtils.createPyProtocolFile((ProtocolRegistration) protocolRegistration);
}
}
for (var language : generateOperation.getGenerateLanguages()) {
if (language.codeGenerateClass == null) {
continue;
@@ -27,7 +27,6 @@ import com.zfoo.protocol.generate.GenerateProtocolPath;
import com.zfoo.protocol.registration.field.*;
import com.zfoo.protocol.serializer.gdscript.GenerateGdUtils;
import com.zfoo.protocol.serializer.go.GenerateGoUtils;
import com.zfoo.protocol.serializer.python.GeneratePyUtils;
import com.zfoo.protocol.serializer.reflect.*;
import com.zfoo.protocol.util.*;
import com.zfoo.protocol.xml.XmlProtocols;
@@ -397,7 +396,6 @@ public class ProtocolAnalysis {
GenerateProtocolPath.clear();
GenerateGoUtils.clear();
GenerateGdUtils.clear();
GeneratePyUtils.clear();
}
public static List<Field> getFields(Class<?> clazz) {
@@ -17,6 +17,7 @@ import com.zfoo.protocol.serializer.csharp.CodeGenerateCsharp;
import com.zfoo.protocol.serializer.ecmascript.CodeGenerateEcmaScript;
import com.zfoo.protocol.serializer.javascript.CodeGenerateJavaScript;
import com.zfoo.protocol.serializer.lua.CodeGenerateLua;
import com.zfoo.protocol.serializer.python.CodeGeneratePython;
import com.zfoo.protocol.serializer.typescript.CodeGenerateTypeScript;
/**
@@ -45,7 +46,7 @@ public enum CodeLanguage {
GdScript(1 << 12, null),
Python(1 << 13, null),
Python(1 << 13, CodeGeneratePython.class),
Protobuf(1 << 30, null);
@@ -0,0 +1,276 @@
/*
* 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.python;
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.ProtocolRegistration;
import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.serializer.CodeTemplatePlaceholder;
import com.zfoo.protocol.serializer.ICodeGenerate;
import com.zfoo.protocol.serializer.csharp.CodeGenerateCsharp;
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 CodeGeneratePython implements ICodeGenerate {
private static final Logger logger = LoggerFactory.getLogger(CodeGeneratePython.class);
// custom configuration
public static String protocolOutputRootPath = "zfoopy";
private static String protocolOutputPath = StringUtils.EMPTY;
private static Map<ISerializer, IPySerializer> pySerializerMap = new HashMap<>();
public static IPySerializer pySerializer(ISerializer serializer) {
return pySerializerMap.get(serializer);
}
@Override
public void init(GenerateOperation generateOperation) {
protocolOutputPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
FileUtils.deleteFile(new File(protocolOutputPath));
pySerializerMap.put(BooleanSerializer.INSTANCE, new PyBooleanSerializer());
pySerializerMap.put(ByteSerializer.INSTANCE, new PyByteSerializer());
pySerializerMap.put(ShortSerializer.INSTANCE, new PyShortSerializer());
pySerializerMap.put(IntSerializer.INSTANCE, new PyIntSerializer());
pySerializerMap.put(LongSerializer.INSTANCE, new PyLongSerializer());
pySerializerMap.put(FloatSerializer.INSTANCE, new PyFloatSerializer());
pySerializerMap.put(DoubleSerializer.INSTANCE, new PyDoubleSerializer());
pySerializerMap.put(StringSerializer.INSTANCE, new PyStringSerializer());
pySerializerMap.put(ArraySerializer.INSTANCE, new PyArraySerializer());
pySerializerMap.put(ListSerializer.INSTANCE, new PyListSerializer());
pySerializerMap.put(SetSerializer.INSTANCE, new PySetSerializer());
pySerializerMap.put(MapSerializer.INSTANCE, new PyMapSerializer());
pySerializerMap.put(ObjectProtocolSerializer.INSTANCE, new PyObjectProtocolSerializer());
}
@Override
public void mergerProtocol(List<ProtocolRegistration> registrations) throws IOException {
createTemplateFile();
var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("python/ProtocolManagerTemplate.py");
var protocol_imports = new StringBuilder();
var protocol_manager_registrations = new StringBuilder();
protocol_imports.append("from . import Protocols").append(LS);
for (var registration : registrations) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
protocol_manager_registrations.append(StringUtils.format("protocols[{}] = Protocols.{}", protocol_id, protocol_name)).append(LS);
}
var placeholderMap = Map.of(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("{}/{}", protocolOutputPath, "ProtocolManager.py"));
FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true);
logger.info("Generated Python protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath());
var protocol_class = new StringBuilder();
for (var registration : registrations) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
protocol_class.append(formatProtocolTemplate(registration)).append(LS);
}
var protocolTemplate = ClassUtils.getFileFromClassPathToString("python/ProtocolsTemplate.py");
var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of(
CodeTemplatePlaceholder.protocol_class, protocol_class.toString()
));
var outputPath = StringUtils.format("{}/Protocols.py", protocolOutputPath);
var file = new File(outputPath);
FileUtils.writeStringToFile(file, formatProtocolTemplate, true);
logger.info("Generated Python protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
}
@Override
public void foldProtocol(List<ProtocolRegistration> registrations) throws IOException {
createTemplateFile();
var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("python/ProtocolManagerTemplate.py");
var protocol_imports = new StringBuilder();
var protocol_manager_registrations = new StringBuilder();
for (var registration : registrations) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
protocol_imports.append(StringUtils.format("from .{} import {}", GenerateProtocolPath.protocolPathPeriod(protocol_id), protocol_name)).append(LS);
protocol_manager_registrations.append(StringUtils.format("protocols[{}] = {}.{}", protocol_id, protocol_name, protocol_name)).append(LS);
}
var placeholderMap = Map.of(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("{}/{}", protocolOutputPath, "ProtocolManager.py"));
FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true);
logger.info("Generated Python 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 formatProtocolTemplate = formatProtocolTemplate(registration);
var outputPath = StringUtils.format("{}/{}/{}.py", protocolOutputPath, GenerateProtocolPath.protocolPathSlash(protocol_id), protocol_name);
var file = new File(outputPath);
FileUtils.writeStringToFile(file, formatProtocolTemplate, true);
logger.info("Generated Python protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
}
}
@Override
public void defaultProtocol(List<ProtocolRegistration> registrations) throws IOException {
createTemplateFile();
var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("python/ProtocolManagerTemplate.py");
var protocol_imports = new StringBuilder();
var protocol_manager_registrations = new StringBuilder();
for (var registration : registrations) {
var protocol_id = registration.protocolId();
var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName();
protocol_imports.append(StringUtils.format("from . import {}", protocol_name)).append(LS);
protocol_manager_registrations.append(StringUtils.format("protocols[{}] = {}.{}", protocol_id, protocol_name, protocol_name)).append(LS);
}
var placeholderMap = Map.of(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("{}/{}", protocolOutputPath, "ProtocolManager.py"));
FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true);
logger.info("Generated Python 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 formatProtocolTemplate = formatProtocolTemplate(registration);
var outputPath = StringUtils.format("{}/{}.py", protocolOutputPath, protocol_name);
var file = new File(outputPath);
FileUtils.writeStringToFile(file, formatProtocolTemplate, true);
logger.info("Generated Python protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
}
}
private void createTemplateFile() throws IOException {
var list = List.of("python/ByteBuffer.py");
for (var fileName : list) {
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
var outputPath = StringUtils.format("{}/{}", protocolOutputPath, StringUtils.substringAfterFirst(fileName, "python/"));
var createFile = new File(outputPath);
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
}
}
public String formatProtocolTemplate(ProtocolRegistration registration) {
var protocol_id = registration.protocolId();
var protocol_name = registration.getConstructor().getDeclaringClass().getSimpleName();
var protocolTemplate = ClassUtils.getFileFromClassPathToString("python/ProtocolTemplate.py");
var placeholderMap = Map.of(
CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Python)
, CodeTemplatePlaceholder.protocol_name, protocol_name
, CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id)
, CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration)
, CodeTemplatePlaceholder.protocol_write_serialization, protocol_write_serialization(registration)
, CodeTemplatePlaceholder.protocol_read_deserialization, protocol_read_deserialization(registration)
);
return CodeTemplatePlaceholder.formatTemplate(protocolTemplate, placeholderMap);
}
private String protocol_field_definition(ProtocolRegistration registration) {
var protocolId = registration.getId();
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var pyBuilder = new StringBuilder();
// when generate source code fields, use origin fields sort
var sequencedFields = ReflectionUtils.notStaticAndTransientFields(registration.getConstructor().getDeclaringClass());
for (var field : sequencedFields) {
var fieldRegistration = fieldRegistrations[GenerateProtocolFile.indexOf(fields, field)];
var fieldName = field.getName();
// 生成注释
var fieldNotes = GenerateProtocolNote.fieldNotes(protocolId, fieldName, CodeLanguage.Python);
for (var fieldNote : fieldNotes) {
pyBuilder.append(fieldNote).append(LS);
}
var fieldDefaultValue = pySerializer(fieldRegistration.serializer()).fieldDefaultValue(field, fieldRegistration);
// 生成类型的注释
pyBuilder.append(StringUtils.format("{} = {}", fieldName, fieldDefaultValue));
pyBuilder.append(StringUtils.format(" # {}", CodeGenerateCsharp.toCsClassName(field.getGenericType().getTypeName())));
pyBuilder.append(LS);
}
return pyBuilder.toString();
}
private String protocol_write_serialization(ProtocolRegistration registration) {
GenerateProtocolFile.localVariableId = 0;
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var pyBuilder = new StringBuilder();
if (registration.isCompatible()) {
pyBuilder.append("beforeWriteIndex = buffer.getWriteOffset()").append(LS);
pyBuilder.append(StringUtils.format("buffer.writeInt({})", registration.getPredictionLength())).append(LS);
} else {
pyBuilder.append("buffer.writeInt(-1)").append(LS);
}
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
pySerializer(fieldRegistration.serializer()).writeObject(pyBuilder, "packet." + field.getName(), 0, field, fieldRegistration);
}
if (registration.isCompatible()) {
pyBuilder.append(StringUtils.format("buffer.adjustPadding({}, beforeWriteIndex)", registration.getPredictionLength())).append(LS);
}
return pyBuilder.toString();
}
private String protocol_read_deserialization(ProtocolRegistration registration) {
GenerateProtocolFile.localVariableId = 0;
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var pyBuilder = new StringBuilder();
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
if (field.isAnnotationPresent(Compatible.class)) {
pyBuilder.append("if buffer.compatibleRead(beforeReadIndex, length):").append(LS);
var compatibleReadObject = pySerializer(fieldRegistration.serializer()).readObject(pyBuilder, 1, field, fieldRegistration);
pyBuilder.append(TAB).append(StringUtils.format("packet.{} = {}", field.getName(), compatibleReadObject)).append(LS);
continue;
}
var readObject = pySerializer(fieldRegistration.serializer()).readObject(pyBuilder, 0, field, fieldRegistration);
pyBuilder.append(StringUtils.format("packet.{} = {}", field.getName(), readObject)).append(LS);
}
return pyBuilder.toString();
}
}
@@ -1,198 +0,0 @@
/*
* 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.python;
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.ProtocolRegistration;
import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.serializer.csharp.CodeGenerateCsharp;
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 abstract class GeneratePyUtils {
private static final Logger logger = LoggerFactory.getLogger(GeneratePyUtils.class);
// custom configuration
public static String protocolOutputRootPath = "zfoopy";
private static String protocolOutputPath = StringUtils.EMPTY;
private static Map<ISerializer, IPySerializer> pySerializerMap;
public static IPySerializer pySerializer(ISerializer serializer) {
return pySerializerMap.get(serializer);
}
public static void init(GenerateOperation generateOperation) {
protocolOutputPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
FileUtils.deleteFile(new File(protocolOutputPath));
pySerializerMap = new HashMap<>();
pySerializerMap.put(BooleanSerializer.INSTANCE, new PyBooleanSerializer());
pySerializerMap.put(ByteSerializer.INSTANCE, new PyByteSerializer());
pySerializerMap.put(ShortSerializer.INSTANCE, new PyShortSerializer());
pySerializerMap.put(IntSerializer.INSTANCE, new PyIntSerializer());
pySerializerMap.put(LongSerializer.INSTANCE, new PyLongSerializer());
pySerializerMap.put(FloatSerializer.INSTANCE, new PyFloatSerializer());
pySerializerMap.put(DoubleSerializer.INSTANCE, new PyDoubleSerializer());
pySerializerMap.put(StringSerializer.INSTANCE, new PyStringSerializer());
pySerializerMap.put(ArraySerializer.INSTANCE, new PyArraySerializer());
pySerializerMap.put(ListSerializer.INSTANCE, new PyListSerializer());
pySerializerMap.put(SetSerializer.INSTANCE, new PySetSerializer());
pySerializerMap.put(MapSerializer.INSTANCE, new PyMapSerializer());
pySerializerMap.put(ObjectProtocolSerializer.INSTANCE, new PyObjectProtocolSerializer());
}
public static void clear() {
protocolOutputPath = null;
protocolOutputRootPath = null;
pySerializerMap = null;
}
public static void createProtocolManager(List<ProtocolRegistration> protocolList) throws IOException {
var list = List.of("python/ByteBuffer.py");
for (var fileName : list) {
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
var outputPath = StringUtils.format("{}/{}", protocolOutputPath, StringUtils.substringAfterFirst(fileName, "python/"));
var createFile = new File(outputPath);
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
}
var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("python/ProtocolManagerTemplate.py");
var importBuilder = new StringBuilder();
var initProtocolBuilder = new StringBuilder();
for (var protocol : protocolList) {
var protocolId = protocol.protocolId();
var protocolName = protocol.protocolConstructor().getDeclaringClass().getSimpleName();
var path = GenerateProtocolPath.protocolAbsolutePath(protocolId, CodeLanguage.Python);
importBuilder.append(StringUtils.format("from {} import {}", path, protocolName)).append(LS);
initProtocolBuilder.append(StringUtils.format("protocols[{}] = {}.{}", protocolId, protocolName, protocolName)).append(LS);
}
protocolManagerTemplate = StringUtils.format(protocolManagerTemplate, importBuilder.toString().trim(), StringUtils.EMPTY_JSON, initProtocolBuilder.toString().trim());
var outputPath = StringUtils.format("{}/{}", protocolOutputPath, "ProtocolManager.py");
var file = new File(outputPath);
FileUtils.writeStringToFile(file, protocolManagerTemplate, true);
logger.info("Generated Python protocol manager file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
}
public static void createPyProtocolFile(ProtocolRegistration registration) {
var protocolId = registration.protocolId();
var registrationConstructor = registration.getConstructor();
var protocolClazzName = registrationConstructor.getDeclaringClass().getSimpleName();
var protocolTemplate = ClassUtils.getFileFromClassPathToString("python/ProtocolTemplate.py");
var classNote = GenerateProtocolNote.classNote(protocolId, CodeLanguage.Python, TAB, 0);
var fieldDefinition = fieldDefinition(registration);
var writeObject = writeObject(registration);
var readObject = readObject(registration);
protocolTemplate = StringUtils.format(protocolTemplate, classNote, protocolClazzName
, fieldDefinition.trim(), protocolId, writeObject.trim(), protocolClazzName, readObject.trim());
var outputPath = StringUtils.format("{}/{}/{}.py", protocolOutputPath, GenerateProtocolPath.protocolPathSlash(protocolId), protocolClazzName);
var file = new File(outputPath);
FileUtils.writeStringToFile(file, protocolTemplate, true);
logger.info("Generated Python protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath());
}
private static String fieldDefinition(ProtocolRegistration registration) {
var protocolId = registration.getId();
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var pyBuilder = new StringBuilder();
// when generate source code fields, use origin fields sort
var sequencedFields = ReflectionUtils.notStaticAndTransientFields(registration.getConstructor().getDeclaringClass());
for (var field : sequencedFields) {
var fieldRegistration = fieldRegistrations[GenerateProtocolFile.indexOf(fields, field)];
var fieldName = field.getName();
// 生成注释
var fieldNotes = GenerateProtocolNote.fieldNotes(protocolId, fieldName, CodeLanguage.Python);
for(var fieldNote : fieldNotes) {
pyBuilder.append(TAB).append(fieldNote).append(LS);
}
var fieldDefaultValue = pySerializer(fieldRegistration.serializer()).fieldDefaultValue(field, fieldRegistration);
// 生成类型的注释
pyBuilder.append(StringUtils.format("{}{} = {}", TAB, fieldName, fieldDefaultValue));
pyBuilder.append(StringUtils.format(" # {}", CodeGenerateCsharp.toCsClassName(field.getGenericType().getTypeName())));
pyBuilder.append(LS);
}
return pyBuilder.toString();
}
private static String writeObject(ProtocolRegistration registration) {
GenerateProtocolFile.localVariableId = 0;
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var pyBuilder = new StringBuilder();
if (registration.isCompatible()) {
pyBuilder.append("beforeWriteIndex = buffer.getWriteOffset()").append(LS);
pyBuilder.append(TAB + TAB).append(StringUtils.format("buffer.writeInt({})", registration.getPredictionLength())).append(LS);
} else {
pyBuilder.append(TAB + TAB).append("buffer.writeInt(-1)").append(LS);
}
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
pySerializer(fieldRegistration.serializer()).writeObject(pyBuilder, "packet." + field.getName(), 2, field, fieldRegistration);
}
if (registration.isCompatible()) {
pyBuilder.append(TAB + TAB).append(StringUtils.format("buffer.adjustPadding({}, beforeWriteIndex)", registration.getPredictionLength())).append(LS);
}
return pyBuilder.toString();
}
private static String readObject(ProtocolRegistration registration) {
GenerateProtocolFile.localVariableId = 0;
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var pyBuilder = new StringBuilder();
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
if (field.isAnnotationPresent(Compatible.class)) {
pyBuilder.append(TAB + TAB).append("if buffer.compatibleRead(beforeReadIndex, length):").append(LS);
var compatibleReadObject = pySerializer(fieldRegistration.serializer()).readObject(pyBuilder, 3, field, fieldRegistration);
pyBuilder.append(TAB + TAB+ TAB).append(StringUtils.format("packet.{} = {}", field.getName(), compatibleReadObject)).append(LS);
continue;
}
var readObject = pySerializer(fieldRegistration.serializer()).readObject(pyBuilder, 2, field, fieldRegistration);
pyBuilder.append(TAB + TAB).append(StringUtils.format("packet.{} = {}", field.getName(), readObject)).append(LS);
}
return pyBuilder.toString();
}
}
@@ -54,7 +54,7 @@ public class PyArraySerializer implements IPySerializer {
String element = "element" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for {} in {}:", element, objectStr)).append(LS);
GeneratePyUtils.pySerializer(arrayField.getArrayElementRegistration().serializer())
CodeGeneratePython.pySerializer(arrayField.getArrayElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, arrayField.getArrayElementRegistration());
}
@@ -81,7 +81,7 @@ public class PyArraySerializer implements IPySerializer {
builder.append(StringUtils.format("if {} > 0:", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for {} in range({}):", i, size)).append(LS);
String readObject = GeneratePyUtils.pySerializer(arrayField.getArrayElementRegistration().serializer())
String readObject = CodeGeneratePython.pySerializer(arrayField.getArrayElementRegistration().serializer())
.readObject(builder, deep + 2, field, arrayField.getArrayElementRegistration());
GenerateProtocolFile.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.append({})", result, readObject)).append(LS);
@@ -54,7 +54,7 @@ public class PyListSerializer implements IPySerializer {
String element = "element" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for {} in {}:", element, objectStr)).append(LS);
GeneratePyUtils.pySerializer(listField.getListElementRegistration().serializer())
CodeGeneratePython.pySerializer(listField.getListElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, listField.getListElementRegistration());
}
@@ -81,7 +81,7 @@ public class PyListSerializer implements IPySerializer {
builder.append(StringUtils.format("if {} > 0:", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for {} in range({}):", i, size)).append(LS);
String readObject = GeneratePyUtils.pySerializer(listField.getListElementRegistration().serializer())
String readObject = CodeGeneratePython.pySerializer(listField.getListElementRegistration().serializer())
.readObject(builder, deep + 2, field, listField.getListElementRegistration());
GenerateProtocolFile.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.append({})", result, readObject)).append(LS);
@@ -58,9 +58,9 @@ public class PyMapSerializer implements IPySerializer {
builder.append(StringUtils.format("for {} in {}:", key, objectStr)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 2);
builder.append(StringUtils.format("{} = {}[{}]", value, objectStr, key)).append(LS);
GeneratePyUtils.pySerializer(mapField.getMapKeyRegistration().serializer())
CodeGeneratePython.pySerializer(mapField.getMapKeyRegistration().serializer())
.writeObject(builder, key, deep + 2, field, mapField.getMapKeyRegistration());
GeneratePyUtils.pySerializer(mapField.getMapValueRegistration().serializer())
CodeGeneratePython.pySerializer(mapField.getMapValueRegistration().serializer())
.writeObject(builder, value, deep + 2, field, mapField.getMapValueRegistration());
}
@@ -88,11 +88,11 @@ public class PyMapSerializer implements IPySerializer {
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for {} in range({}):", i, size)).append(LS);
String keyObject = GeneratePyUtils.pySerializer(mapField.getMapKeyRegistration().serializer())
String keyObject = CodeGeneratePython.pySerializer(mapField.getMapKeyRegistration().serializer())
.readObject(builder, deep + 2, field, mapField.getMapKeyRegistration());
String valueObject = GeneratePyUtils.pySerializer(mapField.getMapValueRegistration().serializer())
String valueObject = CodeGeneratePython.pySerializer(mapField.getMapValueRegistration().serializer())
.readObject(builder, deep + 2, field, mapField.getMapValueRegistration());
GenerateProtocolFile.addTab(builder, deep + 2);
@@ -54,7 +54,7 @@ public class PySetSerializer implements IPySerializer {
String element = "element" + GenerateProtocolFile.localVariableId++;
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for {} in {}:", element, objectStr)).append(LS);
GeneratePyUtils.pySerializer(setField.getSetElementRegistration().serializer())
CodeGeneratePython.pySerializer(setField.getSetElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, setField.getSetElementRegistration());
}
@@ -81,7 +81,7 @@ public class PySetSerializer implements IPySerializer {
builder.append(StringUtils.format("if {} > 0:", size)).append(LS);
GenerateProtocolFile.addTab(builder, deep + 1);
builder.append(StringUtils.format("for {} in range({}):", i, size)).append(LS);
String readObject = GeneratePyUtils.pySerializer(setField.getSetElementRegistration().serializer())
String readObject = CodeGeneratePython.pySerializer(setField.getSetElementRegistration().serializer())
.readObject(builder, deep + 2, field, setField.getSetElementRegistration());
GenerateProtocolFile.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.append({})", result, readObject)).append(LS);
@@ -1,8 +1,8 @@
{}
${protocol_imports}
protocols = {}
{}
${protocol_manager_registrations}
def getProtocol(protocolId):
return protocols[protocolId]
@@ -1,17 +1,16 @@
{}
class {}:
{}
${protocol_note}
class ${protocol_name}:
${protocol_field_definition}
def protocolId(self):
return {}
return ${protocol_id}
@classmethod
def write(cls, buffer, packet):
if packet is None:
buffer.writeInt(0)
return
{}
${protocol_write_serialization}
pass
@classmethod
@@ -20,9 +19,8 @@ class {}:
if length == 0:
return None
beforeReadIndex = buffer.getReadOffset()
packet = {}()
{}
packet = ${protocol_name}()
${protocol_read_deserialization}
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
return packet
@@ -0,0 +1 @@
${protocol_class}
@@ -1,10 +1,10 @@
from . import EmptyObject
from . import VeryBigObject
from . import ComplexObject
from . import NormalObject
from . import ObjectA
from . import ObjectB
from . import SimpleObject
from .packet import EmptyObject
from .packet import VeryBigObject
from .packet import ComplexObject
from .packet import NormalObject
from .packet import ObjectA
from .packet import ObjectB
from .packet import SimpleObject
protocols = {}
@@ -29,4 +29,4 @@ def read(buffer):
protocolId = buffer.readShort()
protocol = protocols[protocolId]
packet = protocol.read(buffer)
return packet
return packet
@@ -1,6 +1,5 @@
# 复杂的对象,包括了各种复杂的结构,数组,List,Set,Map
class ComplexObject:
# byte类型,最简单的整形
a = 0 # byte
# byte的包装类型,优先使用基础类型,包装类型会有装箱拆箱
@@ -51,7 +50,7 @@ class ComplexObject:
sss = {} # HashSet<HashSet<ObjectA>>
ssss = {} # HashSet<string>
sssss = {} # HashSet<Dictionary<int, string>>
# 如果要修改协议并且兼容老协议,需要加上Compatible注解,按照增加的顺序添加order
# 如果要修改协议并且兼容老协议,需要加上Compatible注解,保持Compatible注解的value自增
myCompatible = 0 # int
myObject = None # ObjectA
@@ -210,190 +209,189 @@ class ComplexObject:
return None
beforeReadIndex = buffer.getReadOffset()
packet = ComplexObject()
result19 = buffer.readByte()
packet.a = result19
result20 = buffer.readByte()
packet.aa = result20
array21 = buffer.readByteArray()
packet.aaa = array21
array22 = buffer.readByteArray()
packet.aaaa = array22
result23 = buffer.readShort()
packet.b = result23
result24 = buffer.readShort()
packet.bb = result24
array25 = buffer.readShortArray()
packet.bbb = array25
array26 = buffer.readShortArray()
packet.bbbb = array26
result27 = buffer.readInt()
packet.c = result27
result28 = buffer.readInt()
packet.cc = result28
array29 = buffer.readIntArray()
packet.ccc = array29
array30 = buffer.readIntArray()
packet.cccc = array30
result31 = buffer.readLong()
packet.d = result31
result32 = buffer.readLong()
packet.dd = result32
array33 = buffer.readLongArray()
packet.ddd = array33
array34 = buffer.readLongArray()
packet.dddd = array34
result35 = buffer.readFloat()
packet.e = result35
result36 = buffer.readFloat()
packet.ee = result36
array37 = buffer.readFloatArray()
packet.eee = array37
array38 = buffer.readFloatArray()
packet.eeee = array38
result39 = buffer.readDouble()
packet.f = result39
result40 = buffer.readDouble()
packet.ff = result40
array41 = buffer.readDoubleArray()
packet.fff = array41
array42 = buffer.readDoubleArray()
packet.ffff = array42
result43 = buffer.readBool()
packet.g = result43
result44 = buffer.readBool()
packet.gg = result44
array45 = buffer.readBooleanArray()
packet.ggg = array45
array46 = buffer.readBooleanArray()
packet.gggg = array46
result47 = buffer.readString()
packet.jj = result47
array48 = buffer.readStringArray()
packet.jjj = array48
result49 = buffer.readPacket(102)
packet.kk = result49
array50 = buffer.readPacketArray(102)
packet.kkk = array50
list51 = buffer.readIntArray()
packet.l = list51
result52 = []
size54 = buffer.readInt()
if size54 > 0:
for index53 in range(size54):
result55 = []
size57 = buffer.readInt()
if size57 > 0:
for index56 in range(size57):
list58 = buffer.readIntArray()
result55.append(list58)
result52.append(result55)
packet.ll = result52
result59 = []
size61 = buffer.readInt()
if size61 > 0:
for index60 in range(size61):
list62 = buffer.readPacketArray(102)
result59.append(list62)
packet.lll = result59
list63 = buffer.readStringArray()
packet.llll = list63
result64 = []
size66 = buffer.readInt()
if size66 > 0:
for index65 in range(size66):
map67 = buffer.readIntStringMap()
result64.append(map67)
packet.lllll = result64
map68 = buffer.readIntStringMap()
packet.m = map68
map69 = buffer.readIntPacketMap(102)
packet.mm = map69
result0 = buffer.readByte()
packet.a = result0
result1 = buffer.readByte()
packet.aa = result1
array2 = buffer.readByteArray()
packet.aaa = array2
array3 = buffer.readByteArray()
packet.aaaa = array3
result4 = buffer.readShort()
packet.b = result4
result5 = buffer.readShort()
packet.bb = result5
array6 = buffer.readShortArray()
packet.bbb = array6
array7 = buffer.readShortArray()
packet.bbbb = array7
result8 = buffer.readInt()
packet.c = result8
result9 = buffer.readInt()
packet.cc = result9
array10 = buffer.readIntArray()
packet.ccc = array10
array11 = buffer.readIntArray()
packet.cccc = array11
result12 = buffer.readLong()
packet.d = result12
result13 = buffer.readLong()
packet.dd = result13
array14 = buffer.readLongArray()
packet.ddd = array14
array15 = buffer.readLongArray()
packet.dddd = array15
result16 = buffer.readFloat()
packet.e = result16
result17 = buffer.readFloat()
packet.ee = result17
array18 = buffer.readFloatArray()
packet.eee = array18
array19 = buffer.readFloatArray()
packet.eeee = array19
result20 = buffer.readDouble()
packet.f = result20
result21 = buffer.readDouble()
packet.ff = result21
array22 = buffer.readDoubleArray()
packet.fff = array22
array23 = buffer.readDoubleArray()
packet.ffff = array23
result24 = buffer.readBool()
packet.g = result24
result25 = buffer.readBool()
packet.gg = result25
array26 = buffer.readBooleanArray()
packet.ggg = array26
array27 = buffer.readBooleanArray()
packet.gggg = array27
result28 = buffer.readString()
packet.jj = result28
array29 = buffer.readStringArray()
packet.jjj = array29
result30 = buffer.readPacket(102)
packet.kk = result30
array31 = buffer.readPacketArray(102)
packet.kkk = array31
list32 = buffer.readIntArray()
packet.l = list32
result33 = []
size35 = buffer.readInt()
if size35 > 0:
for index34 in range(size35):
result36 = []
size38 = buffer.readInt()
if size38 > 0:
for index37 in range(size38):
list39 = buffer.readIntArray()
result36.append(list39)
result33.append(result36)
packet.ll = result33
result40 = []
size42 = buffer.readInt()
if size42 > 0:
for index41 in range(size42):
list43 = buffer.readPacketArray(102)
result40.append(list43)
packet.lll = result40
list44 = buffer.readStringArray()
packet.llll = list44
result45 = []
size47 = buffer.readInt()
if size47 > 0:
for index46 in range(size47):
map48 = buffer.readIntStringMap()
result45.append(map48)
packet.lllll = result45
map49 = buffer.readIntStringMap()
packet.m = map49
map50 = buffer.readIntPacketMap(102)
packet.mm = map50
result51 = {}
size52 = buffer.readInt()
if size52 > 0:
for index53 in range(size52):
result54 = buffer.readPacket(102)
list55 = buffer.readIntArray()
result51[result54] = list55
packet.mmm = result51
result56 = {}
size57 = buffer.readInt()
if size57 > 0:
for index58 in range(size57):
result59 = []
size61 = buffer.readInt()
if size61 > 0:
for index60 in range(size61):
list62 = buffer.readPacketArray(102)
result59.append(list62)
result63 = []
size65 = buffer.readInt()
if size65 > 0:
for index64 in range(size65):
result66 = []
size68 = buffer.readInt()
if size68 > 0:
for index67 in range(size68):
list69 = buffer.readIntArray()
result66.append(list69)
result63.append(result66)
result56[result59] = result63
packet.mmmm = result56
result70 = {}
size71 = buffer.readInt()
if size71 > 0:
for index72 in range(size71):
result73 = buffer.readPacket(102)
list74 = buffer.readIntArray()
result70[result73] = list74
packet.mmm = result70
result75 = {}
size76 = buffer.readInt()
if size76 > 0:
for index77 in range(size76):
result78 = []
size80 = buffer.readInt()
if size80 > 0:
for index79 in range(size80):
list81 = buffer.readPacketArray(102)
result78.append(list81)
result82 = []
size84 = buffer.readInt()
if size84 > 0:
for index83 in range(size84):
result85 = []
size87 = buffer.readInt()
if size87 > 0:
for index86 in range(size87):
list88 = buffer.readIntArray()
result85.append(list88)
result82.append(result85)
result75[result78] = result82
packet.mmmm = result75
result89 = {}
size90 = buffer.readInt()
if size90 > 0:
for index91 in range(size90):
result92 = []
size94 = buffer.readInt()
if size94 > 0:
for index93 in range(size94):
map95 = buffer.readIntStringMap()
result92.append(map95)
result96 = []
size98 = buffer.readInt()
if size98 > 0:
for index97 in range(size98):
map99 = buffer.readIntStringMap()
result96.append(map99)
result89[result92] = result96
packet.mmmmm = result89
set100 = buffer.readIntSet()
packet.s = set100
result101 = []
size103 = buffer.readInt()
if size103 > 0:
for index102 in range(size103):
result104 = []
size106 = buffer.readInt()
if size106 > 0:
for index105 in range(size106):
list107 = buffer.readIntArray()
result104.append(list107)
result101.append(result104)
packet.ss = result101
result108 = []
size110 = buffer.readInt()
if size110 > 0:
for index109 in range(size110):
set111 = buffer.readPacketSet(102)
result108.append(set111)
packet.sss = result108
set112 = buffer.readStringSet()
packet.ssss = set112
result113 = []
size115 = buffer.readInt()
if size115 > 0:
for index114 in range(size115):
map116 = buffer.readIntStringMap()
result113.append(map116)
packet.sssss = result113
result73 = []
size75 = buffer.readInt()
if size75 > 0:
for index74 in range(size75):
map76 = buffer.readIntStringMap()
result73.append(map76)
result77 = []
size79 = buffer.readInt()
if size79 > 0:
for index78 in range(size79):
map80 = buffer.readIntStringMap()
result77.append(map80)
result70[result73] = result77
packet.mmmmm = result70
set81 = buffer.readIntSet()
packet.s = set81
result82 = []
size84 = buffer.readInt()
if size84 > 0:
for index83 in range(size84):
result85 = []
size87 = buffer.readInt()
if size87 > 0:
for index86 in range(size87):
list88 = buffer.readIntArray()
result85.append(list88)
result82.append(result85)
packet.ss = result82
result89 = []
size91 = buffer.readInt()
if size91 > 0:
for index90 in range(size91):
set92 = buffer.readPacketSet(102)
result89.append(set92)
packet.sss = result89
set93 = buffer.readStringSet()
packet.ssss = set93
result94 = []
size96 = buffer.readInt()
if size96 > 0:
for index95 in range(size96):
map97 = buffer.readIntStringMap()
result94.append(map97)
packet.sssss = result94
if buffer.compatibleRead(beforeReadIndex, length):
result117 = buffer.readInt()
packet.myCompatible = result117
result98 = buffer.readInt()
packet.myCompatible = result98
if buffer.compatibleRead(beforeReadIndex, length):
result118 = buffer.readPacket(102)
packet.myObject = result118
result99 = buffer.readPacket(102)
packet.myObject = result99
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
return packet
@@ -1,6 +1,5 @@
class EmptyObject:
def protocolId(self):
@@ -24,5 +23,4 @@ class EmptyObject:
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
return packet
@@ -1,6 +1,5 @@
class NormalObject:
a = 0 # byte
aaa = [] # byte[]
b = 0 # short
@@ -106,5 +105,4 @@ class NormalObject:
packet.outCompatibleValue2 = result19
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
return packet
@@ -1,6 +1,5 @@
class ObjectA:
a = 0 # int
m = {} # Dictionary<int, string>
objectB = None # ObjectB
@@ -41,5 +40,4 @@ class ObjectA:
packet.innerCompatibleValue = result3
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
return packet
@@ -1,6 +1,5 @@
class ObjectB:
flag = False # bool
innerCompatibleValue = 0 # int
@@ -33,5 +32,4 @@ class ObjectB:
packet.innerCompatibleValue = result1
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
return packet
@@ -1,6 +1,5 @@
class SimpleObject:
c = 0 # int
g = False # bool
@@ -30,5 +29,4 @@ class SimpleObject:
packet.g = result1
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
return packet
@@ -1,6 +1,5 @@
class VeryBigObject:
a1 = 0 # byte
aa1 = 0 # byte
aaa1 = [] # byte[]
@@ -13398,5 +13397,4 @@ class VeryBigObject:
packet.ssss9 = set3343
if length > 0:
buffer.setReadOffset(beforeReadIndex + length)
return packet
return packet