diff --git a/.gitignore b/.gitignore
index fb832270..a391a886 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,7 @@ test.md
# 忽略生成的协议文件
**/jsProtocol/
**/gdProtocol/
+**/pyProtocol/
**/CsProtocol/
**/LuaProtocol/
**/cppProtocol/
diff --git a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolFile.java b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolFile.java
index 5e8937fa..7d8a83ba 100644
--- a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolFile.java
+++ b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolFile.java
@@ -25,6 +25,7 @@ import com.zfoo.protocol.serializer.go.GenerateGoUtils;
import com.zfoo.protocol.serializer.javascript.GenerateJsUtils;
import com.zfoo.protocol.serializer.lua.GenerateLuaUtils;
import com.zfoo.protocol.serializer.protobuf.GenerateProtobufUtils;
+import com.zfoo.protocol.serializer.python.GeneratePyUtils;
import com.zfoo.protocol.serializer.typescript.GenerateTsUtils;
import java.io.IOException;
@@ -62,11 +63,8 @@ public abstract class GenerateProtocolFile {
}
/**
- * 生成各种语言的协议文件
- *
- * @param generateOperation
- * @throws IOException
- * @throws ClassNotFoundException
+ * EN: Generate protocol files to various languages
+ * CN: 生成各种语言的协议文件
*/
public static void generate(GenerateOperation generateOperation) throws IOException, ClassNotFoundException {
var protocols = ProtocolManager.protocols;
@@ -172,6 +170,15 @@ public abstract class GenerateProtocolFile {
}
}
+ // 生成Python协议
+ if (generateLanguages.contains(CodeLanguage.Python)) {
+ GeneratePyUtils.init(generateOperation);
+ GeneratePyUtils.createProtocolManager(allSortedGenerateProtocols);
+ for (var protocolRegistration : allSortedGenerateProtocols) {
+ GeneratePyUtils.createPyProtocolFile((ProtocolRegistration) protocolRegistration);
+ }
+ }
+
// 生成Protobuf协议
if (generateLanguages.contains(CodeLanguage.Protobuf)) {
GenerateProtobufUtils.init(generateOperation);
diff --git a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java
index eca46d74..1aef10dc 100644
--- a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java
+++ b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java
@@ -28,7 +28,8 @@ import java.util.List;
import java.util.Map;
/**
- * 生成协议的时候,协议的文档注释和字段注释会使用这个类
+ * EN: When generating the protocol, the document comments and field comments of the protocol will use this class
+ * CN: 生成协议的时候,协议的文档注释和字段注释会使用这个类
*
* @author godotg
* @version 3.0
@@ -38,14 +39,14 @@ public abstract class GenerateProtocolNote {
// 临时变量,启动完成就会销毁,协议的文档,外层map的key为协议类;pair的key为总的注释,value为属性字段的注释,value表示的map的key为属性名称
// 比如在Test中的ComplexObject生成的pari是如下格式
/**
- * key docTitle:
+ * key is docTitle note:
* // 复杂的对象
* // 包括了各种复杂的结构,数组,List,Set,Map
* //
* // @author godotg
* // @version 1.0
*
- * value aa:
+ * value is field note:
* // byte的包装类型
* // 优先使用基础类型,包装类型会有装箱拆箱
*/
@@ -92,18 +93,19 @@ public abstract class GenerateProtocolNote {
case Lua:
fieldNote = StringUtils.format("-- {}", fieldNote).replace("\n", "\n-- ");
break;
+ case Python:
case GdScript:
fieldNote = StringUtils.format("# {}", fieldNote).replace("\n", "\n# ");
break;
case Enhance:
default:
- throw new RunException("无法识别的枚举类型[{}]", language);
+ throw new RunException("unrecognized enum type [{}]", language);
}
return fieldNote;
}
public static void initProtocolNote(List protocolRegistrations) {
- AssertionUtils.notNull(protocolNoteMap, "[{}]已经初始完成,初始化完成过后不能调用initProtocolDocument", GenerateProtocolNote.class.getSimpleName());
+ AssertionUtils.notNull(protocolNoteMap, "[{}] duplicate initialization", GenerateProtocolNote.class.getSimpleName());
for (var protocolRegistration : protocolRegistrations) {
var protocolClazz = protocolRegistration.protocolConstructor().getDeclaringClass();
diff --git a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java
index 592e039d..f334a1dc 100644
--- a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java
+++ b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java
@@ -33,6 +33,7 @@ import com.zfoo.protocol.serializer.go.GenerateGoUtils;
import com.zfoo.protocol.serializer.javascript.GenerateJsUtils;
import com.zfoo.protocol.serializer.lua.GenerateLuaUtils;
import com.zfoo.protocol.serializer.protobuf.GenerateProtobufUtils;
+import com.zfoo.protocol.serializer.python.GeneratePyUtils;
import com.zfoo.protocol.serializer.reflect.*;
import com.zfoo.protocol.serializer.typescript.GenerateTsUtils;
import com.zfoo.protocol.util.AssertionUtils;
@@ -352,6 +353,7 @@ public class ProtocolAnalysis {
GenerateTsUtils.clear();
GenerateLuaUtils.clear();
GenerateGdUtils.clear();
+ GeneratePyUtils.clear();
GenerateProtobufUtils.clear();
}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/GeneratePyUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/GeneratePyUtils.java
new file mode 100644
index 00000000..c515bac4
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/GeneratePyUtils.java
@@ -0,0 +1,187 @@
+/*
+ * 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.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.IProtocolRegistration;
+import com.zfoo.protocol.registration.ProtocolRegistration;
+import com.zfoo.protocol.registration.anno.Compatible;
+import com.zfoo.protocol.registration.field.IFieldRegistration;
+import com.zfoo.protocol.serializer.CodeLanguage;
+import com.zfoo.protocol.serializer.csharp.GenerateCsUtils;
+import com.zfoo.protocol.serializer.reflect.*;
+import com.zfoo.protocol.util.*;
+
+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;
+import static com.zfoo.protocol.util.StringUtils.TAB_ASCII;
+
+/**
+ * @author godotg
+ * @version 3.0
+ */
+public abstract class GeneratePyUtils {
+
+ private static String protocolOutputRootPath = "pyProtocol/";
+
+ private static Map pySerializerMap;
+
+
+ public static IPySerializer pySerializer(ISerializer serializer) {
+ return pySerializerMap.get(serializer);
+ }
+
+ public static void init(GenerateOperation generateOperation) {
+ protocolOutputRootPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
+
+ FileUtils.deleteFile(new File(protocolOutputRootPath));
+ FileUtils.createDirectory(protocolOutputRootPath);
+
+ 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(CharSerializer.INSTANCE, new PyCharSerializer());
+ 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() {
+ pySerializerMap = null;
+ protocolOutputRootPath = null;
+ }
+
+ public static void createProtocolManager(List protocolList) throws IOException {
+ var list = List.of("python/byte_buffer.py");
+ for (var fileName : list) {
+ var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
+ var createFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, StringUtils.substringAfterFirst(fileName, "python/")));
+ FileUtils.writeInputStreamToFile(createFile, fileInputStream);
+ }
+
+ // 生成ProtocolManager.js文件
+ var protocolManagerTemplate = StringUtils.bytesToString(IOUtils.toByteArray(ClassUtils.getFileFromClassPath("javascript/ProtocolManagerTemplate.js")));
+
+ 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(protocol.protocolId(), CodeLanguage.JavaScript);
+ importBuilder.append(StringUtils.format("import {} from './{}.js';", protocolName, path)).append(LS);
+ initProtocolBuilder.append(StringUtils.format("protocols.set({}, {});", protocolId, protocolName)).append(LS);
+ }
+
+ protocolManagerTemplate = StringUtils.format(protocolManagerTemplate, importBuilder.toString().trim(), StringUtils.EMPTY_JSON, initProtocolBuilder.toString().trim());
+ FileUtils.writeStringToFile(new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.js")), protocolManagerTemplate, true);
+ }
+
+ public static void createPyProtocolFile(ProtocolRegistration registration) {
+ GenerateProtocolFile.index.set(0);
+
+ 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);
+ var fieldDefinition = fieldDefinition(registration);
+ var writeObject = writeObject(registration);
+ var readObject = readObject(registration);
+
+ protocolTemplate = StringUtils.format(protocolTemplate, classNote, protocolClazzName
+ , fieldDefinition.trim(), protocolId, writeObject.trim(), readObject.trim(), protocolClazzName);
+ var protocolOutputPath = StringUtils.format("{}/{}/{}.py", protocolOutputRootPath
+ , GenerateProtocolPath.getProtocolPath(protocolId), protocolClazzName);
+ FileUtils.writeStringToFile(new File(protocolOutputPath), protocolTemplate, true);
+ }
+
+ private static String fieldDefinition(ProtocolRegistration registration) {
+ var protocolId = registration.getId();
+ var fields = registration.getFields();
+ var fieldRegistrations = registration.getFieldRegistrations();
+ var pyBuilder = 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 fieldNote = GenerateProtocolNote.fieldNote(protocolId, fieldName, CodeLanguage.Python);
+ if (StringUtils.isNotBlank(fieldNote)) {
+ 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(" # {}", GenerateCsUtils.toCsClassName(field.getGenericType().getTypeName())));
+ pyBuilder.append(LS);
+ }
+ return pyBuilder.toString();
+ }
+
+ private static String writeObject(ProtocolRegistration registration) {
+ 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];
+ pySerializer(fieldRegistration.serializer()).writeObject(pyBuilder, "packet." + field.getName(), 2, field, fieldRegistration);
+ }
+ return pyBuilder.toString();
+ }
+
+ private static String readObject(ProtocolRegistration registration) {
+ 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.isReadable():").append(LS);
+ pyBuilder.append(TAB + TAB+ TAB).append("return packet").append(LS);
+ pyBuilder.append(TAB+ TAB).append("pass").append(LS);
+ }
+ 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();
+ }
+
+ public static StringBuilder addTab(StringBuilder builder, int deep) {
+ builder.append(TAB_ASCII.repeat(Math.max(0, deep)));
+ return builder;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/IPySerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/IPySerializer.java
new file mode 100644
index 00000000..8db2caf1
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/IPySerializer.java
@@ -0,0 +1,32 @@
+/*
+ * 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.registration.field.IFieldRegistration;
+
+import java.lang.reflect.Field;
+
+/**
+ * @author godotg
+ * @version 3.0
+ */
+public interface IPySerializer {
+
+ String fieldDefaultValue(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);
+
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyArraySerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyArraySerializer.java
new file mode 100644
index 00000000..7b27ba6a
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyArraySerializer.java
@@ -0,0 +1,92 @@
+/*
+ * 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.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyArraySerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "[]";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.addTab(builder, deep);
+ if (CutDownArraySerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.GdScript)) {
+ return;
+ }
+
+ ArrayField arrayField = (ArrayField) fieldRegistration;
+
+ builder.append(StringUtils.format("if ({} == null):", objectStr)).append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append("buffer.writeInt(0)").append(LS);
+ GeneratePyUtils.addTab(builder, deep);
+
+ builder.append("else:").append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("buffer.writeInt({}.size())", objectStr)).append(LS);
+
+ String element = "element" + GenerateProtocolFile.index.getAndIncrement();
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("for {} in {}:", element, objectStr)).append(LS);
+ GeneratePyUtils.pySerializer(arrayField.getArrayElementRegistration().serializer())
+ .writeObject(builder, element, deep + 2, field, arrayField.getArrayElementRegistration());
+ }
+
+ @Override
+ public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.addTab(builder, deep);
+ var cutDown = CutDownArraySerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.GdScript);
+ if (cutDown != null) {
+ return cutDown;
+ }
+
+ ArrayField arrayField = (ArrayField) fieldRegistration;
+ String result = "result" + GenerateProtocolFile.index.getAndIncrement();
+
+ builder.append(StringUtils.format("{} = []", result)).append(LS);
+
+ String i = "index" + GenerateProtocolFile.index.getAndIncrement();
+ String size = "size" + GenerateProtocolFile.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readInt()", size)).append(LS);
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("if ({} > 0):", size)).append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("for {} in range({}):", i, size)).append(LS);
+ String readObject = GeneratePyUtils.pySerializer(arrayField.getArrayElementRegistration().serializer())
+ .readObject(builder, deep + 2, field, arrayField.getArrayElementRegistration());
+ GeneratePyUtils.addTab(builder, deep + 2);
+ builder.append(StringUtils.format("{}.append({})", result, readObject)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyBooleanSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyBooleanSerializer.java
new file mode 100644
index 00000000..7aac0b3a
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyBooleanSerializer.java
@@ -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.python;
+
+import com.zfoo.protocol.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyBooleanSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "False";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.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.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readBool() ", result)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyByteSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyByteSerializer.java
new file mode 100644
index 00000000..62a5e043
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyByteSerializer.java
@@ -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.python;
+
+import com.zfoo.protocol.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyByteSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "0";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.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.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readByte()", result)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyCharSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyCharSerializer.java
new file mode 100644
index 00000000..b152b749
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyCharSerializer.java
@@ -0,0 +1,48 @@
+/*
+ * 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.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyCharSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return StringUtils.EMPTY;
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("buffer.writeChar({})", objectStr)).append(LS);
+ }
+
+ @Override
+ public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
+ String result = "result" + GenerateProtocolFile.index.getAndIncrement();
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readChar()", result)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyDoubleSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyDoubleSerializer.java
new file mode 100644
index 00000000..ece68a52
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyDoubleSerializer.java
@@ -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.python;
+
+import com.zfoo.protocol.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyDoubleSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "0.0";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.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.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readDouble()", result)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyFloatSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyFloatSerializer.java
new file mode 100644
index 00000000..1e29b461
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyFloatSerializer.java
@@ -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.python;
+
+import com.zfoo.protocol.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyFloatSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "0.0";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.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.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readFloat()", result)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyIntSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyIntSerializer.java
new file mode 100644
index 00000000..2d444c32
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyIntSerializer.java
@@ -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.python;
+
+import com.zfoo.protocol.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyIntSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "0";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.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.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readInt()", result)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyListSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyListSerializer.java
new file mode 100644
index 00000000..85542fb5
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyListSerializer.java
@@ -0,0 +1,92 @@
+/*
+ * 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.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyListSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "[]";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.addTab(builder, deep);
+ if (CutDownListSerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.GdScript)) {
+ return;
+ }
+
+ ListField listField = (ListField) fieldRegistration;
+
+ builder.append(StringUtils.format("if ({} == null):", objectStr)).append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append("buffer.writeInt(0)").append(LS);
+ GeneratePyUtils.addTab(builder, deep);
+
+ builder.append("else:").append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("buffer.writeInt({}.size())", objectStr)).append(LS);
+
+ String element = "element" + GenerateProtocolFile.index.getAndIncrement();
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("for {} in {}:", element, objectStr)).append(LS);
+ GeneratePyUtils.pySerializer(listField.getListElementRegistration().serializer())
+ .writeObject(builder, element, deep + 2, field, listField.getListElementRegistration());
+ }
+
+ @Override
+ public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.addTab(builder, deep);
+ var cutDown = CutDownListSerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.GdScript);
+ if (cutDown != null) {
+ return cutDown;
+ }
+
+ ListField listField = (ListField) fieldRegistration;
+ String result = "result" + GenerateProtocolFile.index.getAndIncrement();
+
+ builder.append(StringUtils.format("{} = []", result)).append(LS);
+
+ String i = "index" + GenerateProtocolFile.index.getAndIncrement();
+ String size = "size" + GenerateProtocolFile.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readInt()", size)).append(LS);
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("if ({} > 0):", size)).append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("for {} in range({}):", i, size)).append(LS);
+ String readObject = GeneratePyUtils.pySerializer(listField.getListElementRegistration().serializer())
+ .readObject(builder, deep + 2, field, listField.getListElementRegistration());
+ GeneratePyUtils.addTab(builder, deep + 2);
+ builder.append(StringUtils.format("{}.append({})", result, readObject)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyLongSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyLongSerializer.java
new file mode 100644
index 00000000..4815cd06
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyLongSerializer.java
@@ -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.python;
+
+import com.zfoo.protocol.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyLongSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "0";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.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.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readLong()", result)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyMapSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyMapSerializer.java
new file mode 100644
index 00000000..49e2f183
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyMapSerializer.java
@@ -0,0 +1,104 @@
+/*
+ * 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.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyMapSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "{}";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.addTab(builder, deep);
+ if (CutDownMapSerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.GdScript)) {
+ return;
+ }
+
+ MapField mapField = (MapField) fieldRegistration;
+ builder.append(StringUtils.format("if ({} == null):", objectStr)).append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append("buffer.writeInt(0)").append(LS);
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append("else:").append(LS);
+
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("buffer.writeInt({}.size())", objectStr)).append(LS);
+
+ String key = "key" + GenerateProtocolFile.index.getAndIncrement();
+ String value = "value" + GenerateProtocolFile.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("for {} in {}:", key, objectStr)).append(LS);
+ GeneratePyUtils.addTab(builder, deep + 2);
+ builder.append(StringUtils.format("{} = {}[{}]", value, objectStr, key)).append(LS);
+ GeneratePyUtils.pySerializer(mapField.getMapKeyRegistration().serializer())
+ .writeObject(builder, key, deep + 2, field, mapField.getMapKeyRegistration());
+ GeneratePyUtils.pySerializer(mapField.getMapValueRegistration().serializer())
+ .writeObject(builder, value, deep + 2, field, mapField.getMapValueRegistration());
+ }
+
+ @Override
+ public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.addTab(builder, deep);
+ var cutDown = CutDownMapSerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.GdScript);
+ if (cutDown != null) {
+ return cutDown;
+ }
+
+ MapField mapField = (MapField) fieldRegistration;
+ String result = "result" + GenerateProtocolFile.index.getAndIncrement();
+
+ builder.append(StringUtils.format("{} = {}", result)).append(LS);
+
+ GeneratePyUtils.addTab(builder, deep);
+ String size = "size" + GenerateProtocolFile.index.getAndIncrement();
+ builder.append(StringUtils.format("{} = buffer.readInt()", size)).append(LS);
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("if ({} > 0):", size)).append(LS);
+
+ String i = "index" + GenerateProtocolFile.index.getAndIncrement();
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("for {} in range({}):", i, size)).append(LS);
+
+ String keyObject = GeneratePyUtils.pySerializer(mapField.getMapKeyRegistration().serializer())
+ .readObject(builder, deep + 2, field, mapField.getMapKeyRegistration());
+
+
+ String valueObject = GeneratePyUtils.pySerializer(mapField.getMapValueRegistration().serializer())
+ .readObject(builder, deep + 2, field, mapField.getMapValueRegistration());
+ GeneratePyUtils.addTab(builder, deep + 2);
+
+ builder.append(StringUtils.format("{}[{}] = {}", result, keyObject, valueObject)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyObjectProtocolSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyObjectProtocolSerializer.java
new file mode 100644
index 00000000..d3812a8d
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyObjectProtocolSerializer.java
@@ -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.python;
+
+import com.zfoo.protocol.generate.GenerateProtocolFile;
+import com.zfoo.protocol.registration.field.IFieldRegistration;
+import com.zfoo.protocol.registration.field.ObjectProtocolField;
+
+import com.zfoo.protocol.util.StringUtils;
+
+import java.lang.reflect.Field;
+
+import static com.zfoo.protocol.util.FileUtils.LS;
+
+/**
+ * @author godotg
+ * @version 3.0
+ */
+public class PyObjectProtocolSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "None";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("buffer.writePacket({}, {})", objectStr, objectProtocolField.getProtocolId())).append(LS);
+ }
+
+ @Override
+ public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
+ ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
+ var result = "result" + GenerateProtocolFile.index.getAndIncrement();
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readPacket({})", result, objectProtocolField.getProtocolId())).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PySetSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PySetSerializer.java
new file mode 100644
index 00000000..ad4103dc
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PySetSerializer.java
@@ -0,0 +1,92 @@
+/*
+ * 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.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PySetSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "{}";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.addTab(builder, deep);
+ if (CutDownSetSerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.GdScript)) {
+ return;
+ }
+
+ SetField setField = (SetField) fieldRegistration;
+
+ builder.append(StringUtils.format("if ({} == null):", objectStr)).append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append("buffer.writeInt(0)").append(LS);
+ GeneratePyUtils.addTab(builder, deep);
+
+ builder.append("else:").append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("buffer.writeInt({}.size())", objectStr)).append(LS);
+
+ String element = "element" + GenerateProtocolFile.index.getAndIncrement();
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("for {} in {}:", element, objectStr)).append(LS);
+ GeneratePyUtils.pySerializer(setField.getSetElementRegistration().serializer())
+ .writeObject(builder, element, deep + 2, field, setField.getSetElementRegistration());
+ }
+
+ @Override
+ public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.addTab(builder, deep);
+ var cutDown = CutDownSetSerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.GdScript);
+ if (cutDown != null) {
+ return cutDown;
+ }
+
+ SetField setField = (SetField) fieldRegistration;
+ String result = "result" + GenerateProtocolFile.index.getAndIncrement();
+
+ builder.append(StringUtils.format("{} = []", result)).append(LS);
+
+ String i = "index" + GenerateProtocolFile.index.getAndIncrement();
+ String size = "size" + GenerateProtocolFile.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readInt()", size)).append(LS);
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("if ({} > 0):", size)).append(LS);
+ GeneratePyUtils.addTab(builder, deep + 1);
+ builder.append(StringUtils.format("for {} in range({}):", i, size)).append(LS);
+ String readObject = GeneratePyUtils.pySerializer(setField.getSetElementRegistration().serializer())
+ .readObject(builder, deep + 2, field, setField.getSetElementRegistration());
+ GeneratePyUtils.addTab(builder, deep + 2);
+ builder.append(StringUtils.format("{}.append({})", result, readObject)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyShortSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyShortSerializer.java
new file mode 100644
index 00000000..030d1cb7
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyShortSerializer.java
@@ -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.python;
+
+import com.zfoo.protocol.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyShortSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return "0";
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.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.index.getAndIncrement();
+
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readShort()", result)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyStringSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyStringSerializer.java
new file mode 100644
index 00000000..cfe89dcc
--- /dev/null
+++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/PyStringSerializer.java
@@ -0,0 +1,48 @@
+/*
+ * 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.generate.GenerateProtocolFile;
+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
+ * @version 3.0
+ */
+public class PyStringSerializer implements IPySerializer {
+ @Override
+ public String fieldDefaultValue(Field field, IFieldRegistration fieldRegistration) {
+ return StringUtils.EMPTY;
+ }
+
+ @Override
+ public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
+ GeneratePyUtils.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.index.getAndIncrement();
+ GeneratePyUtils.addTab(builder, deep);
+ builder.append(StringUtils.format("{} = buffer.readString()", result)).append(LS);
+ return result;
+ }
+}
diff --git a/protocol/src/main/resources/python/ProtocolTemplate.py b/protocol/src/main/resources/python/ProtocolTemplate.py
new file mode 100644
index 00000000..81281b81
--- /dev/null
+++ b/protocol/src/main/resources/python/ProtocolTemplate.py
@@ -0,0 +1,18 @@
+{}
+class {}():
+
+ {}
+
+ def protocolId(self):
+ return {}
+
+ @classmethod
+ def write(cls, buffer, packet):
+ if (buffer.writePacketFlag(packet)):
+ return
+ {}
+
+ @classmethod
+ def read(cls, buffer):
+ {}
+ pass
\ No newline at end of file
diff --git a/protocol/src/main/resources/python/byte_buffer.py b/protocol/src/main/resources/python/byte_buffer.py
new file mode 100644
index 00000000..0227bcdd
--- /dev/null
+++ b/protocol/src/main/resources/python/byte_buffer.py
@@ -0,0 +1,303 @@
+import struct
+
+maxSize = 655537
+maxInt = 2147483647
+minInt = -2147483648
+maxLong = 9223372036854775807
+minLong = -9223372036854775808
+empty_str = ""
+
+
+class ByteBuffer():
+ writeOffset = 0
+ readOffset = 0
+ buffer = bytearray(8)
+
+ def setWriteOffset(self, writeOffset):
+ if writeOffset > len(self.buffer):
+ raise ValueError("index out of bounds exception:readerIndex:" + str(self.readOffset) +
+ ", writerIndex:" + str(self.writeOffset) +
+ "(expected:0 <= readerIndex <= writerIndex <= capacity:" + str(len(self.buffer)))
+ self.writeOffset = writeOffset
+
+ def setReadOffset(self, readOffset):
+ if readOffset > self.writeOffset:
+ raise ValueError("index out of bounds exception:readerIndex:" + str(self.readOffset) +
+ ", writerIndex:" + str(self.writeOffset) +
+ "(expected:0 <= readerIndex <= writerIndex <= capacity:" + str(len(self.buffer)))
+ self.readOffset = readOffset
+
+ def isReadable(self):
+ return self.writeOffset > self.readOffset
+ pass
+
+ def getCapacity(self):
+ return len(self.buffer) - self.writeOffset
+
+ def ensureCapacity(self, minCapacity):
+ while (minCapacity - self.getCapacity() > 0):
+ newSize = len(self.buffer) * 2
+ if newSize > maxSize:
+ raise ValueError("out of memory error")
+ # auto grow capacity
+ self.buffer.extend(bytearray(len(self.buffer)))
+
+ def writeBool(self, value):
+ if value:
+ self.writeByte(1)
+ else:
+ self.writeByte(0)
+
+ def readBool(self):
+ if self.readByte():
+ return True
+ else:
+ return False
+
+ def writeByte(self, value):
+ self.ensureCapacity(1)
+ struct.pack_into('>b', self.buffer, self.writeOffset, value)
+ self.writeOffset += 1
+
+ def readByte(self):
+ value = struct.unpack_from('>b', self.buffer, self.readOffset)[0]
+ self.readOffset += 1
+ return value
+
+ def writeUByte(self, value):
+ self.ensureCapacity(1)
+ struct.pack_into('>B', self.buffer, self.writeOffset, value)
+ self.writeOffset += 1
+
+ def readUByte(self):
+ value = struct.unpack_from('>B', self.buffer, self.readOffset)[0]
+ self.readOffset += 1
+ return value
+
+ def writeShort(self, value):
+ self.ensureCapacity(1)
+ struct.pack_into('>h', self.buffer, self.writeOffset, value)
+ self.writeOffset += 2
+
+ def readShort(self):
+ value = struct.unpack_from('>h', self.buffer, self.readOffset)[0]
+ self.readOffset += 2
+ return value
+
+ def writeRawInt(self, value):
+ self.ensureCapacity(4)
+ struct.pack_into('>i', self.buffer, self.writeOffset, value)
+ self.writeOffset += 4
+
+ def readRawInt(self):
+ value = struct.unpack_from('>i', self.buffer, self.readOffset)[0]
+ self.readOffset += 4
+ return value
+
+ def writeInt(self, value):
+ if not (minInt <= value <= maxInt):
+ raise ValueError('value must range between minInt:-2147483648 and maxInt:2147483647')
+ value = (value << 1) ^ (value >> 31)
+ self.ensureCapacity(5)
+ if value >> 7 == 0:
+ self.writeUByte(value)
+ return
+
+ if value >> 14 == 0:
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte((value >> 7) & 0x7F)
+ return
+
+ if value >> 21 == 0:
+ self.writeUByte((value & 0x7F) | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte((value >> 14) & 0x7F)
+ return
+
+ if value >> 28 == 0:
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte(((value >> 14) & 0x7F | 0x80))
+ self.writeUByte((value >> 21) & 0x7F)
+ return
+
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte(((value >> 14) & 0x7F | 0x80))
+ self.writeUByte(((value >> 21) & 0x7F | 0x80))
+ self.writeUByte((value >> 28) & 0x7F)
+ pass
+
+ def readInt(self):
+ b = self.readUByte()
+ value = b & 0x7F
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 7
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 14
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 21
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 28
+ return (value >> 1) ^ -(value & 1)
+
+ def writeLong(self, value):
+ if not (minLong <= value <= maxLong):
+ raise ValueError('value must range between minLong:-9223372036854775808 and maxLong:9223372036854775807')
+ value = (value << 1) ^ (value >> 63)
+ self.ensureCapacity(9)
+ if value >> 7 == 0:
+ self.writeUByte(value)
+ return
+
+ if value >> 14 == 0:
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte((value >> 7) & 0x7F)
+ return
+
+ if value >> 21 == 0:
+ self.writeUByte((value & 0x7F) | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte((value >> 14) & 0x7F)
+ return
+
+ if value >> 28 == 0:
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte(((value >> 14) & 0x7F | 0x80))
+ self.writeUByte((value >> 21) & 0x7F)
+ return
+ if value >> 35 == 0:
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte(((value >> 14) & 0x7F | 0x80))
+ self.writeUByte(((value >> 21) & 0x7F | 0x80))
+ self.writeUByte((value >> 28) & 0x7F)
+ return
+ if value >> 42 == 0:
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte(((value >> 14) & 0x7F | 0x80))
+ self.writeUByte(((value >> 21) & 0x7F | 0x80))
+ self.writeUByte(((value >> 28) & 0x7F | 0x80))
+ self.writeUByte((value >> 35) & 0x7F)
+ return
+ if value >> 49 == 0:
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte(((value >> 14) & 0x7F | 0x80))
+ self.writeUByte(((value >> 21) & 0x7F | 0x80))
+ self.writeUByte(((value >> 28) & 0x7F | 0x80))
+ self.writeUByte(((value >> 35) & 0x7F | 0x80))
+ self.writeUByte((value >> 42) & 0x7F)
+ return
+ if value >> 56 == 0:
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte(((value >> 14) & 0x7F | 0x80))
+ self.writeUByte(((value >> 21) & 0x7F | 0x80))
+ self.writeUByte(((value >> 28) & 0x7F | 0x80))
+ self.writeUByte(((value >> 35) & 0x7F | 0x80))
+ self.writeUByte(((value >> 42) & 0x7F | 0x80))
+ self.writeUByte((value >> 49) & 0x7F)
+ return
+ self.writeUByte(value & 0x7F | 0x80)
+ self.writeUByte(((value >> 7) & 0x7F | 0x80))
+ self.writeUByte(((value >> 14) & 0x7F | 0x80))
+ self.writeUByte(((value >> 21) & 0x7F | 0x80))
+ self.writeUByte(((value >> 28) & 0x7F | 0x80))
+ self.writeUByte(((value >> 35) & 0x7F | 0x80))
+ self.writeUByte(((value >> 42) & 0x7F | 0x80))
+ self.writeUByte(((value >> 49) & 0x7F | 0x80))
+ self.writeUByte(value >> 56)
+ pass
+
+ def readLong(self):
+ b = self.readUByte()
+ value = b & 0x7F
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 7
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 14
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 21
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 28
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 35
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 42
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= (b & 0x7F) << 49
+ if (b & 0x80) != 0:
+ b = self.readUByte()
+ value |= b << 56
+ return (value >> 1) ^ -(value & 1)
+
+ def writeFloat(self, value):
+ self.ensureCapacity(4)
+ struct.pack_into('>f', self.buffer, self.writeOffset, value)
+ self.writeOffset += 4
+
+ def readFloat(self):
+ value = struct.unpack_from('>f', self.buffer, self.readOffset)[0]
+ self.readOffset += 4
+ return value
+
+ def writeDouble(self, value):
+ self.ensureCapacity(8)
+ struct.pack_into('>d', self.buffer, self.writeOffset, value)
+ self.writeOffset += 8
+
+ def readDouble(self):
+ value = struct.unpack_from('>d', self.buffer, self.readOffset)[0]
+ self.readOffset += 8
+ return value
+
+ def writeChar(self, value):
+ if len(value) == 0:
+ self.writeInt(0)
+ return
+ self.writeString(value[0])
+
+ def readChar(self):
+ return self.readString()
+
+ def writeString(self, value):
+ if len(value) == 0:
+ self.writeInt(0)
+ return
+ byte_array = bytearray(value, 'utf-8')
+ length = len(byte_array)
+ self.ensureCapacity(5 + length)
+ self.writeInt(length)
+ self.buffer[self.writeOffset:self.writeOffset + length] = byte_array[:]
+ self.writeOffset += length
+
+ def readString(self):
+ length = self.readInt()
+ if (length <= 0):
+ return empty_str
+ byte_array = self.buffer[self.readOffset:self.readOffset + length]
+ # 使用utf-8编码进行解码
+ value = byte_array.decode('utf-8')
+ self.readOffset += length
+ return value
+
+ def writePacketFlag(self, value):
+ if value is None:
+ self.writeBool(False)
+ else:
+ self.writeBool(True)
+ pass
\ No newline at end of file
diff --git a/protocol/src/test/java/com/zfoo/protocol/SpeedTest.java b/protocol/src/test/java/com/zfoo/protocol/SpeedTest.java
index e820ec97..26dc59d5 100644
--- a/protocol/src/test/java/com/zfoo/protocol/SpeedTest.java
+++ b/protocol/src/test/java/com/zfoo/protocol/SpeedTest.java
@@ -23,6 +23,7 @@ import com.google.protobuf.CodedOutputStream;
import com.zfoo.protocol.collection.ArrayUtils;
import com.zfoo.protocol.generate.GenerateOperation;
import com.zfoo.protocol.packet.*;
+import com.zfoo.protocol.serializer.CodeLanguage;
import com.zfoo.protocol.util.StringUtils;
import io.fury.Fury;
import io.fury.Language;
@@ -375,6 +376,7 @@ public class SpeedTest {
// op.getGenerateLanguages().add(CodeLanguage.Lua);
// op.getGenerateLanguages().add(CodeLanguage.CSharp);
// op.getGenerateLanguages().add(CodeLanguage.GdScript);
+ op.getGenerateLanguages().add(CodeLanguage.Python);
// 需要protocol协议的字段里面都加上JProtobuf注解才能用
// op.setProtocolParam("protobuf=protobuf.xml");