perf[protocol]: 使用模板生成协议

This commit is contained in:
jaysunxiao
2022-05-18 18:35:12 +08:00
parent 5eb2530eae
commit d4ded2dd19
15 changed files with 99 additions and 144 deletions
@@ -128,7 +128,9 @@ public abstract class GenerateProtocolFile {
if (generateLanguages.contains(CodeLanguage.Lua)) {
GenerateLuaUtils.init(generateOperation);
GenerateLuaUtils.createProtocolManager(allSortedGenerateProtocols);
allSortedGenerateProtocols.forEach(it -> GenerateLuaUtils.createLuaProtocolFile((ProtocolRegistration) it));
for (var protocolRegistration : allSortedGenerateProtocols) {
GenerateLuaUtils.createLuaProtocolFile((ProtocolRegistration) protocolRegistration);
}
}
// 生成GdScript协议
@@ -17,9 +17,9 @@ import com.zfoo.protocol.generate.GenerateOperation;
import com.zfoo.protocol.generate.GenerateProtocolDocument;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.generate.GenerateProtocolPath;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.reflect.*;
import com.zfoo.protocol.util.ClassUtils;
import com.zfoo.protocol.util.FileUtils;
@@ -28,8 +28,10 @@ import com.zfoo.protocol.util.StringUtils;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.zfoo.protocol.util.FileUtils.LS;
@@ -79,7 +81,6 @@ public abstract class GenerateLuaUtils {
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
var list = List.of("lua/Buffer/ByteBuffer.lua", "lua/Buffer/Long.lua");
for (var fileName : list) {
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
var createFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, StringUtils.substringAfterFirst(fileName, "lua/")));
@@ -87,110 +88,71 @@ public abstract class GenerateLuaUtils {
}
// 生成Protocol.lua文件
var luaBuilder = new StringBuilder();
var protocolManagerTemplate = StringUtils.bytesToString(IOUtils.toByteArray(ClassUtils.getFileFromClassPath("lua/ProtocolManagerTemplate.lua")));
var fieldBuilder = new StringBuilder();
var protocolBuilder = new StringBuilder();
for (var protocol : protocolList) {
var protocolId = protocol.protocolId();
var name = protocol.protocolConstructor().getDeclaringClass().getSimpleName();
var path = GenerateProtocolPath.getCapitalizeProtocolPath(protocolId);
if (StringUtils.isBlank(path)) {
fieldBuilder.append(TAB).append(StringUtils.format("local {} = require(\"LuaProtocol.{}\")", name, name)).append(LS);
} else {
fieldBuilder.append(TAB).append(StringUtils.format("local {} = require(\"LuaProtocol.{}.{}\")"
, name, path.replaceAll(StringUtils.SLASH, StringUtils.PERIOD), name)).append(LS);
}
var protocolManagerStr = StringUtils.bytesToString(IOUtils.toByteArray(ClassUtils.getFileFromClassPath("lua/ProtocolManager.lua")));
luaBuilder.append(protocolManagerStr);
luaBuilder.append("function initProtocol()").append(LS);
protocolList.stream()
.filter(it -> Objects.nonNull(it))
.forEach(it -> {
var name = it.protocolConstructor().getDeclaringClass().getSimpleName();
var path = GenerateProtocolPath.getCapitalizeProtocolPath(it.protocolId());
if (StringUtils.isBlank(path)) {
luaBuilder.append(TAB).append(StringUtils.format("local {} = require(\"LuaProtocol.{}\")", name, name)).append(LS);
} else {
luaBuilder.append(TAB).append(StringUtils.format("local {} = require(\"LuaProtocol.{}.{}\")"
, name, path.replaceAll(StringUtils.SLASH, StringUtils.PERIOD), name)).append(LS);
}
});
protocolList.stream().filter(it -> Objects.nonNull(it))
.forEach(it -> luaBuilder.append(TAB).append(StringUtils.format("protocols[{}] = {}", it.protocolId(), it.protocolConstructor().getDeclaringClass().getSimpleName())).append(LS));
luaBuilder.append("end").append(LS + LS);
luaBuilder.append("ProtocolManager.initProtocol = initProtocol").append(LS);
luaBuilder.append("return ProtocolManager").append(LS);
FileUtils.writeStringToFile(new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.lua")), luaBuilder.toString());
protocolBuilder.append(TAB).append(StringUtils.format("protocols[{}] = {}", protocolId, name)).append(LS);
}
protocolManagerTemplate = StringUtils.format(protocolManagerTemplate, "{}", "{}", fieldBuilder.toString().trim(), protocolBuilder.toString().trim());
FileUtils.writeStringToFile(new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.lua")), protocolManagerTemplate);
}
public static void createLuaProtocolFile(ProtocolRegistration registration) {
public static void createLuaProtocolFile(ProtocolRegistration registration) throws IOException {
// 初始化index
GenerateProtocolFile.index.set(0);
var protocolId = registration.protocolId();
var registrationConstructor = registration.getConstructor();
var fieldRegistrations = registration.getFieldRegistrations();
var protocolClazzName = registrationConstructor.getDeclaringClass().getSimpleName();
var protocolTemplate = StringUtils.bytesToString(IOUtils.toByteArray(ClassUtils.getFileFromClassPath("lua/ProtocolTemplate.lua")));
var luaBuilder = new StringBuilder();
// document
luaBuilder.append(documentTitle(registration));
// new object
luaBuilder.append(newFunction(registration));
// protocolId method
luaBuilder.append(protocolIdFunction(registration));
// writeObject method
luaBuilder.append(writePacket(registration));
// readObject method
luaBuilder.append(readPacket(registration)).append(LS);
luaBuilder.append(StringUtils.format("return {}", protocolClazzName)).append(LS);
var docTitle = docTitle(registration);
var valueOfMethod = valueOfMethod(registration);
var writePacket = writePacket(registration);
var readPacket = readPacket(registration);
protocolTemplate = StringUtils.format(protocolTemplate, docTitle, protocolClazzName, "{}", protocolClazzName
, valueOfMethod.getKey().trim(), valueOfMethod.getValue().trim(), protocolClazzName, protocolId
, protocolClazzName, writePacket.trim(), protocolClazzName, protocolClazzName, readPacket.trim(), protocolClazzName);
var protocolOutputPath = StringUtils.format("{}/{}/{}.lua"
, protocolOutputRootPath
, GenerateProtocolPath.getCapitalizeProtocolPath(protocolId)
, protocolClazzName);
FileUtils.writeStringToFile(new File(protocolOutputPath), luaBuilder.toString());
, protocolOutputRootPath, GenerateProtocolPath.getCapitalizeProtocolPath(protocolId), protocolClazzName);
FileUtils.writeStringToFile(new File(protocolOutputPath), protocolTemplate);
}
private static String documentTitle(ProtocolRegistration registration) {
private static String docTitle(ProtocolRegistration registration) {
var protocolId = registration.protocolId();
var registrationConstructor = registration.getConstructor();
var fieldRegistrations = registration.getFieldRegistrations();
var luaBuilder = new StringBuilder();
var protocolDocument = GenerateProtocolDocument.getProtocolDocument(protocolId);
var docTitle = protocolDocument.getKey();
if (StringUtils.isNotBlank(docTitle)) {
Arrays.stream(docTitle.split(LS)).forEach(it -> luaBuilder.append(docToLuaDoc(it)).append(LS));
luaBuilder.append(LS);
}
return luaBuilder.toString();
}
private static String newFunction(ProtocolRegistration registration) {
short protocolId = registration.getId();
private static Pair<String, String> valueOfMethod(ProtocolRegistration registration) {
var protocolId = registration.getId();
var fields = registration.getFields();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var protocolDocument = GenerateProtocolDocument.getProtocolDocument(protocolId);
var docFieldMap = protocolDocument.getValue();
var valueOfParams = StringUtils.joinWith(", ", Arrays.stream(fields).map(it -> it.getName()).collect(Collectors.toList()).toArray());
var luaBuilder = new StringBuilder();
luaBuilder.append(StringUtils.format("local {} = {}", protocolClazzName)).append(LS + LS);
luaBuilder.append(StringUtils.format("function {}:new(", protocolClazzName));
luaBuilder.append(StringUtils.joinWith(", ", Arrays.stream(fields).map(it -> it.getName()).collect(Collectors.toList()).toArray()))
.append(")")
.append(LS);
luaBuilder.append(TAB).append("local obj = {").append(LS);
for (int i = 0; i < fields.length; i++) {
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var propertyName = field.getName();
@@ -201,92 +163,42 @@ public abstract class GenerateLuaUtils {
}
if (i == fields.length - 1) {
luaBuilder.append(TAB + TAB)
.append(StringUtils.format("{} = {}", propertyName, propertyName));
luaBuilder.append(TAB + TAB).append(StringUtils.format("{} = {}", propertyName, propertyName));
} else {
luaBuilder.append(TAB + TAB)
.append(StringUtils.format("{} = {},", propertyName, propertyName));
luaBuilder.append(TAB + TAB).append(StringUtils.format("{} = {},", propertyName, propertyName));
}
// 生成类型的注释
luaBuilder.append(" -- ").append(field.getGenericType().getTypeName()).append(LS);
}
luaBuilder.append(TAB).append("}").append(LS);
luaBuilder.append(TAB).append("setmetatable(obj, self)").append(LS);
luaBuilder.append(TAB).append("self.__index = self").append(LS);
luaBuilder.append(TAB).append("return obj").append(LS);
luaBuilder.append("end").append(LS).append(LS);
return luaBuilder.toString();
return new Pair<>(valueOfParams, luaBuilder.toString());
}
private static String protocolIdFunction(ProtocolRegistration registration) {
short protocolId = registration.getId();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var luaBuilder = new StringBuilder();
luaBuilder.append(StringUtils.format("function {}:protocolId()", protocolClazzName)).append(LS);
luaBuilder.append(TAB).append(StringUtils.format("return {}", protocolId)).append(LS);
luaBuilder.append("end").append(LS).append(LS);
return luaBuilder.toString();
}
private static String writePacket(ProtocolRegistration registration) {
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var luaBuilder = new StringBuilder();
luaBuilder.append(StringUtils.format("function {}:write(buffer, packet)", protocolClazzName)).append(LS);
luaBuilder.append(TAB).append("if buffer:writePacketFlag(packet) then").append(LS);
luaBuilder.append(TAB + TAB).append("return").append(LS);
luaBuilder.append(TAB).append("end").append(LS);
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
luaSerializer(fieldRegistration.serializer()).writeObject(luaBuilder, "packet." + field.getName(), 1, field, fieldRegistration);
}
luaBuilder.append("end").append(LS).append(LS);
return luaBuilder.toString();
}
private static String readPacket(ProtocolRegistration registration) {
Field[] fields = registration.getFields();
IFieldRegistration[] fieldRegistrations = registration.getFieldRegistrations();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var jsBuilder = new StringBuilder();
jsBuilder.append(StringUtils.format("function {}:read(buffer)", protocolClazzName)).append(LS);
jsBuilder.append(TAB).append("if not(buffer:readBoolean()) then").append(LS);
jsBuilder.append(TAB + TAB).append("return nil").append(LS);
jsBuilder.append(TAB).append("end").append(LS);
jsBuilder.append(TAB).append(StringUtils.format("local packet = {}:new()", protocolClazzName)).append(LS);
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var luaBuilder = new StringBuilder();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
IFieldRegistration fieldRegistration = fieldRegistrations[i];
String readObject = luaSerializer(fieldRegistration.serializer()).readObject(jsBuilder, 1, field, fieldRegistration);
jsBuilder.append(TAB).append(StringUtils.format("packet.{} = {}", field.getName(), readObject)).append(LS);
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
var readObject = luaSerializer(fieldRegistration.serializer()).readObject(luaBuilder, 1, field, fieldRegistration);
luaBuilder.append(TAB).append(StringUtils.format("packet.{} = {}", field.getName(), readObject)).append(LS);
}
jsBuilder.append(TAB).append("return packet").append(LS);
jsBuilder.append("end").append(LS);
return jsBuilder.toString();
return luaBuilder.toString();
}
private static String docToLuaDoc(String doc) {
return doc.replaceFirst("//", "--");
}
@@ -32,3 +32,10 @@ function ProtocolManager.read(buffer)
return ProtocolManager.getProtocol(protocolId):read(buffer)
end
function initProtocol()
{}
{}
end
ProtocolManager.initProtocol = initProtocol
return ProtocolManager
@@ -0,0 +1,33 @@
{}
local {} = {}
function {}:new({})
local obj = {
{}
}
setmetatable(obj, self)
self.__index = self
return obj
end
function {}:protocolId()
return {}
end
function {}:write(buffer, packet)
if buffer:writePacketFlag(packet) then
return
end
{}
end
function {}:read(buffer)
if not(buffer:readBoolean()) then
return nil
end
local packet = {}:new()
{}
return packet
end
return {}
+2 -2
View File
@@ -13,7 +13,7 @@ namespace csharp
ProtocolManager.InitProtocol();
// 获取复杂对象的字节流
var complexObjectBytes = File.ReadAllBytes("C:\\zfoo\\protocol\\src\\test\\resources\\ComplexObject.bytes");
var complexObjectBytes = File.ReadAllBytes("../resources/ComplexObject.bytes");
var buffer = ByteBuffer.ValueOf();
buffer.WriteBytes(complexObjectBytes);
var packet = ProtocolManager.Read(buffer);
@@ -187,4 +187,4 @@ namespace csharp
throw new Exception("a is not equals b");
}
}
}
}
@@ -1,6 +1,7 @@
using System.IO;
using System.Text;
using NUnit.Framework;
using Spring.Util;
using XLua;
namespace Test.Editor.LuaTest
@@ -18,7 +19,7 @@ namespace Test.Editor.LuaTest
var luaEnv = new LuaEnv();
var luaDebugBuilder = new StringBuilder();
// Rider的断点调试
// luaDebugBuilder.Append("package.cpath = package.cpath .. ';C:/Users/jm/AppData/Roaming/JetBrains/Rider2020.1/plugins/intellij-emmylua/classes/debugger/emmy/windows/x64/?.dll'").Append(FileUtils.LS);
// luaDebugBuilder.Append("package.cpath = package.cpath .. ';C:/Users/jaysunxiao/AppData/Roaming/JetBrains/Rider2021.1/plugins/EmmyLua/classes/debugger/emmy/windows/x64/?.dll'").Append(FileUtils.LS);
// luaDebugBuilder.Append("local dbg = require('emmy_core')").Append(FileUtils.LS);
// luaDebugBuilder.Append("dbg.tcpListen('localhost', 9966)").Append(FileUtils.LS);
// luaDebugBuilder.Append("dbg.waitIDE()").Append(FileUtils.LS);
@@ -27,8 +28,8 @@ namespace Test.Editor.LuaTest
luaEnv.AddLoader(CustomLoader);
var luaProtocolTestStr = File.ReadAllText(TEST_PATH + "LuaProtocolTest.lua");
luaEnv.DoString(luaProtocolTestStr, "LuaProtocolTest");
var luaProtocolTestStr = File.ReadAllText(TEST_PATH + "main.lua");
luaEnv.DoString(luaProtocolTestStr, "main");
LuaFunction byteBufferTestFunction = luaEnv.Global.Get<LuaFunction>("byteBufferTest");
byteBufferTestFunction.Call();
@@ -44,4 +45,4 @@ namespace Test.Editor.LuaTest
return File.ReadAllBytes(TEST_PATH + filepath);
}
}
}
}