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 aff1ec02..bd62a333 100644 --- a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java +++ b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java @@ -90,6 +90,7 @@ public abstract class GenerateProtocolNote { case EcmaScript: case TypeScript: case CSharp: + case Php: case Protobuf: note = StringUtils.format("// {}", note); break; diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/CodeLanguage.java b/protocol/src/main/java/com/zfoo/protocol/serializer/CodeLanguage.java index 6e4cdce7..a8948695 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/CodeLanguage.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/CodeLanguage.java @@ -21,6 +21,7 @@ import com.zfoo.protocol.serializer.java.CodeGenerateJava; import com.zfoo.protocol.serializer.javascript.CodeGenerateJavaScript; import com.zfoo.protocol.serializer.kotlin.CodeGenerateKotlin; import com.zfoo.protocol.serializer.lua.CodeGenerateLua; +import com.zfoo.protocol.serializer.php.CodeGeneratePhp; import com.zfoo.protocol.serializer.python.CodeGeneratePython; import com.zfoo.protocol.serializer.scala.CodeGenerateScala; import com.zfoo.protocol.serializer.typescript.CodeGenerateTypeScript; @@ -59,6 +60,8 @@ public enum CodeLanguage { Python(1 << 22, CodeGeneratePython.class), + Php(1 << 28, CodeGeneratePhp.class), + Protobuf(1 << 30, null); public final int id; diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/CodeGeneratePhp.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/CodeGeneratePhp.java new file mode 100644 index 00000000..822afe82 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/CodeGeneratePhp.java @@ -0,0 +1,405 @@ +/* + * 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.php; + +import com.zfoo.protocol.anno.Compatible; +import com.zfoo.protocol.generate.GenerateOperation; +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.generate.GenerateProtocolNote; +import com.zfoo.protocol.generate.GenerateProtocolPath; +import com.zfoo.protocol.registration.ProtocolAnalysis; +import com.zfoo.protocol.registration.ProtocolRegistration; +import com.zfoo.protocol.serializer.CodeLanguage; +import com.zfoo.protocol.serializer.CodeTemplatePlaceholder; +import com.zfoo.protocol.serializer.ICodeGenerate; +import com.zfoo.protocol.serializer.enhance.EnhanceObjectProtocolSerializer; +import com.zfoo.protocol.serializer.reflect.*; +import com.zfoo.protocol.util.ClassUtils; +import com.zfoo.protocol.util.FileUtils; +import com.zfoo.protocol.util.ReflectionUtils; +import com.zfoo.protocol.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.zfoo.protocol.util.FileUtils.LS; +import static com.zfoo.protocol.util.StringUtils.TAB; + +/** + * @author godotg + */ +public class CodeGeneratePhp implements ICodeGenerate { + private static final Logger logger = LoggerFactory.getLogger(CodeGeneratePhp.class); + + // custom configuration + public static String protocolOutputRootPath = "zfoophp"; + private static String protocolOutputPath = StringUtils.EMPTY; + + private static final Map phpSerializerMap = new HashMap<>(); + + public static IPhpSerializer phpSerializer(ISerializer serializer) { + return phpSerializerMap.get(serializer); + } + + @Override + public void init(GenerateOperation generateOperation) { + protocolOutputPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath); + FileUtils.deleteFile(new File(protocolOutputPath)); + + phpSerializerMap.put(BooleanSerializer.INSTANCE, new PhpBooleanSerializer()); + phpSerializerMap.put(ByteSerializer.INSTANCE, new PhpByteSerializer()); + phpSerializerMap.put(ShortSerializer.INSTANCE, new PhpShortSerializer()); + phpSerializerMap.put(IntSerializer.INSTANCE, new PhpIntSerializer()); + phpSerializerMap.put(LongSerializer.INSTANCE, new PhpLongSerializer()); + phpSerializerMap.put(FloatSerializer.INSTANCE, new PhpFloatSerializer()); + phpSerializerMap.put(DoubleSerializer.INSTANCE, new PhpDoubleSerializer()); + phpSerializerMap.put(StringSerializer.INSTANCE, new PhpStringSerializer()); + phpSerializerMap.put(ArraySerializer.INSTANCE, new PhpArraySerializer()); + phpSerializerMap.put(ListSerializer.INSTANCE, new PhpListSerializer()); + phpSerializerMap.put(SetSerializer.INSTANCE, new PhpSetSerializer()); + phpSerializerMap.put(MapSerializer.INSTANCE, new PhpMapSerializer()); + phpSerializerMap.put(ObjectProtocolSerializer.INSTANCE, new PhpObjectProtocolSerializer()); + } + + @Override + public void mergerProtocol(List registrations) throws IOException { + createTemplateFile(); + + + // 生成ProtocolManager.ts文件 + var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("typescript/ProtocolManagerTemplate.ts"); + var protocol_imports_manager = new StringBuilder(); + var protocol_manager_registrations = new StringBuilder(); + protocol_imports_manager.append("import * as Protocols from './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.set({}, new Protocols.{}Registration());", protocol_id, protocol_name)).append(LS); + protocol_manager_registrations.append(StringUtils.format("protocolIdMap.set(Protocols.{}, {});", protocol_name, protocol_id)).append(LS); + } + var placeholderMap = Map.of(CodeTemplatePlaceholder.protocol_imports, protocol_imports_manager.toString() + , CodeTemplatePlaceholder.protocol_manager_registrations, protocol_manager_registrations.toString()); + var formatProtocolManagerTemplate = CodeTemplatePlaceholder.formatTemplate(protocolManagerTemplate, placeholderMap); + var protocolManagerFile = new File(StringUtils.format("{}/{}", protocolOutputPath, "ProtocolManager.ts")); + FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true); + logger.info("Generated TypeScript protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath()); + + + var protocol_imports_protocols = new StringBuilder(); + protocol_imports_protocols.append("import IByteBuffer from './IByteBuffer';").append(LS); + protocol_imports_protocols.append("import IProtocolRegistration from './IProtocolRegistration';").append(LS); + var protocol_class = new StringBuilder(); + var protocol_registration = new StringBuilder(); + for (var registration : registrations) { + protocol_class.append(protocol_class(registration).replace("class ", "export class ")).append(LS); + protocol_registration.append(protocol_registration(registration)).append(LS); + } + var protocolTemplate = ClassUtils.getFileFromClassPathToString("typescript/ProtocolsTemplate.ts"); + var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of( + CodeTemplatePlaceholder.protocol_imports, protocol_imports_protocols.toString() + , CodeTemplatePlaceholder.protocol_class, protocol_class.toString() + , CodeTemplatePlaceholder.protocol_registration, protocol_registration.toString() + )); + var outputPath = StringUtils.format("{}/Protocols.ts", protocolOutputPath); + var file = new File(outputPath); + FileUtils.writeStringToFile(file, formatProtocolTemplate, true); + logger.info("Generated TypeScript protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); + } + + @Override + public void foldProtocol(List registrations) throws IOException { + createTemplateFile(); + + + // 生成ProtocolManager.ts文件 + var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("typescript/ProtocolManagerTemplate.ts"); + 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("import {} from './{}/{}';", protocol_name, GenerateProtocolPath.protocolPathSlash(protocol_id), protocol_name)).append(LS); + protocol_imports.append(StringUtils.format("import { {}Registration } from './{}/{}';", protocol_name, GenerateProtocolPath.protocolPathSlash(protocol_id), protocol_name)).append(LS); + protocol_manager_registrations.append(StringUtils.format("protocols.set({}, new {}Registration());", protocol_id, protocol_name)).append(LS); + protocol_manager_registrations.append(StringUtils.format("protocolIdMap.set({}, {});", protocol_name, protocol_id)).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.ts")); + FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true); + logger.info("Generated TypeScript protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath()); + + + for (var registration : registrations) { + var protocol_id = registration.protocolId(); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var protocolTemplate = ClassUtils.getFileFromClassPathToString("typescript/ProtocolTemplate.ts"); + var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of( + CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id) + , CodeTemplatePlaceholder.protocol_name, protocol_name + , CodeTemplatePlaceholder.protocol_class, protocol_class(registration) + , CodeTemplatePlaceholder.protocol_registration, protocol_registration(registration) + )); + var outputPath = StringUtils.format("{}/{}/{}.ts", protocolOutputPath, GenerateProtocolPath.protocolPathSlash(protocol_id), protocol_name); + var file = new File(outputPath); + FileUtils.writeStringToFile(file, formatProtocolTemplate, true); + logger.info("Generated TypeScript protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); + } + } + + @Override + public void defaultProtocol(List registrations) throws IOException { + createTemplateFile(); + + + // 生成ProtocolManager.ts文件 + var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("php/ProtocolManagerTemplate.php"); + 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("include_once '{}.php';", protocol_name, protocol_name)).append(LS); + protocol_manager_registrations.append(StringUtils.format("self::$protocols[{}] = new {}Registration();", protocol_id, protocol_name)).append(LS); + protocol_manager_registrations.append(StringUtils.format("self::$protocolIdMap[{}::class] = {};", protocol_name, protocol_id)).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.php")); + FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true); + logger.info("Generated Php protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath()); + + + for (var registration : registrations) { + var protocol_id = registration.protocolId(); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var protocolTemplate = ClassUtils.getFileFromClassPathToString("php/ProtocolTemplate.php"); + var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of( + CodeTemplatePlaceholder.protocol_name, protocol_name + , CodeTemplatePlaceholder.protocol_imports, protocol_imports_default(registration) + , CodeTemplatePlaceholder.protocol_class, protocol_class(registration) + , CodeTemplatePlaceholder.protocol_registration, protocol_registration(registration) + )); + var outputPath = StringUtils.format("{}/{}.php", protocolOutputPath, protocol_name); + var file = new File(outputPath); + FileUtils.writeStringToFile(file, formatProtocolTemplate, true); + logger.info("Generated Php protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); + } + } + + private void createTemplateFile() throws IOException { + var list = List.of("php/IProtocolRegistration.php", "php/ByteBuffer.php"); + for (var fileName : list) { + var fileInputStream = ClassUtils.getFileFromClassPath(fileName); + var createFile = new File(StringUtils.format("{}/{}", protocolOutputPath, StringUtils.substringAfterFirst(fileName, "php/"))); + FileUtils.writeInputStreamToFile(createFile, fileInputStream); + } + } + + private String protocol_class(ProtocolRegistration registration) { + var protocol_id = registration.protocolId(); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var protocolTemplate = ClassUtils.getFileFromClassPathToString("php/ProtocolClassTemplate.php"); + var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of( + CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Php) + , CodeTemplatePlaceholder.protocol_name, protocol_name + , CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id) + , CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration) + )); + return formatProtocolTemplate; + } + + private String protocol_registration(ProtocolRegistration registration) { + var protocol_id = registration.protocolId(); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var protocolTemplate = ClassUtils.getFileFromClassPathToString("php/ProtocolRegistrationTemplate.php"); + var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of( + CodeTemplatePlaceholder.protocol_name, protocol_name + , CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id) + , CodeTemplatePlaceholder.protocol_write_serialization, protocol_write_serialization(registration) + , CodeTemplatePlaceholder.protocol_read_deserialization, protocol_read_deserialization(registration) + )); + return formatProtocolTemplate; + } + + private String protocol_imports_default(ProtocolRegistration registration) { + // import IByteBuffer first + var protocolId = registration.getId(); + var importBuilder = new StringBuilder(); + importBuilder.append(StringUtils.format("include_once 'IProtocolRegistration.php';")).append(LS); + + // import other sub protocols + var subProtocols = ProtocolAnalysis.getFirstSubProtocolIds(protocolId); + for (var subProtocolId : subProtocols) { + var protocolName = EnhanceObjectProtocolSerializer.getProtocolClassSimpleName(subProtocolId); + importBuilder.append(StringUtils.format("include_once '{}.php';", protocolName, protocolName)).append(LS); + } + return importBuilder.toString(); + } + + private String protocol_field_definition(ProtocolRegistration registration) { + var protocolId = registration.protocolId(); + var fields = registration.getFields(); + var fieldRegistrations = registration.getFieldRegistrations(); + // when generate source code fields, use origin fields sort + var sequencedFields = ReflectionUtils.notStaticAndTransientFields(registration.getConstructor().getDeclaringClass()); + var phpBuilder = new StringBuilder(); + for (var field : sequencedFields) { + var fieldRegistration = fieldRegistrations[GenerateProtocolFile.indexOf(fields, field)]; + var fieldName = field.getName(); + // 生成注释 + var fieldNotes = GenerateProtocolNote.fieldNotes(protocolId, fieldName, CodeLanguage.Php); + for (var fieldNote : fieldNotes) { + phpBuilder.append(fieldNote).append(LS); + } + var pair = phpSerializer(fieldRegistration.serializer()).field(field, fieldRegistration); + phpBuilder.append(StringUtils.format("var {} ${} = {};", pair.getKey(), fieldName, pair.getValue())).append(LS); + } + return phpBuilder.toString(); + } + + private String protocol_write_serialization(ProtocolRegistration registration) { + GenerateProtocolFile.localVariableId = 0; + var fields = registration.getFields(); + var fieldRegistrations = registration.getFieldRegistrations(); + var phpBuilder = new StringBuilder(); + if (registration.isCompatible()) { + phpBuilder.append("$beforeWriteIndex = $buffer->getWriteOffset();").append(LS); + phpBuilder.append(StringUtils.format("$buffer->writeInt({});", registration.getPredictionLength())).append(LS); + } else { + phpBuilder.append("$buffer->writeInt(-1);").append(LS); + } + for (var i = 0; i < fields.length; i++) { + var field = fields[i]; + var fieldRegistration = fieldRegistrations[i]; + phpSerializer(fieldRegistration.serializer()).writeObject(phpBuilder, "$packet->" + field.getName(), 0, field, fieldRegistration); + } + if (registration.isCompatible()) { + phpBuilder.append(StringUtils.format("$buffer->adjustPadding({}, $beforeWriteIndex);", registration.getPredictionLength())).append(LS); + } + return phpBuilder.toString(); + } + + private String protocol_read_deserialization(ProtocolRegistration registration) { + GenerateProtocolFile.localVariableId = 0; + var fields = registration.getFields(); + var fieldRegistrations = registration.getFieldRegistrations(); + var phpBuilder = new StringBuilder(); + for (var i = 0; i < fields.length; i++) { + var field = fields[i]; + var fieldRegistration = fieldRegistrations[i]; + if (field.isAnnotationPresent(Compatible.class)) { + phpBuilder.append("if ($buffer->compatibleRead($beforeReadIndex, $length)) {").append(LS); + var compatibleReadObject = phpSerializer(fieldRegistration.serializer()).readObject(phpBuilder, 1, field, fieldRegistration); + phpBuilder.append(TAB).append(StringUtils.format("$packet->{} = {};", field.getName(), compatibleReadObject)).append(LS); + phpBuilder.append("}").append(LS); + continue; + } + var readObject = phpSerializer(fieldRegistration.serializer()).readObject(phpBuilder, 0, field, fieldRegistration); + phpBuilder.append(StringUtils.format("$packet->{} = {};", field.getName(), readObject)).append(LS); + } + return phpBuilder.toString(); + } + + public static String toTsClassName(String typeName) { + typeName = typeName.replaceAll("java.util.|java.lang.", StringUtils.EMPTY); + typeName = typeName.replaceAll("[a-zA-Z0-9_.]*\\.", StringUtils.EMPTY); + + switch (typeName) { + case "boolean": + case "Boolean": + typeName = "boolean"; + return typeName; + case "byte": + case "Byte": + case "short": + case "Short": + case "int": + case "Integer": + case "long": + case "Long": + case "float": + case "Float": + case "double": + case "Double": + typeName = "number"; + return typeName; + case "char": + case "Character": + case "String": + typeName = "string"; + return typeName; + default: + } + + // 将boolean转为bool + typeName = typeName.replaceAll("[B|b]oolean\\[", "boolean"); + typeName = typeName.replace("", "boolean>"); + + // 将Byte转为byte + typeName = typeName.replace("Byte[", "number"); + typeName = typeName.replace("Byte>", "number>"); + typeName = typeName.replace("", "number>"); + typeName = typeName.replace("", "number>"); + typeName = typeName.replace("", "number>"); + typeName = typeName.replace("", "number>"); + typeName = typeName.replace("", "number>"); + typeName = typeName.replace("", "string>"); + typeName = typeName.replace("", "string>"); + typeName = typeName.replace(" field(Field field, IFieldRegistration fieldRegistration); + + void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration); + + String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration); + +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpArraySerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpArraySerializer.java new file mode 100644 index 00000000..38d2127b --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpArraySerializer.java @@ -0,0 +1,109 @@ +/* + * 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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +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.serializer.kotlin.CodeGenerateKotlin; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpArraySerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("array", "array()"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + if (CutDownArraySerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.Php)) { + return; + } + + ArrayField arrayField = (ArrayField) fieldRegistration; + + builder.append(StringUtils.format("if (empty({})) {", objectStr)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("$buffer->writeInt(0);").append(LS); + GenerateProtocolFile.addTab(builder, deep); + + builder.append("} else {").append(LS); + + GenerateProtocolFile.addTab(builder, deep + 1); + String length = "$length" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = count({});", length, objectStr)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append(StringUtils.format("$buffer->writeInt({});", length)).append(LS); + + String i = "$i" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("for ({} = 0; {} < {}; {}++) {", i, i, length, i)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + String element = "$element" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = {}[{}];", element, objectStr, i)).append(LS); + CodeGeneratePhp.phpSerializer(arrayField.getArrayElementRegistration().serializer()) + .writeObject(builder, element, deep + 2, field, arrayField.getArrayElementRegistration()); + + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("}").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("}").append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + var cutDown = CutDownArraySerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.Php); + if (cutDown != null) { + return cutDown; + } + + ArrayField arrayField = (ArrayField) fieldRegistration; + String result = "$result" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = array();", result)).append(LS); + + String i = "$index" + GenerateProtocolFile.localVariableId++; + String size = "$size" + GenerateProtocolFile.localVariableId++; + + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readInt();", size)).append(LS); + + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append(StringUtils.format("for ({} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS); + String readObject = CodeGeneratePhp.phpSerializer(arrayField.getArrayElementRegistration().serializer()) + .readObject(builder, deep + 2, field, arrayField.getArrayElementRegistration()); + GenerateProtocolFile.addTab(builder, deep + 2); + builder.append(StringUtils.format("array_push({}, {});", result, readObject)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("}").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("}").append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpBooleanSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpBooleanSerializer.java new file mode 100644 index 00000000..310d86d9 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpBooleanSerializer.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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpBooleanSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("bool", "false"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("$buffer->writeBool({});", objectStr)).append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + String result = "$result" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readBool(); ", result)).append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpByteSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpByteSerializer.java new file mode 100644 index 00000000..cb998b90 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpByteSerializer.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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpByteSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("int", "0"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("$buffer->writeByte({});", objectStr)).append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + String result = "$result" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readByte();", result)).append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpDoubleSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpDoubleSerializer.java new file mode 100644 index 00000000..b6cbb295 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpDoubleSerializer.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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpDoubleSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("float", "0"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("$buffer->writeDouble({});", objectStr)).append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + String result = "$result" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readDouble();", result)).append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpFloatSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpFloatSerializer.java new file mode 100644 index 00000000..a6cf2a12 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpFloatSerializer.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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpFloatSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("float", "0"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("$buffer->writeFloat({});", objectStr)).append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + String result = "$result" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readFloat();", result)).append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpIntSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpIntSerializer.java new file mode 100644 index 00000000..32b16c80 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpIntSerializer.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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpIntSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("int", "0"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("$buffer->writeInt({});", objectStr)).append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + String result = "$result" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readInt();", result)).append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpListSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpListSerializer.java new file mode 100644 index 00000000..25e943b8 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpListSerializer.java @@ -0,0 +1,108 @@ +/* + * 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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.registration.field.ArrayField; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.registration.field.ListField; +import com.zfoo.protocol.serializer.CodeLanguage; +import com.zfoo.protocol.serializer.CutDownArraySerializer; +import com.zfoo.protocol.serializer.CutDownListSerializer; +import com.zfoo.protocol.serializer.reflect.ArraySerializer; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpListSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("array", "array()"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + if (CutDownListSerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.Php)) { + return; + } + + ListField listField = (ListField) fieldRegistration; + + builder.append(StringUtils.format("if (empty({})) {", objectStr)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("$buffer->writeInt(0);").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("} else {").append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + String length = "$length" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = count({});", length, objectStr)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append(StringUtils.format("$buffer->writeInt({});", length)).append(LS); + + String i = "$i" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("for ({} = 0; {} < {}; {}++) {", i, i, length, i)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + String element = "$element" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = {}[{}];", element, objectStr, i)).append(LS); + CodeGeneratePhp.phpSerializer(listField.getListElementRegistration().serializer()) + .writeObject(builder, element, deep + 2, field, listField.getListElementRegistration()); + + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("}").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("}").append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + var cutDown = CutDownListSerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.Php); + if (cutDown != null) { + return cutDown; + } + + ListField arrayField = (ListField) fieldRegistration; + String result = "$result" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = array();", result)).append(LS); + + String i = "$index" + GenerateProtocolFile.localVariableId++; + String size = "$size" + GenerateProtocolFile.localVariableId++; + + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readInt();", size)).append(LS); + + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append(StringUtils.format("for ({} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS); + String readObject = CodeGeneratePhp.phpSerializer(arrayField.getListElementRegistration().serializer()) + .readObject(builder, deep + 2, field, arrayField.getListElementRegistration()); + GenerateProtocolFile.addTab(builder, deep + 2); + builder.append(StringUtils.format("array_push({}, {});", result, readObject)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("}").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("}").append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpLongSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpLongSerializer.java new file mode 100644 index 00000000..13ef0296 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpLongSerializer.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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpLongSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("int", "0"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("$buffer->writeLong({});", objectStr)).append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + String result = "$result" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readLong();", result)).append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpMapSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpMapSerializer.java new file mode 100644 index 00000000..7db79ecd --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpMapSerializer.java @@ -0,0 +1,113 @@ +/* + * 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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.registration.field.MapField; +import com.zfoo.protocol.serializer.CodeLanguage; +import com.zfoo.protocol.serializer.CutDownMapSerializer; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpMapSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("array", "array()"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + if (CutDownMapSerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.Php)) { + return; + } + + MapField mapField = (MapField) fieldRegistration; + builder.append(StringUtils.format("if (empty({})) {", objectStr)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("$buffer->writeInt(0);").append(LS); + + GenerateProtocolFile.addTab(builder, deep); + builder.append("} else {").append(LS); + + GenerateProtocolFile.addTab(builder, deep + 1); + String length = "$length" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = count({});", length, objectStr)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append(StringUtils.format("$buffer->writeInt({});", length)).append(LS); + + String key = "$key" + GenerateProtocolFile.localVariableId++; + String value = "$value" + GenerateProtocolFile.localVariableId++; + + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append(StringUtils.format("foreach ({} as {} => {}) {", objectStr, value, key)).append(LS); + CodeGeneratePhp.phpSerializer(mapField.getMapKeyRegistration().serializer()) + .writeObject(builder, key, deep + 2, field, mapField.getMapKeyRegistration()); + CodeGeneratePhp.phpSerializer(mapField.getMapValueRegistration().serializer()) + .writeObject(builder, value, deep + 2, field, mapField.getMapValueRegistration()); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("}").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("}").append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + var cutDown = CutDownMapSerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.Php); + if (cutDown != null) { + return cutDown; + } + + MapField mapField = (MapField) fieldRegistration; + String result = "$result" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = array();", result)).append(LS); + + GenerateProtocolFile.addTab(builder, deep); + String size = "$size" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = $buffer->readInt();", size)).append(LS); + + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS); + + String i = "$index" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append(StringUtils.format("for ({} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS); + + String keyObject = CodeGeneratePhp.phpSerializer(mapField.getMapKeyRegistration().serializer()) + .readObject(builder, deep + 2, field, mapField.getMapKeyRegistration()); + + + String valueObject = CodeGeneratePhp.phpSerializer(mapField.getMapValueRegistration().serializer()) + .readObject(builder, deep + 2, field, mapField.getMapValueRegistration()); + GenerateProtocolFile.addTab(builder, deep + 2); + + builder.append(StringUtils.format("{}[{}] = {};", result, keyObject, valueObject)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("}").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("}").append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpObjectProtocolSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpObjectProtocolSerializer.java new file mode 100644 index 00000000..af25e08d --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpObjectProtocolSerializer.java @@ -0,0 +1,53 @@ +/* + * 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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.registration.field.ObjectProtocolField; +import com.zfoo.protocol.serializer.enhance.EnhanceObjectProtocolSerializer; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpObjectProtocolSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("mixed", "null"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("$buffer->writePacket({}, {});", 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.localVariableId++; + GenerateProtocolFile.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/php/PhpSetSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpSetSerializer.java new file mode 100644 index 00000000..3a5f25cd --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpSetSerializer.java @@ -0,0 +1,108 @@ +/* + * 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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.registration.field.ListField; +import com.zfoo.protocol.registration.field.SetField; +import com.zfoo.protocol.serializer.CodeLanguage; +import com.zfoo.protocol.serializer.CutDownSetSerializer; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpSetSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("array", "array()"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + if (CutDownSetSerializer.getInstance().writeObject(builder, objectStr, field, fieldRegistration, CodeLanguage.Php)) { + return; + } + + SetField setField = (SetField) fieldRegistration; + + builder.append(StringUtils.format("if (empty({})) {", objectStr)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("$buffer->writeInt(0);").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("} else {").append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + String length = "$length" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = count({});", length, objectStr)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append(StringUtils.format("$buffer->writeInt({});", length)).append(LS); + + String i = "$i" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("for ({} = 0; {} < {}; {}++) {", i, i, length, i)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + String element = "$element" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = {}[{}];", element, objectStr, i)).append(LS); + CodeGeneratePhp.phpSerializer(setField.getSetElementRegistration().serializer()) + .writeObject(builder, element, deep + 2, field, setField.getSetElementRegistration()); + + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("}").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("}").append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + var cutDown = CutDownSetSerializer.getInstance().readObject(builder, field, fieldRegistration, CodeLanguage.Php); + if (cutDown != null) { + return cutDown; + } + + SetField setField = (SetField) fieldRegistration; + String result = "$result" + GenerateProtocolFile.localVariableId++; + var typeName = CodeGeneratePhp.toTsClassName(setField.getType().toString()); + builder.append(StringUtils.format("{} = array();", result)).append(LS); + + GenerateProtocolFile.addTab(builder, deep); + String size = "$size" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("{} = $buffer->readInt();", size)).append(LS); + + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS); + + GenerateProtocolFile.addTab(builder, deep + 1); + String i = "$index" + GenerateProtocolFile.localVariableId++; + builder.append(StringUtils.format("for ({} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS); + String readObject = CodeGeneratePhp.phpSerializer(setField.getSetElementRegistration().serializer()) + .readObject(builder, deep + 2, field, setField.getSetElementRegistration()); + GenerateProtocolFile.addTab(builder, deep + 2); + builder.append(StringUtils.format("array_push({}, {});", result, readObject)).append(LS); + GenerateProtocolFile.addTab(builder, deep + 1); + builder.append("}").append(LS); + GenerateProtocolFile.addTab(builder, deep); + builder.append("}").append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpShortSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpShortSerializer.java new file mode 100644 index 00000000..676102d1 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpShortSerializer.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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpShortSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("int", "0"); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("$buffer->writeShort({});", objectStr)).append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + String result = "$result" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readShort();", result)).append(LS); + return result; + } +} diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpStringSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpStringSerializer.java new file mode 100644 index 00000000..666337df --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/php/PhpStringSerializer.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.php; + +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.model.Pair; +import com.zfoo.protocol.model.Triple; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.util.StringUtils; + +import java.lang.reflect.Field; + +import static com.zfoo.protocol.util.FileUtils.LS; + +/** + * @author godotg + */ +public class PhpStringSerializer implements IPhpSerializer { + + @Override + public Pair field(Field field, IFieldRegistration fieldRegistration) { + return new Pair<>("string", "\"\""); + } + + @Override + public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("$buffer->writeString({});", objectStr)).append(LS); + } + + @Override + public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { + String result = "$result" + GenerateProtocolFile.localVariableId++; + GenerateProtocolFile.addTab(builder, deep); + builder.append(StringUtils.format("{} = $buffer->readString();", result)).append(LS); + return result; + } +} diff --git a/protocol/src/main/resources/php/ByteBuffer.php b/protocol/src/main/resources/php/ByteBuffer.php new file mode 100644 index 00000000..c6a46176 --- /dev/null +++ b/protocol/src/main/resources/php/ByteBuffer.php @@ -0,0 +1,927 @@ +buffer = str_pad("", 128); + } + + public function adjustPadding(int $predictionLength, int $beforewriteIndex): void + { + // 因为写入的是可变长的int,如果预留的位置过多,则清除多余的位置 + $currentwriteIndex = $this->writeOffset; + $predictionCount = $this->writeIntCount($predictionLength); + $length = $currentwriteIndex - $beforewriteIndex - $predictionCount; + $lengthCount = $this->writeIntCount($length); + $padding = $lengthCount - $predictionCount; + if ($padding == 0) { + $this->writeOffset = $beforewriteIndex; + $this->writeInt($length); + $this->writeOffset = $currentwriteIndex; + } else { + $bytes = substr($this->buffer, $currentwriteIndex - $length, $length); + $this->writeOffset = $beforewriteIndex; + $this->writeInt($length); + $this->writeBytes($bytes); + } + } + + public function compatibleRead(int $beforereadIndex, int $length): bool + { + return $length != -1 && $this->readOffset < $length + $beforereadIndex; + } + + // -------------------------------------------------get/set------------------------------------------------- + public function getBuffer(): string + { + return $this->buffer; + } + + public function getWriteOffset(): int + { + return $this->writeOffset; + } + + /** + * @throws Exception + */ + public function setWriteOffset(int $writeIndex): void + { + if ($writeIndex > strlen($this->buffer)) { + throw new Exception("writeIndex[" . $writeIndex . "] out of bounds exception: readerIndex: " . $this->readOffset . + ", writerIndex: " . $this->writeOffset . "(expected: 0 <= readerIndex <= writerIndex <= capacity:" . strlen($this->buffer)); + } + $this->writeOffset = $writeIndex; + } + + public function getReadOffset(): int + { + return $this->readOffset; + } + + /** + * @throws Exception + */ + public function setReadOffset(int $readIndex): void + { + if ($readIndex > $this->writeOffset) { + throw new Exception("readIndex[" . $readIndex . "] out of bounds exception: readerIndex: " . $this->readOffset . + ", writerIndex: " . $this->writeOffset . "(expected: 0 <= readerIndex <= writerIndex <= capacity:" . strlen($this->buffer)); + } + $this->readOffset = $readIndex; + } + + public function toBytes(): string + { + return substr($this->buffer, 0, $this->writeOffset); + } + + public function isReadable(): bool + { + return $this->writeOffset > $this->readOffset; + } + + public function getCapacity(): int + { + return strlen($this->buffer) - $this->writeOffset; + } + + // -------------------------------------------------write/read------------------------------------------------- + public function writeBytes(string $bytes): void + { + // 如果容量不够则扩容一倍 + $length = strlen($bytes); + while ($length > $this->getCapacity()) { + $this->buffer = str_pad($this->buffer, strlen($this->buffer) * 2); + } + + for ($i = 0; $i < $length; $i++) { + $this->buffer[$this->writeOffset] = $bytes[$i]; + $this->writeOffset++; + } + } + + public function readBytes(int $count): string + { + $bytes = substr($this->buffer, $this->readOffset, $count); + $this->readOffset += $count; + return $bytes; + } + + public function writeByte(int $value): void + { + $this->writeBytes(pack('c', $value)); + } + + public function readByte(): int + { + return unpack('c', $this->readBytes(1))[1]; + } + + public function writeUByte(int $value): void + { + $this->writeBytes(pack('C', $value)); + } + + public function readUByte(): int + { + return unpack('c', $this->readBytes(1))[1]; + } + + public function writeBool(bool $value): void + { + $this->writeBytes(pack('C', $value ? 1 : 0)); + } + + public function readBool(): bool + { + return unpack('C', $this->readBytes(1))[1] == 1; + } + + public function writeShort(int $value): void + { + $this->writeBytes(pack('s', $value)); + } + + public function readShort(): int + { + return unpack('s', $this->readBytes(2))[1]; + } + + public function writeRawInt(int $value): void + { + $this->writeBytes(pack('i', $value)); + } + + public function readRawInt(): int + { + return unpack('i', $this->readBytes(4))[1]; + } + + public function writeInt(int $value): void + { + $this->writeLong($value); + } + + public function readInt(): int + { + return $this->readLong(); + } + + public function writeIntCount(int $value): int + { + $value = ($value << 1) ^ ($value >> 31); + if ($value >> 7 == 0) { + return 1; + } + if ($value >> 14 == 0) { + return 2; + } + if ($value >> 21 == 0) { + return 3; + } + if ($value >> 28 == 0) { + return 4; + } + return 5; + } + + public function writeLong(int $longValue): void + { + $value = ($longValue << 1) ^ ($longValue >> 63); + if ($value < 0) { + $this->writeByte($value & 0xFF | 0x80); + $this->writeByte($value >> 7 & 0xFF | 0x80); + $this->writeByte($value >> 14 & 0xFF | 0x80); + $this->writeByte($value >> 21 & 0xFF | 0x80); + $this->writeByte($value >> 28 & 0xFF | 0x80); + $this->writeByte($value >> 35 & 0xFF | 0x80); + $this->writeByte($value >> 42 & 0xFF | 0x80); + $this->writeByte($value >> 49 & 0xFF | 0x80); + $this->writeByte($value >> 56 & 0xFF); + return; + } + if ($value >> 7 == 0) { + $this->writeByte($value); + return; + } + + if ($value >> 14 == 0) { + $this->writeByte($value | 0x80); + $this->writeByte($value >> 7); + return; + } + + if ($value >> 21 == 0) { + $this->writeByte($value | 0x80); + $this->writeByte($value >> 7 | 0x80); + $this->writeByte($value >> 14); + return; + } + + if ($value >> 28 == 0) { + $this->writeByte($value | 0x80); + $this->writeByte($value >> 7 | 0x80); + $this->writeByte($value >> 14 | 0x80); + $this->writeByte($value >> 21); + return; + } + + if ($value >> 35 == 0) { + $this->writeByte($value | 0x80); + $this->writeByte($value >> 7 | 0x80); + $this->writeByte($value >> 14 | 0x80); + $this->writeByte($value >> 21 | 0x80); + $this->writeByte($value >> 28); + return; + } + + if ($value >> 42 == 0) { + $this->writeByte($value | 0x80); + $this->writeByte($value >> 7 | 0x80); + $this->writeByte($value >> 14 | 0x80); + $this->writeByte($value >> 21 | 0x80); + $this->writeByte($value >> 28 | 0x80); + $this->writeByte($value >> 35); + return; + } + + if ($value >> 49 == 0) { + $this->writeByte($value | 0x80); + $this->writeByte($value >> 7 | 0x80); + $this->writeByte($value >> 14 | 0x80); + $this->writeByte($value >> 21 | 0x80); + $this->writeByte($value >> 28 | 0x80); + $this->writeByte($value >> 35 | 0x80); + $this->writeByte($value >> 42); + return; + } + + if (($value >> 56) == 0) { + $this->writeByte($value | 0x80); + $this->writeByte($value >> 7 | 0x80); + $this->writeByte($value >> 14 | 0x80); + $this->writeByte($value >> 21 | 0x80); + $this->writeByte($value >> 28 | 0x80); + $this->writeByte($value >> 35 | 0x80); + $this->writeByte($value >> 42 | 0x80); + $this->writeByte($value >> 49); + return; + } + + $this->writeByte($value | 0x80); + $this->writeByte($value >> 7 | 0x80); + $this->writeByte($value >> 14 | 0x80); + $this->writeByte($value >> 21 | 0x80); + $this->writeByte($value >> 28 | 0x80); + $this->writeByte($value >> 35 | 0x80); + $this->writeByte($value >> 42 | 0x80); + $this->writeByte($value >> 49 | 0x80); + $this->writeByte($value >> 56); + } + + public function readLong(): int + { + $b = $this->readByte(); + $value = $b; + if ($b < 0) { + $b = $this->readByte(); + $value = $value & 0x00000000_0000007F | $b << 7; + if ($b < 0) { + $b = $this->readByte(); + $value = $value & 0x00000000_00003FFF | $b << 14; + if ($b < 0) { + $b = $this->readByte(); + $value = $value & 0x00000000_001FFFFF | $b << 21; + if ($b < 0) { + $b = $this->readByte(); + $value = $value & 0x00000000_0FFFFFFF | $b << 28; + if ($b < 0) { + $b = $this->readByte(); + $value = $value & 0x00000007_FFFFFFFF | $b << 35; + if ($b < 0) { + $b = $this->readByte(); + $value = $value & 0x000003FF_FFFFFFFF | $b << 42; + if ($b < 0) { + $b = $this->readByte(); + $value = $value & 0x0001FFFF_FFFFFFFF | $b << 49; + if ($b < 0) { + $b = $this->readByte(); + $value = $value & 0x00FFFFFF_FFFFFFFF | $b << 56; + } + } + } + } + } + } + } + } + return (($value >> 1 & 0x7FFFFFFF_FFFFFFFF) ^ -($value & 1)); + } + + public function writeFloat(float $value): void + { + $this->writeBytes(pack('f', $value)); + } + + public function readFloat(): float + { + return unpack('f', $this->readBytes(4))[1]; + } + + public function writeDouble(float $value): void + { + $this->writeBytes(pack('d', $value)); + } + + public function readDouble(): float + { + return unpack('d', $this->readBytes(8))[1]; + } + + public function writeString(string $value): void + { + $this->writeInt(strlen($value)); + $this->writeBytes($value); + } + + public function readString(): string + { + $length = $this->readInt(); + return $this->readBytes($length); + } + + public function writePacket(mixed $value, int $protocolId): void + { + $protocolRegistration = ProtocolManager::getProtocol($protocolId); + $protocolRegistration->write($this, $value); + } + + public function readPacket(int $protocolId): mixed + { + $protocolRegistration = ProtocolManager::getProtocol($protocolId); + return $protocolRegistration->read($this); + } + + public function writeBooleanArray(array $array): void + { + if (empty($array)) { + $this->writeInt(0); + } else { + $this->writeInt(count($array)); + $length = count($array); + for ($index = 0; $index < $length; $index++) { + $this->writeBool($array[$index]); + } + } + } + + public function readBooleanArray(): array + { + $size = $this->readInt(); + $array = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + array_push($array, $this->readBool()); + } + } + return $array; + } + + public function writeByteArray(array $array): void + { + if (empty($array)) { + $this->writeInt(0); + } else { + $this->writeInt(count($array)); + $length = count($array); + for ($index = 0; $index < $length; $index++) { + $this->writeByte($array[$index]); + } + } + } + + public function readByteArray(): array + { + $size = $this->readInt(); + $array = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + array_push($array, $this->readByte()); + } + } + return $array; + } + + public function writeShortArray(array $array): void + { + if (empty($array)) { + $this->writeInt(0); + } else { + $this->writeInt(count($array)); + $length = count($array); + for ($index = 0; $index < $length; $index++) { + $this->writeShort($array[$index]); + } + } + } + + public function readShortArray(): array + { + $size = $this->readInt(); + $array = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + array_push($array, $this->readShort()); + } + } + return $array; + } + + public function writeIntArray(array $array): void + { + if (empty($array)) { + $this->writeInt(0); + } else { + $this->writeInt(count($array)); + $length = count($array); + for ($index = 0; $index < $length; $index++) { + $this->writeInt($array[$index]); + } + } + } + + public function readIntArray(): array + { + $size = $this->readInt(); + $array = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + array_push($array, $this->readInt()); + } + } + return $array; + } + + + public function writeLongArray(array $array): void + { + if (empty($array)) { + $this->writeInt(0); + } else { + $this->writeInt(count($array)); + $length = count($array); + for ($index = 0; $index < $length; $index++) { + $this->writeLong($array[$index]); + } + } + } + + public function readLongArray(): array + { + $size = $this->readInt(); + $array = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + array_push($array, $this->readLong()); + } + } + return $array; + } + + + public function writeFloatArray(array $array): void + { + if (empty($array)) { + $this->writeInt(0); + } else { + $this->writeInt(count($array)); + $length = count($array); + for ($index = 0; $index < $length; $index++) { + $this->writeFloat($array[$index]); + } + } + } + + public function readFloatArray(): array + { + $size = $this->readInt(); + $array = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + array_push($array, $this->readFloat()); + } + } + return $array; + } + + + public function writeDoubleArray(array $array): void + { + if (empty($array)) { + $this->writeInt(0); + } else { + $this->writeInt(count($array)); + $length = count($array); + for ($index = 0; $index < $length; $index++) { + $this->writeDouble($array[$index]); + } + } + } + + public function readDoubleArray(): array + { + $size = $this->readInt(); + $array = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + array_push($array, $this->readDouble()); + } + } + return $array; + } + + + public function writeStringArray(array $array): void + { + if (empty($array)) { + $this->writeInt(0); + } else { + $this->writeInt(count($array)); + $length = count($array); + for ($index = 0; $index < $length; $index++) { + $this->writeString($array[$index]); + } + } + } + + public function readStringArray(): array + { + $size = $this->readInt(); + $array = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + array_push($array, $this->readString()); + } + } + return $array; + } + + public function writePacketArray(array $array, int $protocolId): void + { + if (empty($array)) { + $this->writeInt(0); + } else { + $this->writeInt(count($array)); + $length = count($array); + for ($index = 0; $index < $length; $index++) { + $this->writePacket($array[$index], $protocolId); + } + } + } + + public function readPacketArray(int $protocolId): array + { + $size = $this->readInt(); + $array = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + array_push($array, $this->readPacket($protocolId)); + } + } + return $array; + } + + public function writeIntIntMap(array $map): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeInt($key); + $this->writeInt($value); + } + } + } + + public function readIntIntMap(): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readInt(); + $value = $this->readInt(); + $map[$key] = $value; + } + } + return $map; + } + + public function writeIntLongMap(array $map): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeInt($key); + $this->writeLong($value); + } + } + } + + public function readIntLongMap(): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readInt(); + $value = $this->readLong(); + $map[$key] = $value; + } + } + return $map; + } + + public function writeIntStringMap(array $map): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeInt($key); + $this->writeString($value); + } + } + } + + public function readIntStringMap(): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readInt(); + $value = $this->readString(); + $map[$key] = $value; + } + } + return $map; + } + + public function writeIntPacketMap(array $map, int $protocolId): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeInt($key); + $this->writePacket($value, $protocolId); + } + } + } + + public function readIntPacketMap(int $protocolId): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readInt(); + $value = $this->readPacket($protocolId); + $map[$key] = $value; + } + } + return $map; + } + + public function writeLongIntMap(array $map): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeLong($key); + $this->writeInt($value); + } + } + } + + public function readLongIntMap(): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readLong(); + $value = $this->readInt(); + $map[$key] = $value; + } + } + return $map; + } + + public function writeLongLongMap(array $map): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeLong($key); + $this->writeLong($value); + } + } + } + + public function readLongLongMap(): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readLong(); + $value = $this->readLong(); + $map[$key] = $value; + } + } + return $map; + } + + public function writeLongStringMap(array $map): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeLong($key); + $this->writeString($value); + } + } + } + + public function readLongStringMap(): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readLong(); + $value = $this->readString(); + $map[$key] = $value; + } + } + return $map; + } + + public function writeLongPacketMap(array $map, int $protocolId): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeLong($key); + $this->writePacket($value, $protocolId); + } + } + } + + public function readLongPacketMap(int $protocolId): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readLong(); + $value = $this->readPacket($protocolId); + $map[$key] = $value; + } + } + return $map; + } + + public function writeStringIntMap(array $map): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeString($key); + $this->writeInt($value); + } + } + } + + public function readStringIntMap(): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readString(); + $value = $this->readInt(); + $map[$key] = $value; + } + } + return $map; + } + + public function writeStringLongMap(array $map): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeString($key); + $this->writeLong($value); + } + } + } + + public function readStringLongMap(): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readString(); + $value = $this->readLong(); + $map[$key] = $value; + } + } + return $map; + } + + public function writeStringStringMap(array $map): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeString($key); + $this->writeString($value); + } + } + } + + public function readStringStringMap(): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readString(); + $value = $this->readString(); + $map[$key] = $value; + } + } + return $map; + } + + public function writeStringPacketMap(array $map, int $protocolId): void + { + if (empty($map)) { + $this->writeInt(0); + } else { + $this->writeInt(count($map)); + foreach ($map as $key => $value) { + $this->writeString($key); + $this->writePacket($value, $protocolId); + } + } + } + + public function readStringPacketMap(int $protocolId): array + { + $size = $this->readInt(); + $map = array(); + if ($size > 0) { + for ($index = 0; $index < $size; $index++) { + $key = $this->readString(); + $value = $this->readPacket($protocolId); + $map[$key] = $value; + } + } + return $map; + } +} \ No newline at end of file diff --git a/protocol/src/main/resources/php/IProtocolRegistration.php b/protocol/src/main/resources/php/IProtocolRegistration.php new file mode 100644 index 00000000..983c8648 --- /dev/null +++ b/protocol/src/main/resources/php/IProtocolRegistration.php @@ -0,0 +1,13 @@ +writeShort($protocolId); + // write packet + self::getProtocol($protocolId)->write($buffer, $packet); + + } + + public static function read(ByteBuffer $buffer): mixed + { + $protocolId = $buffer->readShort(); + return self::getProtocol($protocolId)->read($buffer); + } +} \ No newline at end of file diff --git a/protocol/src/main/resources/php/ProtocolRegistrationTemplate.php b/protocol/src/main/resources/php/ProtocolRegistrationTemplate.php new file mode 100644 index 00000000..f711a3ee --- /dev/null +++ b/protocol/src/main/resources/php/ProtocolRegistrationTemplate.php @@ -0,0 +1,31 @@ +class ${protocol_name}Registration implements IProtocolRegistration { + public function protocolId(): int + { + return ${protocol_id}; + } + + public function write(ByteBuffer $buffer, mixed $packet): void + { + if ($packet == null) + { + $buffer->writeInt(0); + return; + } + ${protocol_write_serialization} + } + + public function read(ByteBuffer $buffer): mixed + { + $length = $buffer->readInt(); + $packet = new ${protocol_name}(); + if ($length == 0) { + return $packet; + } + $beforeReadIndex = $buffer->readOffset(); + ${protocol_read_deserialization} + if ($length > 0) { + $buffer->setReadOffset($beforeReadIndex + $length); + } + return $packet; + } +} \ No newline at end of file diff --git a/protocol/src/main/resources/php/ProtocolTemplate.php b/protocol/src/main/resources/php/ProtocolTemplate.php new file mode 100644 index 00000000..28f919a7 --- /dev/null +++ b/protocol/src/main/resources/php/ProtocolTemplate.php @@ -0,0 +1,9 @@ +