init project

This commit is contained in:
jaysunxiao
2021-05-20 14:17:21 +08:00
parent b7f28da485
commit bce060a28e
573 changed files with 84513 additions and 0 deletions
@@ -0,0 +1,31 @@
/*
* 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;
/**
* 所有协议类都必须实现这个接口
*
* @author jaysunxiao
* @version 3.0
*/
public interface IPacket {
/**
* 这个类的协议号
*
* @return 协议号Id
*/
short protocolId();
}
@@ -0,0 +1,574 @@
/*
* 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;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.collection.CollectionUtils;
import com.zfoo.protocol.exception.RunException;
import com.zfoo.protocol.exception.UnknownException;
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.registration.EnhanceUtils;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.registration.ProtocolModule;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.registration.field.*;
import com.zfoo.protocol.serializer.*;
import com.zfoo.protocol.serializer.cs.GenerateCsUtils;
import com.zfoo.protocol.serializer.js.GenerateJsUtils;
import com.zfoo.protocol.serializer.lua.GenerateLuaUtils;
import com.zfoo.protocol.util.AssertionUtils;
import com.zfoo.protocol.util.ReflectionUtils;
import com.zfoo.protocol.util.StringUtils;
import com.zfoo.protocol.xml.XmlProtocols;
import io.netty.buffer.ByteBuf;
import javassist.CannotCompileException;
import javassist.NotFoundException;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ProtocolManager {
/**
* 包体的头部的长度,一个int字节长度
*/
public static final int PROTOCOL_HEAD_LENGTH = 4;
public static final String PROTOCOL_ID = "PROTOCOL_ID";
public static final short MAX_PROTOCOL_NUM = Short.MAX_VALUE;
public static final byte MAX_MODULE_NUM = Byte.MAX_VALUE;
private static final Comparator<Field> PACKET_FIELD_COMPARATOR = (a, b) -> a.getName().compareTo(b.getName());
private static final IProtocolRegistration[] protocols = new IProtocolRegistration[MAX_PROTOCOL_NUM];
private static final ProtocolModule[] modules = new ProtocolModule[MAX_MODULE_NUM];
// 临时变量,启动完成就会销毁,协议名称保留字符,即协议的名称不能用以下名称命名
private static Set<String> tempProtocolReserved = Set.of("Buffer", "ByteBuf", "ByteBuffer", "LittleEndianByteBuffer", "NormalByteBuffer"
, "IPacket", "IProtocolRegistration", "ProtocolManager", "IFieldRegistration"
, "ByteBufUtils", "ArrayUtils", "CollectionUtils"
, "Boolean", "Byte", "Short", "Integer", "Long", "Float", "Double", "String", "Character", "Object");
// 临时变量,启动完成就会销毁,是一个基本类型序列化器
private static Map<Class<?>, ISerializer> tempBaseSerializerMap = new HashMap<>();
// 临时变量,启动完成就会销毁,协议下包含的子协议,只包含一层子协议
private static Map<Short, Set<Short>> tempSubProtocolIdMap = new HashMap<>();
static {
// 初始化默认协议模块
modules[0] = ProtocolModule.DEFAULT_PROTOCOL_MODULE;
// 初始化基础类型序列化器
tempBaseSerializerMap.put(boolean.class, BooleanSerializer.getInstance());
tempBaseSerializerMap.put(Boolean.class, BooleanSerializer.getInstance());
tempBaseSerializerMap.put(byte.class, ByteSerializer.getInstance());
tempBaseSerializerMap.put(Byte.class, ByteSerializer.getInstance());
tempBaseSerializerMap.put(short.class, ShortSerializer.getInstance());
tempBaseSerializerMap.put(Short.class, ShortSerializer.getInstance());
tempBaseSerializerMap.put(int.class, IntSerializer.getInstance());
tempBaseSerializerMap.put(Integer.class, IntSerializer.getInstance());
tempBaseSerializerMap.put(long.class, LongSerializer.getInstance());
tempBaseSerializerMap.put(Long.class, LongSerializer.getInstance());
tempBaseSerializerMap.put(float.class, FloatSerializer.getInstance());
tempBaseSerializerMap.put(Float.class, FloatSerializer.getInstance());
tempBaseSerializerMap.put(double.class, DoubleSerializer.getInstance());
tempBaseSerializerMap.put(Double.class, DoubleSerializer.getInstance());
tempBaseSerializerMap.put(char.class, CharSerializer.getInstance());
tempBaseSerializerMap.put(Character.class, CharSerializer.getInstance());
tempBaseSerializerMap.put(String.class, StringSerializer.getInstance());
}
public static void write(ByteBuf buffer, IPacket packet) {
var protocolId = packet.protocolId();
// 写入协议号
ByteBufUtils.writeShort(buffer, protocolId);
// 写入包体
protocols[protocolId].write(buffer, packet);
}
public static IPacket read(ByteBuf buffer) {
return (IPacket) protocols[ByteBufUtils.readShort(buffer)].read(buffer);
}
public static IProtocolRegistration getProtocol(short id) {
var protocol = protocols[id];
if (protocol == null) {
throw new RunException("[protocolId:{}]协议不存在", id);
}
return protocol;
}
public static ProtocolModule moduleByProtocolId(short id) {
return modules[protocols[id].module()];
}
public static ProtocolModule moduleByModuleId(byte moduleId) {
var module = modules[moduleId];
AssertionUtils.notNull(module, "[moduleId:{}]不存在", moduleId);
return module;
}
public static ProtocolModule moduleByModuleName(String name) {
var moduleOptional = Arrays.stream(modules)
.filter(it -> Objects.nonNull(it))
.filter(it -> it.getName().equals(name))
.findFirst();
if (moduleOptional.isEmpty()) {
return null;
}
return moduleOptional.get();
}
public static synchronized void initProtocol(Set<Class<?>> protocolClassSet) {
initProtocol(protocolClassSet, GenerateOperation.NO_OPERATION);
}
public static synchronized void initProtocol(Set<Class<?>> protocolClassSet, GenerateOperation generateOperation) {
AssertionUtils.notNull(tempSubProtocolIdMap, "[{}]已经初始完成只能parseProtocol一次请不要重复初始化", ProtocolManager.class.getSimpleName());
try {
for (var protocolClass : protocolClassSet) {
try {
var registration = parseProtocolRegistration(protocolClass, ProtocolModule.DEFAULT_PROTOCOL_MODULE);
// 注册协议
protocols[registration.protocolId()] = registration;
} catch (Exception e) {
throw new RuntimeException(StringUtils.format("解析协议[class:{}]异常", protocolClass), e);
}
}
enhanceProtocolBefore(generateOperation);
// 通过指定类注册的协议,全部使用字节码增强
enhanceProtocolRegistration(Arrays.stream(protocols).filter(it -> Objects.nonNull(it)).collect(Collectors.toList()));
enhanceProtocolAfter();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static synchronized void initProtocol(XmlProtocols xmlProtocols, GenerateOperation generateOperation) {
AssertionUtils.notNull(tempSubProtocolIdMap, "[{}]已经初始完成只能parseProtocol一次请不要重复初始化", ProtocolManager.class.getSimpleName());
try {
var enhanceList = new ArrayList<IProtocolRegistration>();
for (var moduleDefinition : xmlProtocols.getModules()) {
var module = new ProtocolModule(moduleDefinition.getId(), moduleDefinition.getName(), moduleDefinition.getVersion());
AssertionUtils.isTrue(module.getId() > 0, "[module:{}] [id:{}] 模块必须大于等于1", module.getName(), module.getId());
AssertionUtils.isNull(modules[module.getId()], "duplicate [module:{}] [id:{}] Exception!", module.getName(), module.getId());
AssertionUtils.notNull(moduleDefinition.getProtocols(), "[module:{}] does not have any protocols", module.getName());
modules[module.getId()] = module;
for (var protocolDefinition : moduleDefinition.getProtocols()) {
var id = protocolDefinition.getId();
var location = protocolDefinition.getLocation();
var clazz = Class.forName(location);
AssertionUtils.isTrue(id >= moduleDefinition.getMinId(), "模块[{}]中的协议[{}]的协议号必须大于或者等于[{}]", moduleDefinition.getName(), clazz.getSimpleName(), moduleDefinition.getMinId());
AssertionUtils.isTrue(id < moduleDefinition.getMaxId(), "模块[{}]中的协议[{}]的协议号必须小于[{}]", moduleDefinition.getName(), clazz.getSimpleName(), moduleDefinition.getMaxId());
AssertionUtils.isNull(protocols[id], "duplicate definition [id:{}] Exception!", id);
var packet = (IPacket) ReflectionUtils.newInstance(clazz);
// 协议号是否和id是否相等
AssertionUtils.isTrue(packet.protocolId() == id, "[class:{}]协议序列号[{}]和协议文件里的协议序列号不相等", clazz.getCanonicalName(), PROTOCOL_ID);
try {
var registration = parseProtocolRegistration(clazz, module);
if (protocolDefinition.isEnhance()) {
enhanceList.add(registration);
}
// 注册协议
protocols[id] = registration;
} catch (Exception e) {
throw new UnknownException(e, "解析协议[id:{}][class:{}]异常", id, clazz);
}
}
}
enhanceProtocolBefore(generateOperation);
enhanceProtocolRegistration(enhanceList);
enhanceProtocolAfter();
} catch (Exception e) {
throw new UnknownException(e);
}
}
private static void enhanceProtocolRegistration(List<IProtocolRegistration> enhanceList) throws NoSuchMethodException, IllegalAccessException, InstantiationException, CannotCompileException, NotFoundException, InvocationTargetException, NoSuchFieldException {
// 字节码增强
for (var registration : enhanceList) {
protocols[registration.protocolId()] = EnhanceUtils.createProtocolRegistration((ProtocolRegistration) registration);
}
// 字节码增强过后,初始化各个子协议成员变量
for (var registration : enhanceList) {
var enhanceProtocolRegistration = protocols[registration.protocolId()];
var subProtocolIds = getAllSubProtocolIds(registration.protocolId());
for (var subProtocolId : subProtocolIds) {
var protocolRegistrationField = enhanceProtocolRegistration.getClass().getDeclaredField(EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(subProtocolId));
ReflectionUtils.makeAccessible(protocolRegistrationField);
ReflectionUtils.setField(protocolRegistrationField, enhanceProtocolRegistration, protocols[subProtocolId]);
}
}
}
private static void enhanceProtocolBefore(GenerateOperation generateOperation) throws IOException {
// 检查协议格式
checkAllProtocolClass();
// 检查模块格式
checkAllModules();
// 生成协议
GenerateProtocolFile.generate(protocols, generateOperation);
}
private static void enhanceProtocolAfter() {
tempSubProtocolIdMap.clear();
tempSubProtocolIdMap = null;
tempProtocolReserved = null;
tempBaseSerializerMap.clear();
tempBaseSerializerMap = null;
GenerateProtocolDocument.clear();
GenerateProtocolPath.clear();
GenerateCsUtils.clear();
GenerateJsUtils.clear();
GenerateLuaUtils.clear();
GenerateUtils.clear();
EnhanceUtils.clear();
}
private static short checkProtocol(Class<?> clazz) throws IllegalAccessException, InvocationTargetException, InstantiationException {
// 是否为一个简单的javabean
AssertionUtils.isTrue(clazz.getSuperclass().equals(Object.class), "[class:{}]不是简单的javabean不能继承别的类", clazz.getCanonicalName());
// 是否实现了IPacket接口
AssertionUtils.isTrue(IPacket.class.isAssignableFrom(clazz), "[class:{}]没有实现接口[IPacket:{}]", clazz.getCanonicalName(), IPacket.class.getCanonicalName());
// 不能是泛型类
AssertionUtils.isTrue(CollectionUtils.isEmpty(clazz.getTypeParameters()), "[class:{}]不能是泛型类", clazz.getCanonicalName());
Field protocolIdField;
try {
protocolIdField = clazz.getDeclaredField(PROTOCOL_ID);
} catch (NoSuchFieldException e) {
throw new UnknownException(e, "[class:{}]没有[{}]协议序列号", clazz.getCanonicalName(), PROTOCOL_ID);
}
// 是否被public修饰
AssertionUtils.isTrue(Modifier.isPublic(protocolIdField.getModifiers()), "[class:{}]协议序列号[{}]没有被public修饰", clazz.getCanonicalName(), PROTOCOL_ID);
// 是否被static修饰
AssertionUtils.isTrue(Modifier.isStatic(protocolIdField.getModifiers()), "[class:{}]协议序列号[{}]没有被static修饰", clazz.getCanonicalName(), PROTOCOL_ID);
// 是否被final修饰
AssertionUtils.isTrue(Modifier.isFinal(protocolIdField.getModifiers()), "[class:{}]协议序列号[{}]没有被final修饰", clazz.getCanonicalName(), PROTOCOL_ID);
// 是否被transient修饰
AssertionUtils.isTrue(Modifier.isTransient(protocolIdField.getModifiers()), "[class:{}]协议序列号[{}]没有被transient修饰", clazz.getCanonicalName(), PROTOCOL_ID);
// 命名只能包含字母,数字,下划线
AssertionUtils.isTrue(clazz.getSimpleName().matches("[a-zA-Z0-9_]*"), "[class:{}]的命名只能包含字母数字下划线", clazz.getCanonicalName(), PROTOCOL_ID);
// 必须要有一个空的构造器
Constructor<?> constructor;
try {
constructor = clazz.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
throw new UnknownException(e, "[class:{}]协议序列号[{}]必须有一个空的构造器", clazz.getCanonicalName(), PROTOCOL_ID);
}
ReflectionUtils.makeAccessible(protocolIdField);
IPacket packet = (IPacket) constructor.newInstance();
// 验证protocol()方法的返回是否和PROTOCOL_ID相等
AssertionUtils.isTrue(Short.valueOf(packet.protocolId()).equals(protocolIdField.get(null)), "[class:{}]的protocolId返回的值和协议号的静态变量[{}]不相等", clazz.getCanonicalName(), PROTOCOL_ID);
return packet.protocolId();
}
public static short getProtocolIdByClass(Class<?> clazz) {
var protocolIdField = ReflectionUtils.getFieldByNameInPOJOClass(clazz, PROTOCOL_ID);
ReflectionUtils.makeAccessible(protocolIdField);
return (short) ReflectionUtils.getField(protocolIdField, null);
}
private static void checkAllModules() {
// 模块id不能重复
var moduleIdSet = new HashSet<Byte>();
Arrays.stream(modules)
.filter(it -> Objects.nonNull(it))
.peek(it -> AssertionUtils.isTrue(!moduleIdSet.contains(it.getId()), "模块[{}]存在重复的id模块的id不能重复", it))
.forEach(it -> moduleIdSet.add(it.getId()));
// 模块名称不能重复
var moduleNameSet = new HashSet<String>();
Arrays.stream(modules)
.filter(it -> Objects.nonNull(it))
.peek(it -> AssertionUtils.isTrue(!moduleNameSet.contains(it.getName()), "模块[{}]存在重复的name模块名称不能重复", it))
.forEach(it -> moduleNameSet.add(it.getName()));
}
private static void checkAllProtocolClass() {
// 检查协议格式
// 协议的名称不能重复
var allProtocolNameMap = new HashMap<String, Class<?>>();
for (var protocolRegistration : protocols) {
if (protocolRegistration == null) {
continue;
}
var protocolClass = protocolRegistration.protocolConstructor().getDeclaringClass();
var protocolName = protocolClass.getSimpleName();
if (allProtocolNameMap.containsKey(protocolName)) {
throw new RunException("[class:{}][class:{}]协议名称重复协议不能含有重复的名称", protocolClass.getCanonicalName(), allProtocolNameMap.get(protocolName).getCanonicalName());
}
if (tempProtocolReserved.stream().anyMatch(it -> it.equalsIgnoreCase(protocolName))) {
throw new RunException("协议的名称[class:{}]不能是保留名称[{}]", protocolClass.getCanonicalName(), protocolName);
}
allProtocolNameMap.put(protocolName, protocolClass);
}
// 检查循环协议
for (var protocolEntry : tempSubProtocolIdMap.entrySet()) {
var protocolId = protocolEntry.getKey();
var subProtocolSet = protocolEntry.getValue();
if (subProtocolSet.contains(protocolId)) {
var protocolClass = protocols[protocolId].protocolConstructor().getDeclaringClass();
throw new RunException("[class:{}]在第一层包含循环引用协议[class:{}]", protocolClass.getSimpleName(), protocolClass.getSimpleName());
}
getAllSubProtocolIds(protocolId);
}
}
private static ProtocolRegistration parseProtocolRegistration(Class<?> clazz, ProtocolModule module) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
var protocolId = checkProtocol(clazz);
if (protocols[protocolId] != null) {
throw new RunException("[{}][{}]协议号[protocolId:{}]重复", protocols[protocolId].protocolConstructor().getDeclaringClass().getCanonicalName(), clazz.getCanonicalName(), protocolId);
}
var fields = new ArrayList<Field>();
for (var field : clazz.getDeclaredFields()) {
var modifiers = field.getModifiers();
if (Modifier.isTransient(modifiers) || Modifier.isStatic(modifiers)) {
continue;
}
if (Modifier.isFinal(modifiers)) {
throw new RunException("[{}]协议号[protocolId:{}]中的[filed:{}]属性的访问修饰符不能为final"
, clazz.getCanonicalName(), protocolId, field.getName());
}
if (!Modifier.isPublic(modifiers) && !Modifier.isPrivate(modifiers)) {
throw new RunException("[{}]协议号[protocolId:{}]中的[filed:{}]属性的访问修饰符必须是public或者private"
, clazz.getCanonicalName(), protocolId, field.getName());
}
ReflectionUtils.makeAccessible(field);
fields.add(field);
}
// 按变量名称从小到大排序
fields.sort(PACKET_FIELD_COMPARATOR);
var registrationList = new ArrayList<IFieldRegistration>();
for (var field : fields) {
registrationList.add(toRegistration(clazz, field));
}
var constructor = clazz.getDeclaredConstructor();
ReflectionUtils.makeAccessible(constructor);
var protocol = new ProtocolRegistration();
protocol.setId(protocolId);
protocol.setConstructor(constructor);
protocol.setFields(fields.toArray(new Field[fields.size()]));
protocol.setFieldRegistrations(registrationList.toArray(new IFieldRegistration[registrationList.size()]));
protocol.setModule(module.getId());
return protocol;
}
private static IFieldRegistration toRegistration(Class<?> clazz, Field field) throws NoSuchFieldException, IllegalAccessException {
Class<?> fieldTypeClazz = field.getType();
ISerializer serializer = tempBaseSerializerMap.get(fieldTypeClazz);
// 是一个基本类型变量
if (serializer != null) {
return BaseField.valueOf(serializer);
} else if (fieldTypeClazz.getComponentType() != null) {
// 是一个数组
Class<?> arrayClazz = fieldTypeClazz.getComponentType();
IFieldRegistration registration = typeToRegistration(clazz, arrayClazz);
return ArrayField.valueOf(field, registration);
} else if (Set.class.isAssignableFrom(fieldTypeClazz)) {
if (!fieldTypeClazz.equals(Set.class)) {
throw new RunException("[class:{}]类型声明不正确,必须是Set接口类型", clazz.getCanonicalName());
}
Type type = field.getGenericType();
if (!(type instanceof ParameterizedType)) {
throw new RunException("[class:{}]类型声明不正确,不是泛型类[field:{}]", clazz.getCanonicalName(), field.getName());
}
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
if (types.length != 1) {
throw new RunException("[class:{}]中Set类型声明不正确,[field:{}]必须声明泛型类", clazz.getCanonicalName(), field.getName());
}
IFieldRegistration registration = typeToRegistration(clazz, types[0]);
return SetField.valueOf(registration, type);
} else if (List.class.isAssignableFrom(fieldTypeClazz)) {
// 是一个List
if (!fieldTypeClazz.equals(List.class)) {
throw new RunException("[class:{}]类型声明不正确,必须是List接口类型", clazz.getCanonicalName());
}
Type type = field.getGenericType();
if (!(type instanceof ParameterizedType)) {
throw new RunException("[class:{}]类型声明不正确,不是泛型类[field:{}]", clazz.getCanonicalName(), field.getName());
}
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
if (types.length != 1) {
throw new RunException("[class:{}]中List类型声明不正确,[field:{}]必须声明泛型类", clazz.getCanonicalName(), field.getName());
}
IFieldRegistration registration = typeToRegistration(clazz, types[0]);
return ListField.valueOf(registration, (ParameterizedType) type);
} else if (Map.class.isAssignableFrom(fieldTypeClazz)) {
if (!fieldTypeClazz.equals(Map.class)) {
throw new RunException("[class:{}]类型声明不正确,必须是Map接口类型", clazz.getCanonicalName());
}
Type type = field.getGenericType();
if (!(type instanceof ParameterizedType)) {
throw new RunException("[class:{}]中数组类型声明不正确,[field:{}]不是泛型类", clazz.getCanonicalName(), field.getName());
}
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
if (types.length != 2) {
throw new RunException("[class:{}]中数组类型声明不正确,[field:{}]必须声明泛型类", clazz.getCanonicalName(), field.getName());
}
IFieldRegistration keyRegistration = typeToRegistration(clazz, types[0]);
IFieldRegistration valueRegistration = typeToRegistration(clazz, types[1]);
return MapField.valueOf(keyRegistration, valueRegistration, type);
} else {
// 是一个协议引用变量
var referenceProtocolId = getProtocolIdByClass(field.getType());
tempSubProtocolIdMap.computeIfAbsent(getProtocolIdByClass(clazz), it -> new HashSet<>()).add(referenceProtocolId);
return ObjectProtocolField.valueOf(referenceProtocolId);
}
}
private static IFieldRegistration typeToRegistration(Class<?> currentProtocolClass, Type type) {
if (type instanceof ParameterizedType) {
// 泛型类
Class<?> clazz = (Class<?>) ((ParameterizedType) type).getRawType();
if (Set.class.equals(clazz)) {
// Set<Set<String>>
IFieldRegistration registration = typeToRegistration(currentProtocolClass, ((ParameterizedType) type).getActualTypeArguments()[0]);
return SetField.valueOf(registration, type);
} else if (List.class.equals(clazz)) {
// List<List<String>>
IFieldRegistration registration = typeToRegistration(currentProtocolClass, ((ParameterizedType) type).getActualTypeArguments()[0]);
return ListField.valueOf(registration, (ParameterizedType) type);
} else if (Map.class.equals(clazz)) {
// Map<List<String>, List<String>>
IFieldRegistration keyRegistration = typeToRegistration(currentProtocolClass, ((ParameterizedType) type).getActualTypeArguments()[0]);
IFieldRegistration valueRegistration = typeToRegistration(currentProtocolClass, ((ParameterizedType) type).getActualTypeArguments()[1]);
return MapField.valueOf(keyRegistration, valueRegistration, type);
}
} else if (type instanceof Class) {
Class<?> clazz = ((Class<?>) type);
ISerializer serializer = tempBaseSerializerMap.get(clazz);
if (serializer != null) {
// 基础类型
return BaseField.valueOf(serializer);
} else if (clazz.getComponentType() != null) {
// 是一个二维以上数组
throw new RunException("不支持多维数组或集合嵌套数组[type:{}]类型,仅支持一维数组", type);
} else if (clazz.equals(List.class) || clazz.equals(Set.class) || clazz.equals(Map.class)) {
throw new RunException("不支持数组和集合联合使用[type:{}]类型", type);
} else {
// 是一个协议引用变量
var referenceProtocolId = getProtocolIdByClass(clazz);
tempSubProtocolIdMap.computeIfAbsent(getProtocolIdByClass(currentProtocolClass), it -> new HashSet<>()).add(referenceProtocolId);
return ObjectProtocolField.valueOf(referenceProtocolId);
}
}
throw new RunException("[type:{}]类型不正确", type);
}
/**
* 此方法仅在生成协议的时候调用,一旦运行,不能调用
*/
public static Set<Short> getAllSubProtocolIds(short protocolId) {
AssertionUtils.notNull(tempSubProtocolIdMap, "[{}]已经初始完成,初始化完成过后不能调用getAllSubProtocolIds", ProtocolManager.class.getSimpleName());
if (!tempSubProtocolIdMap.containsKey(protocolId)) {
return Collections.emptySet();
}
var protocolClass = protocols[protocolId].protocolConstructor().getDeclaringClass();
var queue = new LinkedList<>(tempSubProtocolIdMap.get(protocolId));
var allSubProtocolIdSet = new HashSet<>(queue);
while (!queue.isEmpty()) {
var firstSubProtocolId = queue.poll();
if (tempSubProtocolIdMap.containsKey(firstSubProtocolId)) {
for (var subClassId : tempSubProtocolIdMap.get(firstSubProtocolId)) {
if (subClassId == protocolId) {
throw new RunException("[class:{}]在下层协议[class:{}]包含循环引用协议[class:{}]", protocolClass.getSimpleName(), protocols[firstSubProtocolId].protocolConstructor().getDeclaringClass(), protocolClass.getSimpleName());
}
if (!allSubProtocolIdSet.contains(subClassId)) {
allSubProtocolIdSet.add(subClassId);
queue.offer(subClassId);
}
}
}
}
return allSubProtocolIdSet;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,180 @@
/*
* 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.collection;
import com.zfoo.protocol.util.AssertionUtils;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author jaysunxiao
* @version 3.0
*/
public abstract class ArrayUtils {
/**
* length
*/
public static int length(boolean[] array) {
return array == null ? 0 : array.length;
}
public static int length(byte[] array) {
return array == null ? 0 : array.length;
}
public static int length(short[] array) {
return array == null ? 0 : array.length;
}
public static int length(int[] array) {
return array == null ? 0 : array.length;
}
public static int length(long[] array) {
return array == null ? 0 : array.length;
}
public static int length(float[] array) {
return array == null ? 0 : array.length;
}
public static int length(double[] array) {
return array == null ? 0 : array.length;
}
public static int length(char[] array) {
return array == null ? 0 : array.length;
}
public static <T> int length(T[] array) {
return array == null ? 0 : array.length;
}
/**
* toList
*/
public static List<Boolean> toList(boolean[] array) {
if (array == null || array.length == 0) {
return Collections.emptyList();
}
var list = new ArrayList<Boolean>();
for (var value : array) {
list.add(value);
}
return list;
}
public static List<Byte> toList(byte[] array) {
if (array == null || array.length == 0) {
return Collections.emptyList();
}
var list = new ArrayList<Byte>();
for (var value : array) {
list.add(value);
}
return list;
}
public static List<Short> toList(short[] array) {
if (array == null || array.length == 0) {
return Collections.emptyList();
}
var list = new ArrayList<Short>();
for (var value : array) {
list.add(value);
}
return list;
}
public static List<Integer> toList(int[] array) {
if (array == null || array.length == 0) {
return Collections.emptyList();
}
var list = new ArrayList<Integer>();
for (var j : array) {
list.add(j);
}
return list;
}
public static List<Long> toList(long[] array) {
if (array == null || array.length == 0) {
return Collections.emptyList();
}
var list = new ArrayList<Long>();
for (var j : array) {
list.add(j);
}
return list;
}
public static List<Float> toList(float[] array) {
if (array == null || array.length == 0) {
return Collections.emptyList();
}
var list = new ArrayList<Float>();
for (var j : array) {
list.add(j);
}
return list;
}
public static List<Double> toList(double[] array) {
if (array == null || array.length == 0) {
return Collections.emptyList();
}
var list = new ArrayList<Double>();
for (var j : array) {
list.add(j);
}
return list;
}
public static List<Character> toList(char[] array) {
if (array == null || array.length == 0) {
return Collections.emptyList();
}
var list = new ArrayList<Character>();
for (var j : array) {
list.add(j);
}
return list;
}
public static <T> List<T> toList(T[] array) {
if (CollectionUtils.isEmpty(array)) {
return Collections.emptyList();
}
return Arrays.asList(array);
}
public static <T> T[] listToArray(List<T> list, Class<T> clazz) {
AssertionUtils.notNull(list);
AssertionUtils.notNull(clazz);
var length = list.size();
var objectArray = Array.newInstance(clazz, length);
for (var i = 0; i < length; i++) {
Array.set(objectArray, i, list.get(i));
}
return (T[]) objectArray;
}
}
@@ -0,0 +1,312 @@
/*
* 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.collection;
import com.zfoo.protocol.collection.model.NaturalComparator;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.util.AssertionUtils;
import java.util.*;
/**
* @author jaysunxiao
* @version 3.0
*/
public abstract class CollectionUtils {
/**
* Return {@code true} if the supplied Collection is {@code null} or empty.
* Otherwise, return {@code false}.
*
* @param collection the Collection to check
* @return whether the given Collection is empty
*/
public static boolean isEmpty(Collection<?> collection) {
return (collection == null || collection.isEmpty());
}
public static boolean isNotEmpty(Collection<?> collection) {
return !isEmpty(collection);
}
public static boolean isEmpty(Object[] array) {
return (array == null || array.length == 0);
}
public static boolean isNotEmpty(Object[] array) {
return !isEmpty(array);
}
/**
* Return {@code true} if the supplied Map is {@code null} or empty.
* Otherwise, return {@code false}.
*
* @param map the Map to check
* @return whether the given Map is empty
*/
public static boolean isEmpty(Map<?, ?> map) {
return (map == null || map.isEmpty());
}
public static boolean isNotEmpty(Map<?, ?> map) {
return !isEmpty(map);
}
public static int size(Collection<?> collection) {
return collection == null ? 0 : collection.size();
}
public static int size(Map<?, ?> map) {
return map == null ? 0 : map.size();
}
public static <T> Iterator<T> iterator(Collection<T> collection) {
return isEmpty(collection) ? Collections.emptyIterator() : collection.iterator();
}
public static <K, V> Iterator<Map.Entry<K, V>> iterator(Map<K, V> map) {
return isEmpty(map) ? Collections.emptyIterator() : map.entrySet().iterator();
}
/**
* 固定大小集合,如果初始化容量为0,则后续无法继续增加集合容量
*/
public static List<?> newFixedList(int size) {
return size <= 0 ? Collections.EMPTY_LIST : new ArrayList<>(size);
}
public static Set<?> newFixedSet(int size) {
return size <= 0 ? Collections.EMPTY_SET : new HashSet<>(comfortableCapacity(size));
}
public static Map<?, ?> newFixedMap(int size) {
return size <= 0 ? Collections.EMPTY_MAP : new HashMap<>(comfortableCapacity(size));
}
/**
* The largest power of two that can be represented as an {@code int}.
*/
public static final int MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2);
/**
* 计算HashMap初始化合适的大小
* <p>
* from com.google.common.collect.Maps.capacity()
*/
public static int comfortableCapacity(int expectedSize) {
if (expectedSize < 3) {
return expectedSize + 1;
}
if (expectedSize < MAX_POWER_OF_TWO) {
return (int) ((float) expectedSize / 0.75F + 1.0F);
}
// any large value
return Integer.MAX_VALUE;
}
// ----------------------------------归并排序----------------------------------
/**
* Merges two sorted Collections, a and b, into a single, sorted List
* such that the natural ordering of the elements is retained.
* <p>
* Uses the standard O(n) merge algorithm for combining two sorted lists.
* </p>
*
* @param aList the first collection, must not be null
* @param bList the second collection, must not be null
* @return a new sorted List, containing the elements of Collection a and b
*/
public static <T extends Comparable<? super T>> List<T> collate(List<? extends T> aList, List<? extends T> bList) {
return collate(aList, bList, NaturalComparator.getInstance(), true);
}
public static <T extends Comparable<? super T>> List<T> collate(List<? extends T> aList, List<? extends T> bList, boolean includeDuplicates) {
return collate(aList, bList, NaturalComparator.getInstance(), includeDuplicates);
}
public static <T> List<T> collate(List<T> aList, List<T> bList, Comparator<T> comparator) {
return collate(aList, bList, comparator, true);
}
/**
* Merges two sorted Collections, a and b, into a single, sorted List
* such that the ordering of the elements according to Comparator c is retained.
* <p>
* Uses the standard O(n) merge algorithm for combining two sorted lists.
* </p>
*
* @param <T> the element type
* @param aList the first collection, must not be null
* @param bList the second collection, must not be null
* @param comparator the comparator to use for the merge.
* @param includeDuplicates if {@code true} duplicate elements will be retained, otherwise
* they will be removed in the output collection
* @return a new sorted List, containing the elements of Collection a and b
*/
public static <T> List<T> collate(List<? extends T> aList, List<? extends T> bList, Comparator<? super T> comparator, boolean includeDuplicates) {
if (aList == null || bList == null) {
throw new NullPointerException("The collections must not be null");
}
if (comparator == null) {
throw new NullPointerException("The comparator must not be null");
}
var totalSize = aList.size() + bList.size();
var mergedList = new ArrayList<T>(totalSize);
var aIndex = 0;
var bIndex = 0;
T lastItem = null;
while (aIndex < aList.size() && bIndex < bList.size()) {
var a = aList.get(aIndex);
var b = bList.get(bIndex);
if (a == null) {
aIndex++;
continue;
}
if (b == null) {
bIndex++;
continue;
}
if (comparator.compare(a, b) >= 0) {
bIndex++;
if (!includeDuplicates && lastItem != null && lastItem.equals(b)) {
continue;
}
mergedList.add(b);
lastItem = b;
} else {
aIndex++;
if (!includeDuplicates && lastItem != null && lastItem.equals(a)) {
continue;
}
mergedList.add(a);
lastItem = a;
}
}
if (aIndex < aList.size()) {
for (var i = aIndex; i < aList.size(); i++) {
var value = aList.get(i);
if (!includeDuplicates && lastItem != null && lastItem.equals(value)) {
continue;
}
mergedList.add(value);
lastItem = value;
}
}
if (bIndex < bList.size()) {
for (var i = bIndex; i < bList.size(); i++) {
var value = bList.get(i);
if (!includeDuplicates && lastItem != null && lastItem.equals(value)) {
continue;
}
mergedList.add(value);
lastItem = value;
}
}
mergedList.trimToSize();
return mergedList;
}
/**
* list合并
*
* @param exclusive 元素是否是独占的,也就是说是否可以重复
* @param pairs 需要被合并的pairs集合,第一个参数是步数,第二个参数是集合
* @return 返回合并后的list
*/
public static <T> List<T> listJoinList(boolean exclusive, Pair<Integer, List<T>>... pairs) {
return listJoinList(exclusive, List.of(pairs));
}
public static <T> List<T> listJoinList(boolean exclusive, List<Pair<Integer, List<T>>> pairs) {
var iteratorList = new ArrayList<List<T>>();
var iteratorMap = new HashMap<List<T>, Iterator<T>>();
var stepMap = new HashMap<List<T>, Integer>();
for (var pair : pairs) {
var step = pair.getKey();
var list = pair.getValue();
AssertionUtils.ge1(step);
if (isNotEmpty(list)) {
var iterator = list.iterator();
iteratorList.add(list);
iteratorMap.put(list, iterator);
stepMap.put(list, step);
}
}
var result = new ArrayList<T>();
while (iteratorMap.values().stream().anyMatch(it -> it.hasNext())) {
for (var list : iteratorList) {
var iterator = iteratorMap.get(list);
var step = stepMap.get(list);
for (var i = 0; i < step && iterator.hasNext(); i++) {
var element = iterator.next();
if (exclusive && result.contains(element)) {
i--;
continue;
}
result.add(element);
}
}
}
return result;
}
/**
* 获取集合的最后几个元素
*/
public static <T> List<T> subListLast(List<T> list, int num) {
if (isEmpty(list)) {
return Collections.emptyList();
}
var startIndex = list.size() - num;
if (startIndex <= 0) {
return new ArrayList<>(list);
}
var result = new ArrayList<T>();
for (T element : list) {
startIndex--;
if (startIndex < 0) {
result.add(element);
}
}
return result;
}
}
@@ -0,0 +1,285 @@
/*
* 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.collection;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ConcurrentArrayList<E> implements List<E> {
private ReentrantLock lock;
private ArrayList<E> list;
public ConcurrentArrayList() {
this.lock = new ReentrantLock();
this.list = new ArrayList<>();
}
public ConcurrentArrayList(int initialCapacity) {
this.lock = new ReentrantLock();
this.list = new ArrayList<>(initialCapacity);
}
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
public List<E> clearAndReturn() {
lock.lock();
try {
var newList = (ArrayList<E>) list.clone();
list.clear();
return newList;
} finally {
lock.unlock();
}
}
@Override
public boolean contains(Object o) {
lock.lock();
try {
return list.contains(o);
} finally {
lock.unlock();
}
}
@Override
public Iterator<E> iterator() {
lock.lock();
try {
var newList = (ArrayList<E>) list.clone();
return newList.iterator();
} finally {
lock.unlock();
}
}
@Override
public Object[] toArray() {
lock.lock();
try {
return list.toArray();
} finally {
lock.unlock();
}
}
@Override
public <T> T[] toArray(T[] a) {
lock.lock();
try {
return list.toArray(a);
} finally {
lock.unlock();
}
}
@Override
public boolean add(E e) {
lock.lock();
try {
return list.add(e);
} finally {
lock.unlock();
}
}
@Override
public boolean remove(Object o) {
lock.lock();
try {
return list.remove(o);
} finally {
lock.unlock();
}
}
@Override
public boolean containsAll(Collection<?> c) {
lock.lock();
try {
return list.containsAll(c);
} finally {
lock.unlock();
}
}
@Override
public boolean addAll(Collection<? extends E> c) {
lock.lock();
try {
return list.addAll(c);
} finally {
lock.unlock();
}
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
lock.lock();
try {
return list.addAll(index, c);
} finally {
lock.unlock();
}
}
@Override
public boolean removeAll(Collection<?> c) {
lock.lock();
try {
return list.removeAll(c);
} finally {
lock.unlock();
}
}
@Override
public boolean retainAll(Collection<?> c) {
lock.lock();
try {
return list.retainAll(c);
} finally {
lock.unlock();
}
}
@Override
public void clear() {
lock.lock();
try {
list.clear();
} finally {
lock.unlock();
}
}
@Override
public E get(int index) {
return list.get(index);
}
@Override
public E set(int index, E element) {
lock.lock();
try {
return list.set(index, element);
} finally {
lock.unlock();
}
}
@Override
public void add(int index, E element) {
lock.lock();
try {
list.add(index, element);
} finally {
lock.unlock();
}
}
@Override
public E remove(int index) {
lock.lock();
try {
return list.remove(index);
} finally {
lock.unlock();
}
}
@Override
public int indexOf(Object o) {
lock.lock();
try {
return list.indexOf(o);
} finally {
lock.unlock();
}
}
@Override
public int lastIndexOf(Object o) {
lock.lock();
try {
return list.lastIndexOf(o);
} finally {
lock.unlock();
}
}
@Override
public ListIterator<E> listIterator() {
lock.lock();
try {
var newList = (ArrayList<E>) list.clone();
return newList.listIterator();
} finally {
lock.unlock();
}
}
@Override
public ListIterator<E> listIterator(int index) {
lock.lock();
try {
var newList = (ArrayList<E>) list.clone();
return newList.listIterator(index);
} finally {
lock.unlock();
}
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
lock.lock();
try {
return list.subList(fromIndex, toIndex);
} finally {
lock.unlock();
}
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (this != o) {
return false;
}
return list.equals(o);
}
@Override
public int hashCode() {
return super.hashCode();
}
}
@@ -0,0 +1,65 @@
/*
* 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.collection;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ConcurrentHashSet<E> extends AbstractSet<E> {
private Map<E, Boolean> map;
public ConcurrentHashSet() {
this.map = new ConcurrentHashMap<>();
}
public ConcurrentHashSet(int initialCapacity) {
this.map = new ConcurrentHashMap<>(initialCapacity);
}
@Override
public Iterator<E> iterator() {
return map.keySet().iterator();
}
@Override
public boolean contains(Object o) {
return map.containsKey(o);
}
@Override
public boolean add(E e) {
return map.put(e, Boolean.TRUE) == null;
}
@Override
public boolean remove(Object o) {
return map.remove(o) != null;
}
@Override
public int size() {
return map.size();
}
@Override
public void clear() {
map.clear();
}
}
@@ -0,0 +1,72 @@
/*
* 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.collection.model;
import java.util.Comparator;
public class NaturalComparator<E extends Comparable<? super E>> implements Comparator<E> {
/**
* The singleton instance.
*/
private static final NaturalComparator<?> INSTANCE = new NaturalComparator<>();
//-----------------------------------------------------------------------
/**
* Constructor whose use should be avoided.
* <p>
* Please use the {@link #getInstance()} method whenever possible.
*/
public NaturalComparator() {
super();
}
//-----------------------------------------------------------------------
/**
* Gets the singleton instance of a ComparableComparator.
* <p>
* Developers are encouraged to use the comparator returned from this method
* instead of constructing a new instance to reduce allocation and GC overhead
* when multiple comparable comparators may be used in the same VM.
*
* @param <E> the element type
* @return the singleton ComparableComparator
*/
public static <E extends Comparable<? super E>> NaturalComparator<E> getInstance() {
return (NaturalComparator<E>) INSTANCE;
}
//-----------------------------------------------------------------------
/**
* Compare the two {@link Comparable Comparable} arguments.
* This method is equivalent to:
* <pre>((Comparable)obj1).compareTo(obj2)</pre>
*
* @param a the first object to compare
* @param b the second object to compare
* @return negative if obj1 is less, positive if greater, zero if equal
* @throws NullPointerException if <i>obj1</i> is <code>null</code>,
* or when <code>((Comparable)obj1).compareTo(obj2)</code> does
* @throws ClassCastException if <i>obj1</i> is not a <code>Comparable</code>,
* or when <code>((Comparable)obj1).compareTo(obj2)</code> does
*/
@Override
public int compare(final E a, final E b) {
return a.compareTo(b);
}
}
@@ -0,0 +1,90 @@
/*
* 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.collection.tree;
import com.zfoo.protocol.util.StringUtils;
/**
* 多叉树
*
* @author jaysunxiao
* @version 3.0
*/
public class GeneralTree<T> {
private TreeNode<T> rootNode = new TreeNode<>(null, null);
public TreeNode<T> getRootNode() {
return rootNode;
}
public TreeNode<T> getNodeByPath(String path) {
var current = rootNode;
var splitPath = splitPath(path);
for (var nodeName : splitPath) {
current = current.childByName(nodeName);
if (current == null) {
return null;
}
}
return current;
}
public void addNode(String path, T data) {
var current = rootNode;
var splitPath = splitPath(path);
for (var nodeName : splitPath) {
current = current.getOrAddChild(nodeName);
}
current.setData(data);
}
public void removeNode(String path) {
var current = rootNode;
var parent = current.getParent();
var splitPath = splitPath(path);
for (var nodeName : splitPath) {
parent = current;
current = current.childByName(nodeName);
if (current == null) {
return;
}
}
if (parent != null) {
parent.removeChild(current.getName());
}
}
/**
* 移除所有数据结点
*/
public void clear() {
rootNode.clear();
}
private String[] splitPath(String path) {
if (StringUtils.isBlank(path)) {
return StringUtils.EMPTY_ARRAY;
}
if (!path.contains(StringUtils.PERIOD)) {
return new String[]{path};
}
return path.split(StringUtils.PERIOD_REGEX);
}
}
@@ -0,0 +1,224 @@
/*
* 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.collection.tree;
import com.zfoo.protocol.collection.CollectionUtils;
import com.zfoo.protocol.util.StringUtils;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @author jaysunxiao
* @version 3.0
*/
public class TreeNode<T> {
private String name;
private T data;
private TreeNode<T> parent;
private List<TreeNode<T>> children;
/**
* 创建树的结点
*
* @param name 数据结点名称
* @param parent 父数据结点
*/
TreeNode(String name, TreeNode<T> parent) {
this.name = name;
this.parent = parent;
}
/**
* 检测数据结点名称是否合法
*/
private static void checkName(String name) {
if (StringUtils.isBlank(name) || name.contains(StringUtils.PERIOD)) {
throw new RuntimeException("Name of tree node is invalid.");
}
}
/**
* 获取数据结点的完整名称。
*/
public String fullName() {
if (parent == null) {
return name;
}
var parentName = parent.fullName();
if (parentName == null) {
return name;
}
return StringUtils.format("{}{}{}", parentName, StringUtils.PERIOD, name);
}
/**
* 根据名称检查是否存在子数据结点
*
* @param name 子数据结点名称
* @return 是否存在子数据结点
*/
public boolean hasChild(String name) {
checkName(name);
if (children == null) {
return false;
}
for (var child : children) {
if (child.name.equals(name)) {
return true;
}
}
return false;
}
/**
* 根据名称获取子数据结点
*
* @param name 子数据结点名称
* @return 指定名称的子数据结点,如果没有找到,则返回空
*/
public TreeNode<T> childByName(String name) {
checkName(name);
if (children == null) {
return null;
}
for (var child : children) {
if (child.name.equals(name)) {
return child;
}
}
return null;
}
/**
* 获取所有子节点,包括父节点和子节点的子节点
*/
public List<TreeNode<T>> flatTreeNodes() {
var result = new ArrayList<TreeNode<T>>();
result.add(this);
if (CollectionUtils.isEmpty(children)) {
return result;
}
var queue = new LinkedList<>(children);
result.addAll(queue);
while (!queue.isEmpty()) {
var childTreeNode = queue.poll();
var childChildren = childTreeNode.getChildren();
if (CollectionUtils.isEmpty(childChildren)) {
continue;
}
for (var subClassId : childTreeNode.getChildren()) {
result.add(subClassId);
queue.offer(subClassId);
}
}
return result;
}
/**
* 根据名称获取或增加子数据结点
*
* @param name 子数据结点名称
* @return 指定名称的子数据结点,如果对应名称的子数据结点已存在,则返回已存在的子数据结点,否则增加子数据结点
*/
public TreeNode<T> getOrAddChild(String name) {
var node = childByName(name);
if (node != null) {
return node;
}
node = new TreeNode<>(name, this);
if (children == null) {
children = new ArrayList<>();
}
children.add(node);
return node;
}
/**
* 根据名称移除子数据结点
*
* @param name 子数据结点名称
*/
public void removeChild(String name) {
var node = childByName(name);
if (node == null) {
return;
}
children.remove(node);
}
public void clear() {
name = null;
data = null;
parent = null;
children = null;
}
public int childCount() {
if (CollectionUtils.isEmpty(children)) {
return 0;
}
return children.size();
}
public String getName() {
return name;
}
public List<TreeNode<T>> getChildren() {
return children;
}
public TreeNode<T> getParent() {
return parent;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return StringUtils.format("[{}]:[{}]", fullName(), data);
}
}
@@ -0,0 +1,31 @@
/*
* 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.exception;
import com.zfoo.protocol.util.StringUtils;
/**
* @author jaysunxiao
* @version 3.0
*/
public class AssertException extends RuntimeException {
public AssertException(String message) {
super(message);
}
public AssertException(String template, Object... args) {
super(StringUtils.format(template, args));
}
}
@@ -0,0 +1,65 @@
/*
* 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.exception;
import com.zfoo.protocol.util.FileUtils;
import com.zfoo.protocol.util.StringUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
public abstract class ExceptionUtils {
/**
* 获取异常全部信息,格式是:
* <p>
* 类名称: 异常信息
* 异常堆栈
* </p>
*
* @param throwable the throwable to get a message for, null returns empty string
* @return 异常的信息
*/
public static String getMessage(final Throwable throwable) {
if (throwable == null) {
return StringUtils.EMPTY;
}
final String className = throwable.getClass().getName();
return className + ": " + throwable.getMessage() + FileUtils.LS
+ getStackTrace(throwable);
}
/**
* <p>Gets the stack trace from a Throwable as a String.</p>
* <p>The result of this method vary by JDK version as this method uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
*
* @param throwable the <code>Throwable</code> to be examined
* @return the stack trace as generated by the exception's
*/
public static String getStackTrace(final Throwable throwable) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
return sw.getBuffer().toString();
}
public static String getCurrentStackTrace() {
var builder = new StringBuilder();
var stackTraces = Thread.currentThread().getStackTrace();
Arrays.stream(stackTraces).forEach(it -> builder.append(it.toString()).append(FileUtils.LS));
return builder.toString();
}
}
@@ -0,0 +1,39 @@
/*
* 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.exception;
/**
* 不是一个POJO对象,POJO对象不应该继承别的类
*
* @author jaysunxiao
* @version 3.0
*/
public class POJOException extends RuntimeException {
private static final String MESSAGE = "not a POJO object, can't extend other object";
private static final String HYPHEN = "-";//连接号,连接号与破折号的区别是,连接号的两头不用空格
private static final String LEFT_SQUARE_BRACKET = "[";//左方括号
private static final String RIGHT_SQUARE_BRACKET = "]";//右方括号
public POJOException() {
super(POJOException.MESSAGE);
}
public POJOException(String message) {
super(POJOException.MESSAGE + POJOException.HYPHEN + POJOException.LEFT_SQUARE_BRACKET + message + POJOException.RIGHT_SQUARE_BRACKET);
}
}
@@ -0,0 +1,43 @@
/*
* 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.exception;
import com.zfoo.protocol.util.StringUtils;
/**
* @author jaysunxiao
* @version 3.0
*/
public class RunException extends RuntimeException {
public RunException(Throwable cause) {
super(cause);
}
public RunException(String message) {
super(message);
}
public RunException(String template, Object... args) {
super(StringUtils.format(template, args));
}
public RunException(Throwable cause, String message) {
super(message, cause);
}
public RunException(Throwable cause, String template, Object... args) {
super(StringUtils.format(template, args), cause);
}
}
@@ -0,0 +1,43 @@
/*
* 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.exception;
import com.zfoo.protocol.util.StringUtils;
/**
* @author jaysunxiao
* @version 3.0
*/
public class UnknownException extends RuntimeException {
public UnknownException(Throwable cause) {
super(cause);
}
public UnknownException(String message) {
super(message);
}
public UnknownException(String template, Object... args) {
super(StringUtils.format(template, args));
}
public UnknownException(Throwable cause, String message) {
super(message, cause);
}
public UnknownException(Throwable cause, String template, Object... args) {
super(StringUtils.format(template, args), cause);
}
}
@@ -0,0 +1,94 @@
/*
* 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.generate;
/**
* 创建协议文件的操作类
*
* @author jaysunxiao
* @version 3.0
*/
public class GenerateOperation {
/**
* 不创建任何协议文件
*/
public static final GenerateOperation NO_OPERATION = new GenerateOperation();
/**
* 折叠协议,生成协议文件会和Java源文件保持相同的目录结构
*/
private boolean foldProtocol;
/**
* 生成协议文件的后缀名称,如果不指定,用语言约定的默认名称
*/
private String protocolParam;
/**
* 生成javascript协议文件
*/
private boolean generateJsProtocol;
/**
* 生成C#协议文件
*/
private boolean generateCsharpProtocol;
/**
* 生成Lua协议文件
*/
private boolean generateLuaProtocol;
public boolean isFoldProtocol() {
return foldProtocol;
}
public void setFoldProtocol(boolean foldProtocol) {
this.foldProtocol = foldProtocol;
}
public String getProtocolParam() {
return protocolParam;
}
public void setProtocolParam(String protocolParam) {
this.protocolParam = protocolParam;
}
public boolean isGenerateJsProtocol() {
return generateJsProtocol;
}
public void setGenerateJsProtocol(boolean generateJsProtocol) {
this.generateJsProtocol = generateJsProtocol;
}
public boolean isGenerateCsharpProtocol() {
return generateCsharpProtocol;
}
public void setGenerateCsharpProtocol(boolean generateCsharpProtocol) {
this.generateCsharpProtocol = generateCsharpProtocol;
}
public boolean isGenerateLuaProtocol() {
return generateLuaProtocol;
}
public void setGenerateLuaProtocol(boolean generateLuaProtocol) {
this.generateLuaProtocol = generateLuaProtocol;
}
}
@@ -0,0 +1,184 @@
/*
* 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.generate;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.util.AssertionUtils;
import com.zfoo.protocol.util.FileUtils;
import com.zfoo.protocol.util.StringUtils;
import java.io.File;
import java.util.Collections;
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;
/**
* 生成协议的时候,协议的文档注释和字段注释会使用这个类
*
* @author jaysunxiao
* @version 3.0
*/
public abstract class GenerateProtocolDocument {
// 临时变量,启动完成就会销毁,协议的文档,外层map的key为协议类;pair的key为总的注释,value为属性字段的注释,value表示的map的key为属性名称
// 比如在Test中的ComplexObject生成的pari是如下格式
/**
* key docTitle:
* // 复杂的对象
* // 包括了各种复杂的结构,数组,List,Set,Map
* //
* // @author jaysunxiao
* // @version 1.0
* <p>
* value aa:
* // byte的包装类型
* // 优先使用基础类型,包装类型会有装箱拆箱
*/
private static Map<Short, Pair<String, Map<String, String>>> tempProtocolDocumentMap = new HashMap<>();
public static void clear() {
tempProtocolDocumentMap.clear();
tempProtocolDocumentMap = null;
}
/**
* 此方法仅在生成协议的时候调用,一旦运行,不能调用
*/
public static Pair<String, Map<String, String>> getProtocolDocument(short protocolId) {
AssertionUtils.notNull(tempProtocolDocumentMap, "[{}]已经初始完成,初始化完成过后不能调用getProtocolDocument", GenerateProtocolDocument.class.getSimpleName());
var protocolDocument = tempProtocolDocumentMap.get(protocolId);
if (protocolDocument == null) {
return new Pair<>(StringUtils.EMPTY, Collections.emptyMap());
}
return protocolDocument;
}
public static void initProtocolDocument(List<IProtocolRegistration> protocolRegistrations) {
AssertionUtils.notNull(tempProtocolDocumentMap, "[{}]已经初始完成,初始化完成过后不能调用initProtocolDocument", GenerateProtocolDocument.class.getSimpleName());
for (var protocolRegistration : protocolRegistrations) {
var protocolClazzName = protocolRegistration.protocolConstructor().getDeclaringClass().getSimpleName();
// 文件的注释生成
var proAbsFile = new File(FileUtils.getProAbsPath());
var list = FileUtils.getAllReadableFiles(proAbsFile.getParentFile() == null ? proAbsFile : proAbsFile.getParentFile());
var protocolFile = list.stream()
.filter(it -> it.getName().equals(StringUtils.format("{}.java", protocolClazzName)))
.findFirst();
// 如果搜索不到协议文件则直接返回
if (protocolFile.isEmpty()) {
continue;
}
var docFieldMap = new HashMap<String, String>();
var docTitle = StringUtils.EMPTY;
var protocolStringList = FileUtils.readFileToStringList(protocolFile.get())
.stream()
.dropWhile(it -> !it.startsWith("package")) // 过滤掉package之上的版权信息
.collect(Collectors.toList());
// 搜索包名,报名不匹配则直接返回
var protocolClassTitle = StringUtils.format("public class {}", protocolClazzName);
if (protocolStringList.stream().noneMatch(it -> it.contains(protocolClassTitle))) {
continue;
}
protocolStringList = protocolStringList.stream()
.dropWhile(it -> !it.startsWith("package"))
.collect(Collectors.toList());
var docBuilder = new StringBuilder();
var docTitleBuilder = new StringBuilder();
for (var line : protocolStringList) {
var startLineStr = line.trim();
// 排除java的包头
if (startLineStr.startsWith("package") || startLineStr.startsWith("import")) {
continue;
}
if (startLineStr.startsWith("public class ")) {
if (docTitleBuilder != null) {
docTitle = docTitleBuilder.toString();
docTitle = docTitle.replace("/**", StringUtils.EMPTY);
docTitle = docTitle.replace(" */", StringUtils.EMPTY);
docTitle = docTitle.replace(" *", "//");
docTitle = docTitle.trim();
docBuilder = new StringBuilder();
docTitleBuilder = null;
}
} else {
if (docTitleBuilder != null) {
docTitleBuilder.append(line).append(LS);
}
}
// 保留注释
if (startLineStr.startsWith("*/")) {
continue;
}
if (startLineStr.startsWith("//") || startLineStr.startsWith("*")) {
startLineStr = startLineStr.replaceFirst("//", StringUtils.EMPTY);
startLineStr = startLineStr.replaceFirst("\\*", StringUtils.EMPTY);
docBuilder.append("//").append(startLineStr).append(LS);
continue;
}
if (startLineStr.startsWith("private static ")) {
continue;
}
if (startLineStr.contains(" transient ")) {
continue;
}
if (startLineStr.startsWith("public void set") || startLineStr.startsWith("public bool equals")
|| startLineStr.startsWith("public int hashCode") || startLineStr.startsWith("@Override")) {
continue;
}
if (startLineStr.endsWith("{") || startLineStr.startsWith("return ") || startLineStr.startsWith("}")) {
continue;
}
if (!startLineStr.endsWith(";")) {
continue;
}
if (!(startLineStr.startsWith("private ") || startLineStr.startsWith("public "))) {
continue;
}
var fieldName = StringUtils.substringBeforeLast(StringUtils.substringAfterLast(startLineStr, StringUtils.SPACE), StringUtils.SEMICOLON).trim();
docFieldMap.put(fieldName, docBuilder.toString());
docBuilder = new StringBuilder();
}
tempProtocolDocumentMap.put(protocolRegistration.protocolId(), new Pair<>(docTitle, docFieldMap));
}
}
}
@@ -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.generate;
import com.zfoo.protocol.ProtocolManager;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.serializer.cs.GenerateCsUtils;
import com.zfoo.protocol.serializer.js.GenerateJsUtils;
import com.zfoo.protocol.serializer.lua.GenerateLuaUtils;
import com.zfoo.protocol.util.ReflectionUtils;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* @author jaysunxiao
* @version 3.0
*/
public abstract class GenerateProtocolFile {
/**
* 生成协议的过滤器,默认不过滤
*/
public static Predicate<IProtocolRegistration> generateProtocolFilter = registration -> true;
public static void generate(IProtocolRegistration[] protocols, GenerateOperation generateOperation) throws IOException {
// 如果没有需要生成的协议则直接返回
var generateProtocolFlag = Arrays.stream(generateOperation.getClass().getDeclaredFields())
.filter(it -> it.getName().startsWith("generate"))
.peek(it -> ReflectionUtils.makeAccessible(it))
.map(it -> ReflectionUtils.getField(it, generateOperation))
.filter(it -> it instanceof Boolean)
.anyMatch(it -> ((Boolean) it).booleanValue() == true);
if (!generateProtocolFlag) {
return;
}
// 外层需要生成的协议
var outsideGenerateProtocols = Arrays.stream(protocols)
.filter(it -> Objects.nonNull(it))
.filter(it -> generateProtocolFilter.test(it))
.collect(Collectors.toList());
// 需要生成的子协议,因为外层协议的内部有其它协议
var insideGenerateProtocols = outsideGenerateProtocols.stream()
.map(it -> ProtocolManager.getAllSubProtocolIds(it.protocolId()))
.flatMap(it -> it.stream())
.map(it -> protocols[it])
.distinct()
.collect(Collectors.toList());
var allGenerateProtocols = new HashSet<IProtocolRegistration>();
allGenerateProtocols.addAll(outsideGenerateProtocols);
allGenerateProtocols.addAll(insideGenerateProtocols);
// 通过协议号,从小到大排序
var allSortedGenerateProtocols = allGenerateProtocols.stream()
.sorted((a, b) -> a.protocolId() - b.protocolId())
.collect(Collectors.toList());
// 解析协议的文档注释
GenerateProtocolDocument.initProtocolDocument(allSortedGenerateProtocols);
// 计算协议生成的路径
if (generateOperation.isFoldProtocol()) {
GenerateProtocolPath.initProtocolPath(allSortedGenerateProtocols);
}
// 生成C#协议
if (generateOperation.isGenerateCsharpProtocol()) {
GenerateCsUtils.init();
GenerateCsUtils.createProtocolManager();
allSortedGenerateProtocols.forEach(it -> GenerateCsUtils.createCsProtocolFile((ProtocolRegistration) it));
}
// 生成Javascript协议
if (generateOperation.isGenerateJsProtocol()) {
GenerateJsUtils.init();
allSortedGenerateProtocols.forEach(it -> GenerateJsUtils.createJsProtocolFile((ProtocolRegistration) it));
GenerateJsUtils.createProtocolManager(allSortedGenerateProtocols);
}
// 生成Lua协议
if (generateOperation.isGenerateLuaProtocol()) {
GenerateLuaUtils.init();
GenerateLuaUtils.createProtocolManager(allSortedGenerateProtocols);
allSortedGenerateProtocols.forEach(it -> GenerateLuaUtils.createLuaProtocolFile((ProtocolRegistration) it));
}
// 参数,以后可能会用,比如给Lua修改一个后缀名称
var protocolParam = generateOperation.getProtocolParam();
}
}
@@ -0,0 +1,120 @@
/*
* 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.generate;
import com.zfoo.protocol.collection.CollectionUtils;
import com.zfoo.protocol.collection.tree.GeneralTree;
import com.zfoo.protocol.collection.tree.TreeNode;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.util.AssertionUtils;
import com.zfoo.protocol.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* 生成协议的时候,协议的最终生成路径会使用这个类
*
* @author jaysunxiao
* @version 3.0
*/
public abstract class GenerateProtocolPath {
// 临时变量,启动完成就会销毁,协议生成的路径
private static Map<Short, String> tempProtocolPathMap = new HashMap<>();
public static void clear() {
tempProtocolPathMap.clear();
tempProtocolPathMap = null;
}
/**
* 获取协议生成的路径
*/
public static String getProtocolPath(short protocolId) {
AssertionUtils.notNull(tempProtocolPathMap, "[{}]已经初始完成,初始化完成过后不能调用getProtocolPath", GenerateProtocolPath.class.getSimpleName());
var protocolPath = tempProtocolPathMap.get(protocolId);
if (StringUtils.isBlank(protocolPath)) {
return StringUtils.EMPTY;
}
return protocolPath.replaceAll(StringUtils.PERIOD_REGEX, StringUtils.SLASH);
}
/**
* 获取协议生成的首字母大写的路径
*/
public static String getCapitalizeProtocolPath(short protocolId) {
return StringUtils.joinWith(StringUtils.SLASH, Arrays.stream(getProtocolPath(protocolId).split(StringUtils.SLASH)).map(it -> StringUtils.capitalize(it)).toArray());
}
/**
* 解析协议的路径
*
* @param protocolRegistrations 需要解析的路径
*/
public static void initProtocolPath(List<IProtocolRegistration> protocolRegistrations) {
AssertionUtils.notNull(tempProtocolPathMap, "[{}]已经初始完成,初始化完成过后不能调用initProtocolPath", GenerateProtocolPath.class.getSimpleName());
// 将需要生成的协议的路径添加到多叉树中
var protocolPathTree = new GeneralTree<IProtocolRegistration>();
protocolRegistrations.forEach(it -> protocolPathTree.addNode(it.protocolConstructor().getDeclaringClass().getCanonicalName(), it));
var rootTreeNode = protocolPathTree.getRootNode();
if (CollectionUtils.isEmpty(rootTreeNode.getChildren())) {
return;
}
var queue = new LinkedList<>(rootTreeNode.getChildren());
while (!queue.isEmpty()) {
var childTreeNode = queue.poll();
var childChildren = childTreeNode.getChildren();
// 如果子节点为空,则以当前节点为路径
if (CollectionUtils.isEmpty(childChildren)) {
toProtocolPath(childTreeNode);
continue;
}
// 如果子节点的协议数据有一个不为空的,则以当前节点为路径
if (childChildren.stream().anyMatch(it -> it.getData() != null)) {
toProtocolPath(childTreeNode);
continue;
}
// 继续深度便利子节点的路径
for (var subClassId : childTreeNode.getChildren()) {
queue.offer(subClassId);
}
}
}
private static void toProtocolPath(TreeNode<IProtocolRegistration> protocolTreeNode) {
var allChildren = protocolTreeNode.flatTreeNodes()
.stream()
.filter(it -> it.getData() != null)
.collect(Collectors.toList());
var pathBefore = StringUtils.substringBeforeLast(protocolTreeNode.fullName(), StringUtils.PERIOD);
for (var child : allChildren) {
var protocolSimpleName = child.getData().protocolConstructor().getDeclaringClass().getSimpleName();
var splits = Arrays.stream(StringUtils.substringBeforeLast(StringUtils.substringAfterFirst(child.fullName(), pathBefore), protocolSimpleName)
.split(StringUtils.PERIOD_REGEX))
.filter(it -> !StringUtils.isBlank(it))
.toArray();
tempProtocolPathMap.put(child.getData().protocolId(), StringUtils.joinWith(StringUtils.PERIOD, splits));
}
}
}
@@ -0,0 +1,85 @@
/*
* 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.model;
import java.util.Objects;
/**
* 键值对对象,只能在构造时传入键值
*
* @param <K> 键类型
* @param <V> 值类型
* @author jaysunxiao
* @version 3.0
*/
public class Pair<K, V> {
private K key;
private V value;
public Pair() {
}
/**
* 构造
*
* @param key 键
* @param value 值
*/
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
/**
* 获取键
*
* @return 键
*/
public K getKey() {
return this.key;
}
/**
* 获取值
*
* @return 值
*/
public V getValue() {
return this.value;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Pair<?, ?> pair = (Pair<?, ?>) o;
return Objects.equals(key, pair.key) && Objects.equals(value, pair.value);
}
@Override
public int hashCode() {
return Objects.hash(key, value);
}
@Override
public String toString() {
return "Pair [key=" + key + ", value=" + value + "]";
}
}
@@ -0,0 +1,54 @@
/*
* 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.model;
/**
* T cardinal number that is the sum of three and one.
*
* @author jaysunxiao
* @version 3.0
*/
public class Quaternion<A, B, C, D> {
private A a;
private B b;
private C c;
private D d;
public Quaternion() {
}
public Quaternion(A a, B b, C c, D d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
public A getA() {
return a;
}
public B getB() {
return b;
}
public C getC() {
return c;
}
public D getD() {
return d;
}
}
@@ -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.model;
/**
* A triple consisting of three elements. It refers to the elements as 'left', 'middle' and 'right'.
*
* @author jaysunxiao
* @version 3.0
*/
public class Triple<L, M, R> {
private L left;
private M middle;
private R right;
public Triple() {
}
public Triple(L left, M middle, R right) {
this.left = left;
this.middle = middle;
this.right = right;
}
public L getLeft() {
return left;
}
public M getMiddle() {
return middle;
}
public R getRight() {
return right;
}
}
@@ -0,0 +1,259 @@
/*
* 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.registration;
import com.zfoo.protocol.IPacket;
import com.zfoo.protocol.ProtocolManager;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.collection.ArrayUtils;
import com.zfoo.protocol.collection.CollectionUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.*;
import com.zfoo.protocol.serializer.enhance.*;
import com.zfoo.protocol.util.ReflectionUtils;
import com.zfoo.protocol.util.StringUtils;
import io.netty.buffer.ByteBuf;
import javassist.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
/**
* 对应于ProtocolRegistration
*
* @author jaysunxiao
* @version 3.0
*/
public abstract class EnhanceUtils {
// 临时变量,是一个基本类型序列化器对应的增强类型序列化器
private static Map<ISerializer, IEnhanceSerializer> tempEnhanceSerializerMap = new HashMap<>();
public static String byteBufUtils = ByteBufUtils.class.getSimpleName();
public static String byteBufUtilsWriteBooleanFalse = byteBufUtils + ".writeBoolean($1, false);";
public static String byteBufUtilsWriteBooleanTrue = byteBufUtils + ".writeBoolean($1, true);";
public static String byteBufUtilsReadBoolean = byteBufUtils + ".readBoolean($1)";
public static String byteBufUtilsWriteInt0 = byteBufUtils + ".writeInt($1, 0);";
static {
var classArray = new Class<?>[]{
IPacket.class,
IProtocolRegistration.class,
IFieldRegistration.class,
ByteBuf.class
};
var classPool = ClassPool.getDefault();
// 导入需要的包
classPool.importPackage(IPacket.class.getCanonicalName());
classPool.importPackage(ByteBufUtils.class.getCanonicalName());
classPool.importPackage(Collections.class.getCanonicalName());
classPool.importPackage(CollectionUtils.class.getCanonicalName());
classPool.importPackage(ArrayUtils.class.getCanonicalName());
classPool.importPackage(Iterator.class.getCanonicalName());
classPool.importPackage(List.class.getCanonicalName());
classPool.importPackage(ArrayList.class.getCanonicalName());
classPool.importPackage(Map.class.getCanonicalName());
classPool.importPackage(HashMap.class.getCanonicalName());
classPool.importPackage(Set.class.getCanonicalName());
classPool.importPackage(HashSet.class.getCanonicalName());
// 增加类的路径
for (var clazz : classArray) {
if (classPool.find(clazz.getCanonicalName()) == null) {
ClassClassPath classPath = new ClassClassPath(clazz);
classPool.insertClassPath(classPath);
}
}
tempEnhanceSerializerMap.put(BooleanSerializer.getInstance(), new EnhanceBooleanSerializer());
tempEnhanceSerializerMap.put(ByteSerializer.getInstance(), new EnhanceByteSerializer());
tempEnhanceSerializerMap.put(ShortSerializer.getInstance(), new EnhanceShortSerializer());
tempEnhanceSerializerMap.put(IntSerializer.getInstance(), new EnhanceIntSerializer());
tempEnhanceSerializerMap.put(LongSerializer.getInstance(), new EnhanceLongSerializer());
tempEnhanceSerializerMap.put(FloatSerializer.getInstance(), new EnhanceFloatSerializer());
tempEnhanceSerializerMap.put(DoubleSerializer.getInstance(), new EnhanceDoubleSerializer());
tempEnhanceSerializerMap.put(CharSerializer.getInstance(), new EnhanceCharSerializer());
tempEnhanceSerializerMap.put(StringSerializer.getInstance(), new EnhanceStringSerializer());
tempEnhanceSerializerMap.put(ObjectProtocolSerializer.getInstance(), new EnhanceObjectProtocolSerializer());
tempEnhanceSerializerMap.put(ListSerializer.getInstance(), new EnhanceListSerializer());
tempEnhanceSerializerMap.put(SetSerializer.getInstance(), new EnhanceSetSerializer());
tempEnhanceSerializerMap.put(MapSerializer.getInstance(), new EnhanceMapSerializer());
tempEnhanceSerializerMap.put(ArraySerializer.getInstance(), new EnhanceArraySerializer());
}
public static IEnhanceSerializer enhanceSerializer(ISerializer serializer) {
return tempEnhanceSerializerMap.get(serializer);
}
public static void clear() {
tempEnhanceSerializerMap.clear();
tempEnhanceSerializerMap = null;
byteBufUtils = null;
byteBufUtilsWriteBooleanFalse = null;
byteBufUtilsWriteBooleanTrue = null;
byteBufUtilsReadBoolean = null;
byteBufUtilsWriteInt0 = null;
}
/**
* @param registration 需要增强的类
* @return 返回类的名称格式:EnhanceUtilsProtocolRegistration1
*/
public static IProtocolRegistration createProtocolRegistration(ProtocolRegistration registration) throws NotFoundException, CannotCompileException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
var classPool = ClassPool.getDefault();
GenerateUtils.index.set(0);
short protocolId = registration.getId();
IFieldRegistration[] packetFields = registration.getFieldRegistrations();
// 定义类名称
CtClass enhanceClazz = classPool.makeClass(ProtocolRegistration.class.getCanonicalName() + protocolId);
enhanceClazz.addInterface(classPool.get(IProtocolRegistration.class.getCanonicalName()));
// 定义类中的一个成员
CtField constructorFiled = new CtField(classPool.get(Constructor.class.getCanonicalName()), "constructor", enhanceClazz);
constructorFiled.setModifiers(Modifier.PRIVATE);
enhanceClazz.addField(constructorFiled);
// 定义类所包含的所有子协议成员
var allSubProtocolIds = ProtocolManager.getAllSubProtocolIds(protocolId)
.stream()
.sorted((a, b) -> Short.compare(a, b))
.collect(Collectors.toList());
for (var subProtocolId : allSubProtocolIds) {
var protocolRegistrationField = new CtField(classPool.get(IProtocolRegistration.class.getCanonicalName()), getProtocolRegistrationFieldNameByProtocolId(subProtocolId), enhanceClazz);
constructorFiled.setModifiers(Modifier.PRIVATE);
enhanceClazz.addField(protocolRegistrationField);
}
// 定义类的构造器
CtConstructor constructor = new CtConstructor(classPool.get(new String[]{Constructor.class.getCanonicalName()}), enhanceClazz);
constructor.setBody("{this.constructor=$1;}");
constructor.setModifiers(Modifier.PUBLIC);
enhanceClazz.addConstructor(constructor);
// 定义类实现的接口方法
CtMethod protocolIdMethod = new CtMethod(classPool.get(short.class.getCanonicalName()), "protocolId", null, enhanceClazz);
protocolIdMethod.setModifiers(Modifier.PUBLIC + Modifier.FINAL);
protocolIdMethod.setBody("{return " + registration.protocolId() + ";}");
enhanceClazz.addMethod(protocolIdMethod);
CtMethod protocolConstructorMethod = new CtMethod(classPool.get(Constructor.class.getCanonicalName()), "protocolConstructor", null, enhanceClazz);
protocolConstructorMethod.setModifiers(Modifier.PUBLIC + Modifier.FINAL);
protocolConstructorMethod.setBody("{return this.constructor;}");
enhanceClazz.addMethod(protocolConstructorMethod);
CtMethod moduleMethod = new CtMethod(classPool.get(byte.class.getCanonicalName()), "module", null, enhanceClazz);
moduleMethod.setModifiers(Modifier.PUBLIC + Modifier.FINAL);
moduleMethod.setBody("{return " + registration.module() + ";}");
enhanceClazz.addMethod(moduleMethod);
CtMethod writeMethod = new CtMethod(classPool.get(void.class.getCanonicalName()), "write", classPool.get(new String[]{ByteBuf.class.getCanonicalName(), IPacket.class.getCanonicalName()}), enhanceClazz);
writeMethod.setModifiers(Modifier.PUBLIC + Modifier.FINAL);
writeMethod.setBody(writeMethodBody(registration));
enhanceClazz.addMethod(writeMethod);
CtMethod readMethod = new CtMethod(classPool.get(Object.class.getCanonicalName()), "read", classPool.get(new String[]{ByteBuf.class.getCanonicalName()}), enhanceClazz);
readMethod.setModifiers(Modifier.PUBLIC + Modifier.FINAL);
readMethod.setBody(readMethodBody(registration));
enhanceClazz.addMethod(readMethod);
// 释放缓存
enhanceClazz.detach();
Class<?> resultClazz = enhanceClazz.toClass(IProtocolRegistration.class);
Constructor<?> resultConstructor = resultClazz.getConstructor(Constructor.class);
return (IProtocolRegistration) resultConstructor.newInstance(registration.protocolConstructor());
}
// see: ProtocolRegistration.write()
private static String writeMethodBody(ProtocolRegistration registration) {
short protocolId = registration.getId();
Constructor<?> constructor = registration.getConstructor();
Field[] fields = registration.getFields();
IFieldRegistration[] fieldRegistrations = registration.getFieldRegistrations();
Class<?> packetClazz = constructor.getDeclaringClass();
StringBuilder builder = new StringBuilder();
builder.append("{");
builder.append(packetClazz.getCanonicalName() + " packet = (" + packetClazz.getCanonicalName() + ")$2;");
builder.append("if(ByteBufUtils.writePacketFlag($1, packet)){")
.append("return;}");
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
IFieldRegistration fieldRegistration = fieldRegistrations[i];
if (Modifier.isPublic(field.getModifiers())) {
enhanceSerializer(fieldRegistration.serializer())
.writeObject(builder, StringUtils.format("packet.{}", field.getName()), field, fieldRegistration);
} else {
enhanceSerializer(fieldRegistration.serializer())
.writeObject(builder, StringUtils.format("packet.{}()", ReflectionUtils.fieldToGetMethod(packetClazz, field)), field, fieldRegistration);
}
}
builder.append("}");
return builder.toString();
}
// see: ProtocolRegistration.read()
private static String readMethodBody(ProtocolRegistration registration) throws NoSuchMethodException {
short protocolId = registration.getId();
Constructor<?> constructor = registration.getConstructor();
Field[] fields = registration.getFields();
IFieldRegistration[] fieldRegistrations = registration.getFieldRegistrations();
StringBuilder builder = new StringBuilder();
builder.append("{");
builder.append("if(!" + EnhanceUtils.byteBufUtilsReadBoolean + "){")
.append("return null;}");
Class<?> packetClazz = constructor.getDeclaringClass();
builder.append(packetClazz.getCanonicalName() + " packet=new " + packetClazz.getCanonicalName() + "();");
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
IFieldRegistration fieldRegistration = fieldRegistrations[i];
String readObject = enhanceSerializer(fieldRegistration.serializer()).readObject(builder, field, fieldRegistration);
if (Modifier.isPublic(field.getModifiers())) {
builder.append(StringUtils.format("packet.{}={};", field.getName(), readObject));
} else {
builder.append(StringUtils.format("packet.{}({});", ReflectionUtils.fieldToSetMethod(packetClazz, field), readObject));
}
}
builder.append("return packet;}");
return builder.toString();
}
public static String getProtocolRegistrationFieldNameByProtocolId(short id) {
return StringUtils.format("{}{}", StringUtils.uncapitalize(ProtocolRegistration.class.getSimpleName()), id);
}
}
@@ -0,0 +1,37 @@
/*
* 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.registration;
import com.zfoo.protocol.IPacket;
import io.netty.buffer.ByteBuf;
import java.lang.reflect.Constructor;
/**
* @author jaysunxiao
* @version 3.0
*/
public interface IProtocolRegistration {
short protocolId();
byte module();
Constructor<?> protocolConstructor();
Object read(ByteBuf buffer);
void write(ByteBuf buffer, IPacket packet);
}
@@ -0,0 +1,127 @@
/*
* 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.registration;
import com.zfoo.protocol.util.AssertionUtils;
import com.zfoo.protocol.util.StringUtils;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ProtocolModule {
public static final ProtocolModule DEFAULT_PROTOCOL_MODULE = new ProtocolModule((byte) 0, "default", "1.0.0");
private byte id;
private String name;
/**
* 1.xxx.xxx,将1.0.0转化为1000000
*/
private int version;
private transient int hash;
public ProtocolModule(byte id, String name, String version) {
if (id < 0) {
throw new IllegalArgumentException(StringUtils.format("模块[{}]的id[{}]必须大于0", name, id));
}
this.id = id;
this.name = name;
this.version = versionStrToNum(version);
this.perfectHash();
}
public ProtocolModule(String name) {
this.name = name;
}
public static void assertVersion(String version) {
if (!version.matches("[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}")) {
throw new IllegalArgumentException(StringUtils
.format("[version:{}] must like xxx.xxx.xxx", version));
}
}
public static int versionStrToNum(String version) {
assertVersion(version);
var splits = version.split("\\" + StringUtils.PERIOD);
var versionNum = Integer.parseInt(splits[0]) * 1_000_000 + Integer.parseInt(splits[1]) * 1_000 + Integer.parseInt(splits[2]);
var newVersionStr = versionNumToStr(versionNum);
AssertionUtils.isTrue(version.equals(newVersionStr), "版本号转换前[{}]和转换后不相等[{}]", version, newVersionStr);
return versionNum;
}
public static String versionNumToStr(int version) {
var versionStr = version / 1_000_000 + StringUtils.PERIOD +
version / 1_000 % 1_000 + StringUtils.PERIOD +
version % 1_000;
assertVersion(versionStr);
return versionStr;
}
public void perfectHash() {
this.hash = id * 1_000_000 + this.version;
}
public byte getId() {
return id;
}
public void setId(byte id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ProtocolModule module = (ProtocolModule) o;
return id == module.id && version == module.version;
}
@Override
public int hashCode() {
return this.hash;
}
@Override
public String toString() {
return StringUtils.format("[id:{}][name:{}][version:{}][hash:{}]", id, name, version, hash);
}
}
@@ -0,0 +1,144 @@
/*
* 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.registration;
import com.zfoo.protocol.IPacket;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.ISerializer;
import com.zfoo.protocol.util.ReflectionUtils;
import io.netty.buffer.ByteBuf;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* 协议必须为一个简单的POJO对象,必须有一个标识为private static final transient的PROTOCOL_ID号
* 必须实现IPacket接口,返回的protocolId必须和PROTOCOL_ID号一致
*
* @author jaysunxiao
* @version 3.0
*/
public class ProtocolRegistration implements IProtocolRegistration {
private short id;
private byte module;
private Constructor<?> constructor;
private Field[] fields;
/**
* 所有的协议里的发送顺序都是按字段名称排序
*/
private IFieldRegistration[] fieldRegistrations;
public ProtocolRegistration() {
}
@Override
public short protocolId() {
return id;
}
@Override
public byte module() {
return module;
}
@Override
public Constructor<?> protocolConstructor() {
return constructor;
}
@Override
public Object read(ByteBuf buffer) {
if (!ByteBufUtils.readBoolean(buffer)) {
return null;
}
Object object = ReflectionUtils.newInstance(constructor);
for (int i = 0, length = fields.length; i < length; i++) {
Field field = fields[i];
IFieldRegistration packetFieldRegistration = fieldRegistrations[i];
ISerializer serializer = packetFieldRegistration.serializer();
Object fieldValue = serializer.readObject(buffer, packetFieldRegistration);
ReflectionUtils.setField(field, object, fieldValue);
}
return object;
}
@Override
public void write(ByteBuf buffer, IPacket packet) {
if (packet == null) {
ByteBufUtils.writeBoolean(buffer, false);
return;
}
ByteBufUtils.writeBoolean(buffer, true);
for (int i = 0, length = fields.length; i < length; i++) {
Field field = fields[i];
IFieldRegistration packetFieldRegistration = fieldRegistrations[i];
ISerializer serializer = packetFieldRegistration.serializer();
Object fieldValue = ReflectionUtils.getField(field, packet);
serializer.writeObject(buffer, fieldValue, packetFieldRegistration);
}
}
public short getId() {
return id;
}
public void setId(short id) {
this.id = id;
}
public byte getModule() {
return module;
}
public void setModule(byte module) {
this.module = module;
}
public Field[] getFields() {
return fields;
}
public void setFields(Field[] fields) {
this.fields = fields;
}
public IFieldRegistration[] getFieldRegistrations() {
return fieldRegistrations;
}
public void setFieldRegistrations(IFieldRegistration[] fieldRegistrations) {
this.fieldRegistrations = fieldRegistrations;
}
public Constructor<?> getConstructor() {
return constructor;
}
public void setConstructor(Constructor<?> constructor) {
this.constructor = constructor;
}
}
@@ -0,0 +1,52 @@
/*
* 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.registration.field;
import com.zfoo.protocol.serializer.ArraySerializer;
import com.zfoo.protocol.serializer.ISerializer;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ArrayField implements IFieldRegistration {
private IFieldRegistration arrayElementRegistration;
private Field field;
public static ArrayField valueOf(Field field, IFieldRegistration arrayElementRegistration) {
ArrayField arrayField = new ArrayField();
arrayField.field = field;
arrayField.arrayElementRegistration = arrayElementRegistration;
return arrayField;
}
public Field getField() {
return field;
}
@Override
public ISerializer serializer() {
return ArraySerializer.getInstance();
}
public IFieldRegistration getArrayElementRegistration() {
return arrayElementRegistration;
}
}
@@ -0,0 +1,40 @@
/*
* 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.registration.field;
import com.zfoo.protocol.serializer.ISerializer;
/**
* 一个包里所包含的变量还有这个变量的序列化器
* 描述booleanbyteshortintlongfloatdoublecharString等基本序列化器
*
* @author jaysunxiao
* @version 3.0
*/
public class BaseField implements IFieldRegistration {
private ISerializer serializer;
public static BaseField valueOf(ISerializer serializer) {
BaseField packetField = new BaseField();
packetField.serializer = serializer;
return packetField;
}
@Override
public ISerializer serializer() {
return serializer;
}
}
@@ -0,0 +1,28 @@
/*
* 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.registration.field;
import com.zfoo.protocol.serializer.ISerializer;
/**
* 标记性接口,所有协议里描述变量都要实现这个接口
*
* @author jaysunxiao
* @version 3.0
*/
public interface IFieldRegistration {
ISerializer serializer();
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.registration.field;
import com.zfoo.protocol.serializer.ISerializer;
import com.zfoo.protocol.serializer.ListSerializer;
import java.lang.reflect.Type;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ListField implements IFieldRegistration {
private IFieldRegistration listElementRegistration;
private Type type;
public static ListField valueOf(IFieldRegistration listElementRegistration, Type type) {
ListField listField = new ListField();
listField.listElementRegistration = listElementRegistration;
listField.type = type;
return listField;
}
@Override
public ISerializer serializer() {
return ListSerializer.getInstance();
}
public IFieldRegistration getListElementRegistration() {
return listElementRegistration;
}
public Type getType() {
return this.type;
}
}
@@ -0,0 +1,57 @@
/*
* 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.registration.field;
import com.zfoo.protocol.serializer.ISerializer;
import com.zfoo.protocol.serializer.MapSerializer;
import java.lang.reflect.Type;
/**
* @author jaysunxiao
* @version 3.0
*/
public class MapField implements IFieldRegistration {
private IFieldRegistration mapKeyRegistration;
private IFieldRegistration mapValueRegistration;
private Type type;
public static MapField valueOf(IFieldRegistration mapKeyRegistration, IFieldRegistration mapValueRegistration, Type type) {
MapField mapField = new MapField();
mapField.mapKeyRegistration = mapKeyRegistration;
mapField.mapValueRegistration = mapValueRegistration;
mapField.type = type;
return mapField;
}
@Override
public ISerializer serializer() {
return MapSerializer.getInstance();
}
public IFieldRegistration getMapKeyRegistration() {
return mapKeyRegistration;
}
public IFieldRegistration getMapValueRegistration() {
return mapValueRegistration;
}
public Type getType() {
return type;
}
}
@@ -0,0 +1,44 @@
/*
* 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.registration.field;
import com.zfoo.protocol.serializer.ISerializer;
import com.zfoo.protocol.serializer.ObjectProtocolSerializer;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ObjectProtocolField implements IFieldRegistration {
/**
* 协议序列号是ProtocolRegistration的id
*/
private short protocolId;
public static ObjectProtocolField valueOf(short protocolId) {
ObjectProtocolField objectProtocolField = new ObjectProtocolField();
objectProtocolField.protocolId = protocolId;
return objectProtocolField;
}
public short getProtocolId() {
return protocolId;
}
@Override
public ISerializer serializer() {
return ObjectProtocolSerializer.getInstance();
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.registration.field;
import com.zfoo.protocol.serializer.ISerializer;
import com.zfoo.protocol.serializer.SetSerializer;
import java.lang.reflect.Type;
/**
* @author jaysunxiao
* @version 3.0
*/
public class SetField implements IFieldRegistration {
private IFieldRegistration setElementRegistration;
private Type type;
public static SetField valueOf(IFieldRegistration listElementRegistration, Type type) {
SetField setField = new SetField();
setField.setElementRegistration = listElementRegistration;
setField.type = type;
return setField;
}
@Override
public ISerializer serializer() {
return SetSerializer.getInstance();
}
public IFieldRegistration getSetElementRegistration() {
return setElementRegistration;
}
public Type getType() {
return type;
}
}
@@ -0,0 +1,81 @@
/*
* 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;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.ArrayField;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
import java.lang.reflect.Array;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ArraySerializer implements ISerializer {
private static final ArraySerializer SERIALIZER = new ArraySerializer();
private ArraySerializer() {
}
public static ArraySerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeInt(buffer, 0);
return;
}
ArrayField arrayField = (ArrayField) fieldRegistration;
int length = Array.getLength(object);
if (length == 0) {
ByteBufUtils.writeInt(buffer, 0);
return;
}
ByteBufUtils.writeInt(buffer, length);
for (int i = 0; i < length; i++) {
Object element = Array.get(object, i);
arrayField.getArrayElementRegistration().serializer().writeObject(buffer, element, arrayField.getArrayElementRegistration());
}
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
var length = ByteBufUtils.readInt(buffer);
ArrayField arrayField = (ArrayField) fieldRegistration;
if (length <= 0) {
return Array.newInstance(arrayField.getField().getType().getComponentType(), 0);
}
Object array = Array.newInstance(arrayField.getField().getType().getComponentType(), length);
for (var i = 0; i < length; i++) {
Object value = arrayField.getArrayElementRegistration().serializer().readObject(buffer, arrayField.getArrayElementRegistration());
Array.set(array, i, value);
}
return array;
}
}
@@ -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;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public class BooleanSerializer implements ISerializer {
private static final BooleanSerializer SERIALIZER = new BooleanSerializer();
private BooleanSerializer() {
}
public static BooleanSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeBoolean(buffer, Boolean.FALSE);
return;
}
ByteBufUtils.writeBoolean(buffer, (Boolean) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
return ByteBufUtils.readBoolean(buffer);
}
}
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ByteSerializer implements ISerializer {
private static final ByteSerializer SERIALIZER = new ByteSerializer();
private ByteSerializer() {
}
public static ByteSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeByte(buffer, (byte) 0);
return;
}
ByteBufUtils.writeByte(buffer, (Byte) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
return ByteBufUtils.readByte(buffer);
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CharSerializer implements ISerializer {
private static final CharSerializer SERIALIZER = new CharSerializer();
private CharSerializer() {
}
public static CharSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeChar(buffer, Character.MIN_VALUE);
return;
}
ByteBufUtils.writeChar(buffer, (Character) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
return ByteBufUtils.readChar(buffer);
}
}
@@ -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;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public class DoubleSerializer implements ISerializer {
private static final DoubleSerializer SERIALIZER = new DoubleSerializer();
private DoubleSerializer() {
}
public static DoubleSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeDouble(buffer, 0);
return;
}
ByteBufUtils.writeDouble(buffer, (Double) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
return ByteBufUtils.readDouble(buffer);
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public class FloatSerializer implements ISerializer {
private static final FloatSerializer SERIALIZER = new FloatSerializer();
private FloatSerializer() {
}
public static FloatSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeFloat(buffer, 0F);
return;
}
ByteBufUtils.writeFloat(buffer, (Float) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
return ByteBufUtils.readFloat(buffer);
}
}
@@ -0,0 +1,37 @@
/*
* 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;
import java.util.concurrent.atomic.AtomicInteger;
import static com.zfoo.protocol.util.StringUtils.TAB;
/**
* @author jaysunxiao
* @version 3.0
*/
public abstract class GenerateUtils {
public static AtomicInteger index = new AtomicInteger();
public static StringBuilder addTab(StringBuilder builder, int deep) {
builder.append(TAB.repeat(Math.max(0, deep)));
return builder;
}
public static void clear() {
index = null;
}
}
@@ -0,0 +1,29 @@
/*
* 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;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public interface ISerializer {
void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration);
Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration);
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public class IntSerializer implements ISerializer {
private static final IntSerializer SERIALIZER = new IntSerializer();
private IntSerializer() {
}
public static IntSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeInt(buffer, 0);
return;
}
ByteBufUtils.writeInt(buffer, (Integer) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
return ByteBufUtils.readInt(buffer);
}
}
@@ -0,0 +1,80 @@
/*
* 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;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ListField;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ListSerializer implements ISerializer {
private static final ListSerializer SERIALIZER = new ListSerializer();
private ListSerializer() {
}
public static ListSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeInt(buffer, 0);
return;
}
List<?> list = (List<?>) object;
ListField listField = (ListField) fieldRegistration;
int size = list.size();
if (size == 0) {
ByteBufUtils.writeInt(buffer, 0);
return;
}
ByteBufUtils.writeInt(buffer, size);
for (Object element : list) {
listField.getListElementRegistration().serializer().writeObject(buffer, element, listField.getListElementRegistration());
}
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
int size = ByteBufUtils.readInt(buffer);
if (size <= 0) {
return Collections.EMPTY_LIST;
}
ListField listField = (ListField) fieldRegistration;
List<Object> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
Object value = listField.getListElementRegistration().serializer().readObject(buffer, listField.getListElementRegistration());
list.add(value);
}
return list;
}
}
@@ -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;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public class LongSerializer implements ISerializer {
private static final LongSerializer SERIALIZER = new LongSerializer();
private LongSerializer() {
}
public static LongSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeLong(buffer, 0L);
return;
}
ByteBufUtils.writeLong(buffer, (Long) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
return ByteBufUtils.readLong(buffer);
}
}
@@ -0,0 +1,87 @@
/*
* 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;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.collection.CollectionUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.MapField;
import io.netty.buffer.ByteBuf;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* @author jaysunxiao
* @version 3.0
*/
public class MapSerializer implements ISerializer {
private static final MapSerializer SERIALIZER = new MapSerializer();
private MapSerializer() {
}
public static MapSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeInt(buffer, 0);
return;
}
Map<?, ?> map = (Map<?, ?>) object;
MapField mapField = (MapField) fieldRegistration;
int size = map.size();
if (size == 0) {
ByteBufUtils.writeInt(buffer, 0);
return;
}
ByteBufUtils.writeInt(buffer, size);
for (Map.Entry<?, ?> entry : map.entrySet()) {
mapField.getMapKeyRegistration().serializer().writeObject(buffer, entry.getKey(), mapField.getMapKeyRegistration());
mapField.getMapValueRegistration().serializer().writeObject(buffer, entry.getValue(), mapField.getMapValueRegistration());
}
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
int size = ByteBufUtils.readInt(buffer);
if (size <= 0) {
return Collections.EMPTY_MAP;
}
MapField mapField = (MapField) fieldRegistration;
Map<Object, Object> map = new HashMap<>(CollectionUtils.comfortableCapacity(size));
for (int i = 0; i < size; i++) {
Object key = mapField.getMapKeyRegistration().serializer().readObject(buffer, mapField.getMapKeyRegistration());
Object value = mapField.getMapValueRegistration().serializer().readObject(buffer, mapField.getMapValueRegistration());
map.put(key, value);
}
return map;
}
}
@@ -0,0 +1,58 @@
/*
* 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;
import com.zfoo.protocol.IPacket;
import com.zfoo.protocol.ProtocolManager;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ObjectProtocolField;
import io.netty.buffer.ByteBuf;
/**
* 只要是protocol都是使用FieldSerializer
*
* @author jaysunxiao
* @version 3.0
*/
public class ObjectProtocolSerializer implements ISerializer {
private static final ObjectProtocolSerializer SERIALIZER = new ObjectProtocolSerializer();
private ObjectProtocolSerializer() {
}
public static ObjectProtocolSerializer getInstance() {
return SERIALIZER;
}
/**
* @param buffer ByteBuf
* @param object 必须继承IPacket接口
*/
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
IProtocolRegistration protocol = ProtocolManager.getProtocol(objectProtocolField.getProtocolId());
protocol.write(buffer, (IPacket) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
IProtocolRegistration protocol = ProtocolManager.getProtocol(objectProtocolField.getProtocolId());
return protocol.read(buffer);
}
}
@@ -0,0 +1,83 @@
/*
* 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;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.collection.CollectionUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.SetField;
import io.netty.buffer.ByteBuf;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* @author jaysunxiao
* @version 3.0
*/
public class SetSerializer implements ISerializer {
private static final SetSerializer SERIALIZER = new SetSerializer();
private SetSerializer() {
}
public static SetSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeInt(buffer, 0);
return;
}
Set<?> set = (Set<?>) object;
SetField setField = (SetField) fieldRegistration;
int size = set.size();
if (size == 0) {
ByteBufUtils.writeInt(buffer, 0);
return;
}
ByteBufUtils.writeInt(buffer, size);
for (Object element : set) {
setField.getSetElementRegistration().serializer().writeObject(buffer, element, setField.getSetElementRegistration());
}
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
int size = ByteBufUtils.readInt(buffer);
if (size <= 0) {
return Collections.EMPTY_SET;
}
SetField setField = (SetField) fieldRegistration;
Set<Object> set = new HashSet<>(CollectionUtils.comfortableCapacity(size));
for (int i = 0; i < size; i++) {
Object value = setField.getSetElementRegistration().serializer().readObject(buffer, setField.getSetElementRegistration());
set.add(value);
}
return set;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public class ShortSerializer implements ISerializer {
private static final ShortSerializer SERIALIZER = new ShortSerializer();
private ShortSerializer() {
}
public static ShortSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
if (object == null) {
ByteBufUtils.writeShort(buffer, (short) 0);
return;
}
ByteBufUtils.writeShort(buffer, (Short) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
return ByteBufUtils.readShort(buffer);
}
}
@@ -0,0 +1,46 @@
/*
* 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;
import com.zfoo.protocol.buffer.ByteBufUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import io.netty.buffer.ByteBuf;
/**
* @author jaysunxiao
* @version 3.0
*/
public class StringSerializer implements ISerializer {
private static final StringSerializer SERIALIZER = new StringSerializer();
private StringSerializer() {
}
public static StringSerializer getInstance() {
return SERIALIZER;
}
@Override
public void writeObject(ByteBuf buffer, Object object, IFieldRegistration fieldRegistration) {
ByteBufUtils.writeString(buffer, (String) object);
}
@Override
public Object readObject(ByteBuf buffer, IFieldRegistration fieldRegistration) {
return ByteBufUtils.readString(buffer);
}
}
@@ -0,0 +1,110 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.cs;
import com.zfoo.protocol.registration.field.ArrayField;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsArraySerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
ArrayField arrayField = (ArrayField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if (({} == null) || ({}.Length == 0))", objectStr, objectStr)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("buffer.WriteInt(0);").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("else").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("buffer.WriteInt({}.Length);", objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
String length = "length" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("int {} = {}.Length;", length, objectStr)).append(LS);
String i = "i" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("for (int {} = 0; {} < {}; {}++)", i, i, length, i)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 2);
String element = "element" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("{} {} = {}[{}];", GenerateCsUtils.toCsClassName(arrayField.getField().getType().getComponentType().getSimpleName()), element, objectStr, i)).append(LS);
GenerateCsUtils.csSerializer(arrayField.getArrayElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, arrayField.getArrayElementRegistration());
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
var arrayField = (ArrayField) fieldRegistration;
var result = "result" + GenerateUtils.index.getAndIncrement();
var typeName = GenerateCsUtils.toCsClassName(arrayField.getField().getType().getComponentType().getSimpleName());
var i = "index" + GenerateUtils.index.getAndIncrement();
var size = "size" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("int {} = buffer.ReadInt();", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("{}[] {} = new {}[{}];", typeName, result, typeName, size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0)", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("for (int {} = 0; {} < {}; {}++)", i, i, size, i)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("{").append(LS);
var readObject = GenerateCsUtils.csSerializer(arrayField.getArrayElementRegistration().serializer())
.readObject(builder, deep + 2, field, arrayField.getArrayElementRegistration());
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}[{}] = {};", result, i, readObject));
builder.append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
return result;
}
}
@@ -0,0 +1,44 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsBooleanSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.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" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("bool {} = buffer.ReadBool();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsByteSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.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" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byte {} = buffer.ReadByte();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsCharSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("buffer.WriteChar({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("char {} = buffer.ReadChar();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsDoubleSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.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" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("double {} = buffer.ReadDouble();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsFloatSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.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" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("float {} = buffer.ReadFloat();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,44 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsIntSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.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" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("int {} = buffer.ReadInt();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,112 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ListField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsListSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
ListField listField = (ListField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} == null)", objectStr)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("buffer.WriteInt(0);").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("else").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("buffer.WriteInt({}.Count);", objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
String length = "length" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("int {} = {}.Count;", length, objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
String i = "i" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("for (int {} = 0; {} < {}; {}++)", i, i, length, i)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 2);
String element = "element" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("var {} = {}[{}];", element, objectStr, i)).append(LS);
GenerateCsUtils.csSerializer(listField.getListElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, listField.getListElementRegistration());
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
var listField = (ListField) fieldRegistration;
var result = "result" + GenerateUtils.index.getAndIncrement();
var typeName = GenerateCsUtils.toCsClassName(listField.getType().toString());
var i = "index" + GenerateUtils.index.getAndIncrement();
var size = "size" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("int {} = buffer.ReadInt();", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("var {} = new {}({});", result, typeName, size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0)", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("for (int {} = 0; {} < {}; {}++)", i, i, size, i)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("{").append(LS);
var readObject = GenerateCsUtils.csSerializer(listField.getListElementRegistration().serializer())
.readObject(builder, deep + 2, field, listField.getListElementRegistration());
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.Add({});", result, readObject)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsLongSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.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" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("long {} = buffer.ReadLong();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,122 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.MapField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsMapSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
MapField mapField = (MapField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if (({} == null) || ({}.Count == 0))", objectStr, objectStr)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("buffer.WriteInt(0);").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("else").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("buffer.WriteInt({}.Count);", objectStr)).append(LS);
String i = "i" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("foreach (var {} in {})", i, objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 2);
String key = "keyElement" + GenerateUtils.index.getAndIncrement();
String value = "valueElement" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("var {} = {}.Key;", key, i)).append(LS);
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("var {} = {}.Value;", value, i)).append(LS);
GenerateCsUtils.csSerializer(mapField.getMapKeyRegistration().serializer())
.writeObject(builder, key, deep + 2, field, mapField.getMapKeyRegistration());
GenerateCsUtils.csSerializer(mapField.getMapValueRegistration().serializer())
.writeObject(builder, value, deep + 2, field, mapField.getMapValueRegistration());
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
MapField mapField = (MapField) fieldRegistration;
String result = "result" + GenerateUtils.index.getAndIncrement();
var typeName = GenerateCsUtils.toCsClassName(mapField.getType().toString());
GenerateUtils.addTab(builder, deep);
String size = "size" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("int {} = buffer.ReadInt();", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("var {} = new {}({});", result, typeName, size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0)", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
String i = "index" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("for (var {} = 0; {} < {}; {}++)", i, i, size, i)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("{").append(LS);
String keyObject = GenerateCsUtils.csSerializer(mapField.getMapKeyRegistration().serializer())
.readObject(builder, deep + 2, field, mapField.getMapKeyRegistration());
String valueObject = GenerateCsUtils.csSerializer(mapField.getMapValueRegistration().serializer())
.readObject(builder, deep + 2, field, mapField.getMapValueRegistration());
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}[{}] = {};", result, keyObject, valueObject)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
return result;
}
}
@@ -0,0 +1,56 @@
/*
* 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.cs;
import com.zfoo.protocol.ProtocolManager;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ObjectProtocolField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsObjectProtocolSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("ProtocolManager.GetProtocol({}).Write(buffer, {});", objectProtocolField.getProtocolId(), objectStr))
.append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("{} {} = ({}) ProtocolManager.GetProtocol({}).Read(buffer);", getProtocolSimpleName(objectProtocolField), result, getProtocolSimpleName(objectProtocolField), objectProtocolField.getProtocolId()))
.append(LS);
return result;
}
private String getProtocolSimpleName(ObjectProtocolField objectProtocolField) {
return ProtocolManager.getProtocol(objectProtocolField.getProtocolId()).protocolConstructor().getDeclaringClass().getSimpleName();
}
}
@@ -0,0 +1,105 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.SetField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsSetSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
SetField setField = (SetField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} == null)", objectStr)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("buffer.WriteInt(0);").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("else").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("buffer.WriteInt({}.Count);", objectStr)).append(LS);
String element = "i" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("foreach (var {} in {})", element, objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("{").append(LS);
GenerateCsUtils.csSerializer(setField.getSetElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, setField.getSetElementRegistration());
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
SetField setField = (SetField) fieldRegistration;
var result = "result" + GenerateUtils.index.getAndIncrement();
var typeName = GenerateCsUtils.toCsClassName(setField.getType().toString());
var i = "index" + GenerateUtils.index.getAndIncrement();
var size = "size" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("int {} = buffer.ReadInt();", size)).append(LS);
GenerateUtils.addTab(builder, deep);
// unity里不支持HashSet的初始化大小
// builder.append("var " + result + " = new " + typeName + "(" + size + ");" + LS);
builder.append(StringUtils.format("var {} = new {}();", result, typeName)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0)", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("{").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("for (int {} = 0; {} < {}; {}++)", i, i, size, i)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("{").append(LS);
var readObject = GenerateCsUtils.csSerializer(setField.getSetElementRegistration().serializer())
.readObject(builder, deep + 2, field, setField.getSetElementRegistration());
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.Add({});", result, readObject)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsShortSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.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" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("short {} = buffer.ReadShort();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,46 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class CsStringSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.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" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("string {} = buffer.ReadString();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,384 @@
/*
* 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.cs;
import com.zfoo.protocol.generate.GenerateProtocolDocument;
import com.zfoo.protocol.generate.GenerateProtocolPath;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.*;
import com.zfoo.protocol.util.ClassUtils;
import com.zfoo.protocol.util.FileUtils;
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.stream.Collectors;
import static com.zfoo.protocol.util.FileUtils.LS;
import static com.zfoo.protocol.util.StringUtils.TAB;
/**
* @author jaysunxiao
* @version 3.0
*/
public abstract class GenerateCsUtils {
private static final String PROTOCOL_OUTPUT_ROOT_PATH = "CsProtocol/";
private static Map<ISerializer, ICsSerializer> csSerializerMap;
public static ICsSerializer csSerializer(ISerializer serializer) {
return csSerializerMap.get(serializer);
}
public static void init() {
FileUtils.deleteFile(new File(PROTOCOL_OUTPUT_ROOT_PATH));
FileUtils.createDirectory(PROTOCOL_OUTPUT_ROOT_PATH);
csSerializerMap = new HashMap<>();
csSerializerMap.put(BooleanSerializer.getInstance(), new CsBooleanSerializer());
csSerializerMap.put(ByteSerializer.getInstance(), new CsByteSerializer());
csSerializerMap.put(ShortSerializer.getInstance(), new CsShortSerializer());
csSerializerMap.put(IntSerializer.getInstance(), new CsIntSerializer());
csSerializerMap.put(LongSerializer.getInstance(), new CsLongSerializer());
csSerializerMap.put(FloatSerializer.getInstance(), new CsFloatSerializer());
csSerializerMap.put(DoubleSerializer.getInstance(), new CsDoubleSerializer());
csSerializerMap.put(CharSerializer.getInstance(), new CsCharSerializer());
csSerializerMap.put(StringSerializer.getInstance(), new CsStringSerializer());
csSerializerMap.put(ArraySerializer.getInstance(), new CsArraySerializer());
csSerializerMap.put(ListSerializer.getInstance(), new CsListSerializer());
csSerializerMap.put(SetSerializer.getInstance(), new CsSetSerializer());
csSerializerMap.put(MapSerializer.getInstance(), new CsMapSerializer());
csSerializerMap.put(ObjectProtocolSerializer.getInstance(), new CsObjectProtocolSerializer());
}
public static void clear() {
csSerializerMap = null;
}
/**
* 生成协议依赖的工具类
*/
public static void createProtocolManager() throws IOException {
var list = List.of("cs/ProtocolManager.cs"
, "cs/IProtocolRegistration.cs"
, "cs/IPacket.cs"
, "cs/Buffer/ByteBuffer.cs"
, "cs/Buffer/LittleEndianByteBuffer.cs"
, "cs/Buffer/BigEndianByteBuffer.cs");
for (var fileName : list) {
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
var createFile = new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, StringUtils.substringAfterFirst(fileName, "cs/")));
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
}
}
/**
* 生成协议类
*/
public static void createCsProtocolFile(ProtocolRegistration registration) {
GenerateUtils.index.set(0);
var protocolId = registration.protocolId();
var registrationConstructor = registration.getConstructor();
IFieldRegistration[] fieldRegistrations = registration.getFieldRegistrations();
var protocolClazzName = registrationConstructor.getDeclaringClass().getSimpleName();
var csBuilder = new StringBuilder();
csBuilder.append("using System;").append(LS);
csBuilder.append("using System.Collections.Generic;").append(LS);
csBuilder.append("using CsProtocol.Buffer;").append(LS).append(LS);
csBuilder.append("namespace CsProtocol").append(LS);
csBuilder.append("{").append(LS);
// protocol object
csBuilder.append(protocolClass(registration));
csBuilder.append(TAB).append(StringUtils.format("public class {}Registration : IProtocolRegistration", protocolClazzName)).append(LS);
csBuilder.append(TAB).append("{").append(LS);
// ProtocolId method
csBuilder.append(packetProtocolId(registration));
// writeObject method
csBuilder.append(writeObject(registration));
// readObject method
csBuilder.append(readObject(registration));
csBuilder.append(TAB).append("}").append(LS);
csBuilder.append("}").append(LS);
var protocolOutputPath = StringUtils.format("{}{}/{}.cs"
, PROTOCOL_OUTPUT_ROOT_PATH
, GenerateProtocolPath.getCapitalizeProtocolPath(protocolId)
, protocolClazzName);
FileUtils.writeStringToFile(new File(protocolOutputPath), csBuilder.toString());
}
public static String toCsClassName(String typeName) {
typeName = typeName.replaceAll("java.util.|java.lang.", StringUtils.EMPTY);
typeName = typeName.replaceAll("com\\.[a-zA-Z0-9_.]*\\.", StringUtils.EMPTY);
// CSharp不适用基础类型的泛型会影响性能
switch (typeName) {
case "boolean":
case "Boolean":
typeName = "bool";
return typeName;
case "Byte":
typeName = "byte";
return typeName;
case "Short":
typeName = "short";
return typeName;
case "Integer":
typeName = "int";
return typeName;
case "Long":
typeName = "long";
return typeName;
case "Float":
typeName = "float";
return typeName;
case "Double":
typeName = "double";
return typeName;
case "Character":
typeName = "char";
return typeName;
case "String":
typeName = "string";
return typeName;
default:
}
// 将boolean转为bool
typeName = typeName.replace(" boolean ", " bool ");
typeName = typeName.replace(" Boolean ", " bool ");
typeName = typeName.replaceAll("[B|b]oolean\\[", "bool[");
typeName = typeName.replace("<Boolean", "<bool");
typeName = typeName.replace("Boolean>", "bool>");
// 将Byte转为byte
typeName = typeName.replace(" Byte ", " byte ");
typeName = typeName.replace("Byte[", "byte[");
typeName = typeName.replace("Byte>", "byte>");
typeName = typeName.replace("<Byte", "<byte");
// 将Short转为short
typeName = typeName.replace(" Short ", " short ");
typeName = typeName.replace("Short[", "short[");
typeName = typeName.replace("Short>", "short>");
typeName = typeName.replace("<Short", "<short");
// 将Integer转为int
typeName = typeName.replace(" Integer ", " int ");
typeName = typeName.replace("Integer[", "int[");
typeName = typeName.replace("Integer>", "int>");
typeName = typeName.replace("<Integer", "<int");
// 将Long转为long
typeName = typeName.replace(" Long ", " long ");
typeName = typeName.replace("Long[", "long[");
typeName = typeName.replace("Long>", "long>");
typeName = typeName.replace("<Long", "<long");
// 将Float转为float
typeName = typeName.replace(" Float ", " float ");
typeName = typeName.replace("Float[", "float[");
typeName = typeName.replace("Float>", "float>");
typeName = typeName.replace("<Float", "<float");
// 将Double转为double
typeName = typeName.replace(" Double ", " double ");
typeName = typeName.replace("Double[", "double[");
typeName = typeName.replace("Double>", "double>");
typeName = typeName.replace("<Double", "<double");
// 将Character转为Char
typeName = typeName.replace(" Character ", " char ");
typeName = typeName.replace("Character[", "char[");
typeName = typeName.replace("Character>", "char>");
typeName = typeName.replace("<Character", "<char");
// 将String转为string
typeName = typeName.replace("String ", "string ");
typeName = typeName.replace("String[", "string[");
typeName = typeName.replace("String>", "string>");
typeName = typeName.replace("<String", "<string");
// 将Map转为Dictionary
typeName = typeName.replace("Map<", "Dictionary<");
// 将Set转为HashSet
typeName = typeName.replace("Set<", "HashSet<");
// 将private转为public
typeName = typeName.replace(" private ", " public ");
return typeName;
}
private static String protocolClass(ProtocolRegistration registration) {
short protocolId = registration.getId();
Field[] fields = registration.getFields();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var protocolDocument = GenerateProtocolDocument.getProtocolDocument(protocolId);
var docTitle = protocolDocument.getKey();
var docFieldMap = protocolDocument.getValue();
var csBuilder = new StringBuilder();
if (!StringUtils.isBlank(docTitle)) {
Arrays.stream(docTitle.split(LS)).forEach(it -> csBuilder.append(TAB).append(it).append(LS));
}
csBuilder.append(TAB)
.append(StringUtils.format("public class {} : IPacket", protocolClazzName))
.append(LS);
csBuilder.append(TAB).append("{").append(LS);
// 协议的属性生成
var filedList = new ArrayList<Pair<String, String>>();
for (var field : fields) {
var propertyType = toCsClassName(field.getGenericType().getTypeName());
var propertyName = field.getName();
var propertyFullName = StringUtils.format("public {} {};", propertyType, propertyName);
// 生成注释
var doc = docFieldMap.get(propertyName);
if (!StringUtils.isBlank(doc)) {
Arrays.stream(doc.split(LS)).forEach(it -> csBuilder.append(TAB + TAB).append(it).append(LS));
}
csBuilder.append(TAB + TAB).append(propertyFullName).append(LS);
filedList.add(new Pair<>(propertyType, propertyName));
}
csBuilder.append(LS);
// ValueOf()方法
var valueOfParams = filedList.stream()
.map(it -> StringUtils.format("{} {}", it.getKey(), it.getValue()))
.collect(Collectors.toList());
csBuilder.append(TAB + TAB)
.append(StringUtils.format("public static {} ValueOf({})", protocolClazzName, StringUtils.joinWith(StringUtils.COMMA + " ", valueOfParams.toArray())))
.append(LS);
csBuilder.append(TAB + TAB).append("{").append(LS);
csBuilder.append(TAB + TAB + TAB)
.append(StringUtils.format("var packet = new {}();", protocolClazzName))
.append(LS);
filedList.forEach(it -> csBuilder.append(TAB + TAB + TAB).append(StringUtils.format("packet.{} = {};", it.getValue(), it.getValue())).append(LS));
csBuilder.append(TAB + TAB + TAB).append("return packet;").append(LS);
csBuilder.append(TAB + TAB).append("}").append(LS);
csBuilder.append(LS).append(LS);
// ProtocolId()方法
csBuilder.append(TAB + TAB).append("public short ProtocolId()").append(LS);
csBuilder.append(TAB + TAB).append("{").append(LS);
csBuilder.append(TAB + TAB + TAB).append(StringUtils.format("return {};", registration.protocolId())).append(LS);
csBuilder.append(TAB + TAB).append("}").append(LS);
csBuilder.append(TAB).append("}").append(LS);
csBuilder.append(LS).append(LS);
return csBuilder.toString();
}
private static String packetProtocolId(ProtocolRegistration registration) {
var csBuilder = new StringBuilder();
csBuilder.append(TAB + TAB).append("public short ProtocolId()").append(LS);
csBuilder.append(TAB + TAB).append("{").append(LS);
csBuilder.append(TAB + TAB + TAB).append(StringUtils.format("return {};", registration.protocolId())).append(LS);
csBuilder.append(TAB + TAB).append("}");
csBuilder.append(LS).append(LS);
return csBuilder.toString();
}
private static String writeObject(ProtocolRegistration registration) {
Field[] fields = registration.getFields();
IFieldRegistration[] fieldRegistrations = registration.getFieldRegistrations();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var csBuilder = new StringBuilder();
csBuilder.append(TAB + TAB).append("public void Write(ByteBuffer buffer, IPacket packet)").append(LS);
csBuilder.append(TAB + TAB).append("{").append(LS);
csBuilder.append(TAB + TAB + TAB).append("if (packet == null)").append(LS);
csBuilder.append(TAB + TAB + TAB).append("{").append(LS);
csBuilder.append(TAB + TAB + TAB + TAB).append("buffer.WriteBool(false);").append(LS);
csBuilder.append(TAB + TAB + TAB + TAB).append("return;").append(LS);
csBuilder.append(TAB + TAB + TAB + "}").append(LS);
csBuilder.append(TAB + TAB + TAB).append("buffer.WriteBool(true);").append(LS);
csBuilder.append(TAB + TAB + TAB)
.append(StringUtils.format("{} message = ({}) packet;", protocolClazzName, protocolClazzName))
.append(LS);
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
IFieldRegistration fieldRegistration = fieldRegistrations[i];
csSerializer(fieldRegistration.serializer()).writeObject(csBuilder, "message." + field.getName(), 3, field, fieldRegistration);
}
csBuilder.append(TAB + TAB + "}").append(LS).append(LS);
return csBuilder.toString();
}
private static String readObject(ProtocolRegistration registration) {
Field[] fields = registration.getFields();
IFieldRegistration[] fieldRegistrations = registration.getFieldRegistrations();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var csBuilder = new StringBuilder();
csBuilder.append(TAB + TAB).append("public IPacket Read(ByteBuffer buffer)").append(LS);
csBuilder.append(TAB + TAB).append("{").append(LS);
csBuilder.append(TAB + TAB + TAB).append("if (!buffer.ReadBool())").append(LS);
csBuilder.append(TAB + TAB + TAB).append("{").append(LS);
csBuilder.append(TAB + TAB + TAB + TAB).append("return null;").append(LS);
csBuilder.append(TAB + TAB + TAB).append("}").append(LS);
csBuilder.append(TAB + TAB + TAB)
.append(StringUtils.format("{} packet = new {}();", protocolClazzName, protocolClazzName))
.append(LS);
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
IFieldRegistration fieldRegistration = fieldRegistrations[i];
String readObject = csSerializer(fieldRegistration.serializer()).readObject(csBuilder, 3, field, fieldRegistration);
csBuilder.append(TAB + TAB + TAB)
.append(StringUtils.format("packet.{} = {};", field.getName(), readObject))
.append(LS);
}
csBuilder.append(TAB + TAB + TAB).append("return packet;").append(LS);
csBuilder.append(TAB + TAB).append("}").append(LS);
return csBuilder.toString();
}
}
@@ -0,0 +1,30 @@
/*
* 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.cs;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public interface ICsSerializer {
void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration);
String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration);
}
@@ -0,0 +1,189 @@
/*
* 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.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.ArrayField;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceArraySerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
var arrayField = (ArrayField) fieldRegistration;
var arrayName = getArrayClassName(arrayField);
switch (arrayName) {
case "boolean":
builder.append(StringUtils.format("{}.writeBooleanArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "Boolean":
builder.append(StringUtils.format("{}.writeBooleanBoxArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "byte":
builder.append(StringUtils.format("{}.writeByteArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "Byte":
builder.append(StringUtils.format("{}.writeByteBoxArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "short":
builder.append(StringUtils.format("{}.writeShortArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "Short":
builder.append(StringUtils.format("{}.writeShortBoxArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "int":
builder.append(StringUtils.format("{}.writeIntArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "Integer":
builder.append(StringUtils.format("{}.writeIntBoxArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "long":
builder.append(StringUtils.format("{}.writeLongArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "Long":
builder.append(StringUtils.format("{}.writeLongBoxArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "float":
builder.append(StringUtils.format("{}.writeFloatArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "Float":
builder.append(StringUtils.format("{}.writeFloatBoxArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "double":
builder.append(StringUtils.format("{}.writeDoubleArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "Double":
builder.append(StringUtils.format("{}.writeDoubleBoxArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "String":
builder.append(StringUtils.format("{}.writeStringArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "char":
builder.append(StringUtils.format("{}.writeCharArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "Character":
builder.append(StringUtils.format("{}.writeCharBoxArray($1, {});", EnhanceUtils.byteBufUtils, objectStr));
return;
default:
}
var array = "array" + GenerateUtils.index.getAndIncrement();
var length = "length" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("{}[] {} = {};", arrayName, array, objectStr));
builder.append(StringUtils.format("int {} = ArrayUtils.length({});", length, array));
builder.append(StringUtils.format("{}.writeInt($1,{});", EnhanceUtils.byteBufUtils, length));
var i = "i" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("for(int {}=0; {}<{}; {}++){", i, i, length, i));
var element = "element" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("{} {} = {}[{}];", arrayName, element, array, i));
EnhanceUtils.enhanceSerializer(arrayField.getArrayElementRegistration().serializer())
.writeObject(builder, element, arrayField.getField(), arrayField.getArrayElementRegistration());
builder.append("}");
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var arrayField = (ArrayField) fieldRegistration;
var arrayName = getArrayClassName(arrayField);
var array = "array" + GenerateUtils.index.getAndIncrement();
switch (arrayName) {
case "boolean":
builder.append(StringUtils.format("{}[] {} = {}.readBooleanArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "Boolean":
builder.append(StringUtils.format("{}[] {} = {}.readBooleanBoxArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "byte":
builder.append(StringUtils.format("{}[] {} = {}.readByteArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "Byte":
builder.append(StringUtils.format("{}[] {} = {}.readByteBoxArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "short":
builder.append(StringUtils.format("{}[] {} = {}.readShortArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "Short":
builder.append(StringUtils.format("{}[] {} = {}.readShortBoxArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "int":
builder.append(StringUtils.format("{}[] {} = {}.readIntArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "Integer":
builder.append(StringUtils.format("{}[] {} = {}.readIntBoxArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "long":
builder.append(StringUtils.format("{}[] {} = {}.readLongArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "Long":
builder.append(StringUtils.format("{}[] {} = {}.readLongBoxArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "float":
builder.append(StringUtils.format("{}[] {} = {}.readFloatArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "Float":
builder.append(StringUtils.format("{}[] {} = {}.readFloatBoxArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "double":
builder.append(StringUtils.format("{}[] {} = {}.readDoubleArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "Double":
builder.append(StringUtils.format("{}[] {} = {}.readDoubleBoxArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "String":
builder.append(StringUtils.format("{}[] {} = {}.readStringArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "char":
builder.append(StringUtils.format("{}[] {} = {}.readCharArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
case "Character":
builder.append(StringUtils.format("{}[] {} = {}.readCharBoxArray($1);", arrayName, array, EnhanceUtils.byteBufUtils));
return array;
default:
}
var length = "length" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("int {} = {}.readInt($1);", length, EnhanceUtils.byteBufUtils));
builder.append(StringUtils.format("{}[] {} = new {}[{}];", arrayName, array, arrayName, length));
var i = "i" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("for(int {}=0; {} < {}; {}++){", i, i, length, i));
var readObject = EnhanceUtils.enhanceSerializer(arrayField.getArrayElementRegistration().serializer())
.readObject(builder, arrayField.getField(), arrayField.getArrayElementRegistration());
builder.append(StringUtils.format("{}[{}] = {};}", array, i, readObject));
return array;
}
private String getArrayClassName(ArrayField arrayField) {
// 去掉包装类型的前缀java.lang
return arrayField.getField().getType().getComponentType().getCanonicalName().replaceFirst("java.lang.", StringUtils.EMPTY);
}
}
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceBooleanSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("{}.writeBoolean($1, {});", EnhanceUtils.byteBufUtils, objectStr));
} else {
builder.append(StringUtils.format("{}.writeBooleanBox($1, (Boolean){});", EnhanceUtils.byteBufUtils, objectStr));
}
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var result = "result" + GenerateUtils.index.getAndIncrement();
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("boolean {} = {}.readBoolean($1);", result, EnhanceUtils.byteBufUtils));
} else {
builder.append(StringUtils.format("Boolean {} = {}.readBooleanBox($1);", result, EnhanceUtils.byteBufUtils));
}
return result;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceByteSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("{}.writeByte($1, {});", EnhanceUtils.byteBufUtils, objectStr));
} else {
builder.append(StringUtils.format("{}.writeByteBox($1, (Byte){});", EnhanceUtils.byteBufUtils, objectStr));
}
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var result = "result" + GenerateUtils.index.getAndIncrement();
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("byte {} = {}.readByte($1);", result, EnhanceUtils.byteBufUtils));
} else {
builder.append(StringUtils.format("Byte {} = {}.readByteBox($1);", result, EnhanceUtils.byteBufUtils));
}
return result;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceCharSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("{}.writeChar($1,{});", EnhanceUtils.byteBufUtils, objectStr));
} else {
builder.append(StringUtils.format("{}.writeCharBox($1, (Character){});", EnhanceUtils.byteBufUtils, objectStr));
}
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var result = "result" + GenerateUtils.index.getAndIncrement();
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("char {} = {}.readChar($1);", result, EnhanceUtils.byteBufUtils));
} else {
builder.append(StringUtils.format("Character {} = {}.readCharBox($1);", result, EnhanceUtils.byteBufUtils));
}
return result;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceDoubleSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("{}.writeDouble($1, {});", EnhanceUtils.byteBufUtils, objectStr));
} else {
builder.append(StringUtils.format("{}.writeDoubleBox($1, (Double){});", EnhanceUtils.byteBufUtils, objectStr));
}
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var result = "result" + GenerateUtils.index.getAndIncrement();
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("double {} = {}.readDouble($1);", result, EnhanceUtils.byteBufUtils));
} else {
builder.append(StringUtils.format("Double {} = {}.readDoubleBox($1);", result, EnhanceUtils.byteBufUtils));
}
return result;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceFloatSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("{}.writeFloat($1, {});", EnhanceUtils.byteBufUtils, objectStr));
} else {
builder.append(StringUtils.format("{}.writeFloatBox($1, (Float){});", EnhanceUtils.byteBufUtils, objectStr));
}
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var result = "result" + GenerateUtils.index.getAndIncrement();
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("float {} = {}.readFloat($1);", result, EnhanceUtils.byteBufUtils));
} else {
builder.append(StringUtils.format("Float {} = {}.readFloatBox($1);", result, EnhanceUtils.byteBufUtils));
}
return result;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceIntSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("{}.writeInt($1, {});", EnhanceUtils.byteBufUtils, objectStr));
} else {
builder.append(StringUtils.format("{}.writeIntBox($1, (Integer){});", EnhanceUtils.byteBufUtils, objectStr));
}
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var result = "result" + GenerateUtils.index.getAndIncrement();
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("int {} = {}.readInt($1);", result, EnhanceUtils.byteBufUtils));
} else {
builder.append(StringUtils.format("Integer {} = {}.readIntBox($1);", result, EnhanceUtils.byteBufUtils));
}
return result;
}
}
@@ -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.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ListField;
import com.zfoo.protocol.registration.field.ObjectProtocolField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceListSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
var listField = (ListField) fieldRegistration;
switch (listField.getType().getTypeName()) {
case "java.util.List<java.lang.Integer>":
builder.append(StringUtils.format("{}.writeIntList($1, (List){});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "java.util.List<java.lang.Long>":
builder.append(StringUtils.format("{}.writeLongList($1, (List){});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "java.util.List<java.lang.String>":
builder.append(StringUtils.format("{}.writeStringList($1, (List){});", EnhanceUtils.byteBufUtils, objectStr));
return;
default:
}
// List<IPacket>
if (listField.getListElementRegistration() instanceof ObjectProtocolField) {
var objectProtocolField = (ObjectProtocolField) listField.getListElementRegistration();
builder.append(StringUtils.format("{}.writePacketList($1, (List){}, {});", EnhanceUtils.byteBufUtils, objectStr, EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(objectProtocolField.getProtocolId())));
return;
}
var list = "list" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("List {} = (List){};", list, objectStr));
builder.append(StringUtils.format("{}.writeInt($1, CollectionUtils.size({}));", EnhanceUtils.byteBufUtils, list));
var iterator = "iterator" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("Iterator {} = CollectionUtils.iterator({});", iterator, list));
builder.append(StringUtils.format("while({}.hasNext()){", iterator));
var element = "element" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("Object {}={}.next();", element, iterator));
EnhanceUtils.enhanceSerializer(listField.getListElementRegistration().serializer())
.writeObject(builder, element, field, listField.getListElementRegistration());
builder.append("}");
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var listField = (ListField) fieldRegistration;
var list = "list" + GenerateUtils.index.getAndIncrement();
switch (listField.getType().getTypeName()) {
case "java.util.List<java.lang.Integer>":
builder.append(StringUtils.format("List {} = {}.readIntList($1);", list, EnhanceUtils.byteBufUtils));
return list;
case "java.util.List<java.lang.Long>":
builder.append(StringUtils.format("List {} = {}.readLongList($1);", list, EnhanceUtils.byteBufUtils));
return list;
case "java.util.List<java.lang.String>":
builder.append(StringUtils.format("List {} = {}.readStringList($1);", list, EnhanceUtils.byteBufUtils));
return list;
default:
}
if (listField.getListElementRegistration() instanceof ObjectProtocolField) {
var objectProtocolField = (ObjectProtocolField) listField.getListElementRegistration();
builder.append(StringUtils.format("List {} = {}.readPacketList($1, {});", list, EnhanceUtils.byteBufUtils, EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(objectProtocolField.getProtocolId())));
return list;
}
var size = "size" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("int {}={}.readInt($1);", size, EnhanceUtils.byteBufUtils));
builder.append(StringUtils.format("List {} = CollectionUtils.newFixedList({});", list, size));
var i = "i" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("for(int {}=0; {}<{}; {}++){", i, i, size, i));
var readObject = EnhanceUtils.enhanceSerializer(listField.getListElementRegistration().serializer()).readObject(builder, field, listField.getListElementRegistration());
builder.append(StringUtils.format("{}.add({});}", list, readObject));
return list;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceLongSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("{}.writeLong($1, {});", EnhanceUtils.byteBufUtils, objectStr));
} else {
builder.append(StringUtils.format("{}.writeLongBox($1, (Long){});", EnhanceUtils.byteBufUtils, objectStr));
}
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var result = "result" + GenerateUtils.index.getAndIncrement();
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("long {} = {}.readLong($1);", result, EnhanceUtils.byteBufUtils));
} else {
builder.append(StringUtils.format("Long {} = {}.readLongBox($1);", result, EnhanceUtils.byteBufUtils));
}
return result;
}
}
@@ -0,0 +1,150 @@
/*
* 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.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.BaseField;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.MapField;
import com.zfoo.protocol.registration.field.ObjectProtocolField;
import com.zfoo.protocol.serializer.*;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import java.util.Map;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceMapSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
var mapField = (MapField) fieldRegistration;
var keyRegistration = mapField.getMapKeyRegistration();
var valueRegistration = mapField.getMapValueRegistration();
if (keyRegistration instanceof BaseField) {
if (valueRegistration instanceof BaseField) {
var keyBaseRegistration = (BaseField) keyRegistration;
var valueBaseRegistration = (BaseField) valueRegistration;
if (keyBaseRegistration.serializer() == IntSerializer.getInstance() && valueBaseRegistration.serializer() == IntSerializer.getInstance()) {
builder.append(StringUtils.format("{}.writeIntIntMap($1, (Map){});", EnhanceUtils.byteBufUtils, objectStr));
return;
} else if (keyBaseRegistration.serializer() == IntSerializer.getInstance() && valueBaseRegistration.serializer() == LongSerializer.getInstance()) {
builder.append(StringUtils.format("{}.writeIntLongMap($1, (Map){});", EnhanceUtils.byteBufUtils, objectStr));
return;
} else if (keyBaseRegistration.serializer() == LongSerializer.getInstance() && valueBaseRegistration.serializer() == IntSerializer.getInstance()) {
builder.append(StringUtils.format("{}.writeLongIntMap($1, (Map){});", EnhanceUtils.byteBufUtils, objectStr));
return;
} else if (keyBaseRegistration.serializer() == LongSerializer.getInstance() && valueBaseRegistration.serializer() == LongSerializer.getInstance()) {
builder.append(StringUtils.format("{}.writeLongLongMap($1, (Map){});", EnhanceUtils.byteBufUtils, objectStr));
return;
} else if (keyBaseRegistration.serializer() == IntSerializer.getInstance() && valueBaseRegistration.serializer() == StringSerializer.getInstance()) {
builder.append(StringUtils.format("{}.writeIntStringMap($1, (Map){});", EnhanceUtils.byteBufUtils, objectStr));
return;
}
} else if (valueRegistration instanceof ObjectProtocolField) {
var keyBaseRegistration = (BaseField) keyRegistration;
var valueProtocolRegistration = (ObjectProtocolField) valueRegistration;
if (keyBaseRegistration.serializer() == IntSerializer.getInstance() && valueProtocolRegistration.serializer() == ObjectProtocolSerializer.getInstance()) {
builder.append(StringUtils.format("{}.writeIntPacketMap($1, (Map){}, {});", EnhanceUtils.byteBufUtils, objectStr, EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(valueProtocolRegistration.getProtocolId())));
return;
} else if (keyBaseRegistration.serializer() == LongSerializer.getInstance() && valueProtocolRegistration.serializer() == ObjectProtocolSerializer.getInstance()) {
builder.append(StringUtils.format("{}.writeLongPacketMap($1, (Map){}, {});", EnhanceUtils.byteBufUtils, objectStr, EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(valueProtocolRegistration.getProtocolId())));
return;
}
}
}
var map = "map" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("Map {} = (Map){};", map, objectStr));
builder.append(StringUtils.format("{}.writeInt($1, CollectionUtils.size({}));", EnhanceUtils.byteBufUtils, map));
var iterator = "iterator" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("Iterator {} = CollectionUtils.iterator({});", iterator, map));
builder.append(StringUtils.format("while({}.hasNext()) {", iterator));
var entry = "entry" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("{} {}=({}){}.next();", Map.Entry.class.getCanonicalName(), entry, Map.Entry.class.getCanonicalName(), iterator));
var key = "key" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("Object {} = {}.getKey();", key, entry));
var value = "value" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("Object {} = {}.getValue();", value, entry));
EnhanceUtils.enhanceSerializer(keyRegistration.serializer()).writeObject(builder, key, field, keyRegistration);
EnhanceUtils.enhanceSerializer(valueRegistration.serializer()).writeObject(builder, value, field, valueRegistration);
builder.append("}");
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var mapField = (MapField) fieldRegistration;
var keyRegistration = mapField.getMapKeyRegistration();
var valueRegistration = mapField.getMapValueRegistration();
var map = "map" + GenerateUtils.index.getAndIncrement();
if (keyRegistration instanceof BaseField) {
if (valueRegistration instanceof BaseField) {
var keyBaseRegistration = (BaseField) keyRegistration;
var valueBaseRegistration = (BaseField) valueRegistration;
if (keyBaseRegistration.serializer() == IntSerializer.getInstance() && valueBaseRegistration.serializer() == IntSerializer.getInstance()) {
builder.append(StringUtils.format("Map {} = {}.readIntIntMap($1);", map, EnhanceUtils.byteBufUtils));
return map;
} else if (keyBaseRegistration.serializer() == IntSerializer.getInstance() && valueBaseRegistration.serializer() == LongSerializer.getInstance()) {
builder.append(StringUtils.format("Map {} = {}.readIntLongMap($1);", map, EnhanceUtils.byteBufUtils));
return map;
} else if (keyBaseRegistration.serializer() == LongSerializer.getInstance() && valueBaseRegistration.serializer() == IntSerializer.getInstance()) {
builder.append(StringUtils.format("Map {} = {}.readLongIntMap($1);", map, EnhanceUtils.byteBufUtils));
return map;
} else if (keyBaseRegistration.serializer() == LongSerializer.getInstance() && valueBaseRegistration.serializer() == LongSerializer.getInstance()) {
builder.append(StringUtils.format("Map {} = {}.readLongLongMap($1);", map, EnhanceUtils.byteBufUtils));
return map;
} else if (keyBaseRegistration.serializer() == IntSerializer.getInstance() && valueBaseRegistration.serializer() == StringSerializer.getInstance()) {
builder.append(StringUtils.format("Map {} = {}.readIntStringMap($1);", map, EnhanceUtils.byteBufUtils));
return map;
}
} else if (valueRegistration instanceof ObjectProtocolField) {
var keyBaseRegistration = (BaseField) keyRegistration;
var valueProtocolRegistration = (ObjectProtocolField) valueRegistration;
if (keyBaseRegistration.serializer() == IntSerializer.getInstance() && valueProtocolRegistration.serializer() == ObjectProtocolSerializer.getInstance()) {
builder.append(StringUtils.format("Map {} = {}.readIntPacketMap($1, {});", map, EnhanceUtils.byteBufUtils, EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(valueProtocolRegistration.getProtocolId())));
return map;
} else if (keyBaseRegistration.serializer() == LongSerializer.getInstance() && valueProtocolRegistration.serializer() == ObjectProtocolSerializer.getInstance()) {
builder.append(StringUtils.format("Map {} = {}.readLongPacketMap($1, {});", map, EnhanceUtils.byteBufUtils, EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(valueProtocolRegistration.getProtocolId())));
return map;
}
}
}
var size = "size" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("int {}={}.readInt($1);", size, EnhanceUtils.byteBufUtils));
builder.append(StringUtils.format("Map {} = CollectionUtils.newFixedMap({});", map, size));
var i = "i" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("for(int {}=0; {}<{}; {}++){", i, i, size, i));
var keyObject = EnhanceUtils.enhanceSerializer(keyRegistration.serializer()).readObject(builder, field, keyRegistration);
var valueObject = EnhanceUtils.enhanceSerializer(valueRegistration.serializer()).readObject(builder, field, valueRegistration);
builder.append(StringUtils.format("{}.put({},{});}", map, keyObject, valueObject));
return map;
}
}
@@ -0,0 +1,52 @@
/*
* 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.enhance;
import com.zfoo.protocol.ProtocolManager;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ObjectProtocolField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* 对应于ObjectProtocolSerializer
*
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceObjectProtocolSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
var objectProtocolField = (ObjectProtocolField) fieldRegistration;
builder.append(StringUtils.format("{}.write($1, (IPacket){});", EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(objectProtocolField.getProtocolId()), objectStr));
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var objectProtocolField = (ObjectProtocolField) fieldRegistration;
var result = "result" + GenerateUtils.index.getAndIncrement();
var protocolName = getProtocolClassCanonicalName(objectProtocolField.getProtocolId());
builder.append(StringUtils.format("{} {} = ({}){}.read($1);", protocolName, result, protocolName, EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(objectProtocolField.getProtocolId())));
return result;
}
private String getProtocolClassCanonicalName(short protocolId) {
return ProtocolManager.getProtocol(protocolId).protocolConstructor().getDeclaringClass().getCanonicalName();
}
}
@@ -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.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ObjectProtocolField;
import com.zfoo.protocol.registration.field.SetField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceSetSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
var setField = (SetField) fieldRegistration;
switch (setField.getType().getTypeName()) {
case "java.util.Set<java.lang.Integer>":
builder.append(StringUtils.format("{}.writeIntSet($1, (Set){});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "java.util.Set<java.lang.Long>":
builder.append(StringUtils.format("{}.writeLongSet($1, (Set){});", EnhanceUtils.byteBufUtils, objectStr));
return;
case "java.util.Set<java.lang.String>":
builder.append(StringUtils.format("{}.writeStringSet($1, (Set){});", EnhanceUtils.byteBufUtils, objectStr));
return;
default:
}
// Set<IPacket>
if (setField.getSetElementRegistration() instanceof ObjectProtocolField) {
var objectProtocolField = (ObjectProtocolField) setField.getSetElementRegistration();
builder.append(StringUtils.format("{}.writePacketSet($1, (Set){}, {});", EnhanceUtils.byteBufUtils, objectStr, EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(objectProtocolField.getProtocolId())));
return;
}
var set = "set" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("Set {} = (Set){};", set, objectStr));
builder.append(StringUtils.format("{}.writeInt($1, CollectionUtils.size({}));", EnhanceUtils.byteBufUtils, set));
var iterator = "iterator" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("Iterator {} = CollectionUtils.iterator({});", iterator, set));
builder.append(StringUtils.format("while({}.hasNext()) {", iterator));
var element = "element" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("Object {}={}.next();", element, iterator));
EnhanceUtils.enhanceSerializer(setField.getSetElementRegistration().serializer())
.writeObject(builder, element, field, setField.getSetElementRegistration());
builder.append("}");
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var setField = (SetField) fieldRegistration;
var set = "set" + GenerateUtils.index.getAndIncrement();
switch (setField.getType().getTypeName()) {
case "java.util.Set<java.lang.Integer>":
builder.append(StringUtils.format("Set {} = {}.readIntSet($1);", set, EnhanceUtils.byteBufUtils));
return set;
case "java.util.Set<java.lang.Long>":
builder.append(StringUtils.format("Set {} = {}.readLongSet($1);", set, EnhanceUtils.byteBufUtils));
return set;
case "java.util.Set<java.lang.String>":
builder.append(StringUtils.format("Set {} = {}.readStringSet($1);", set, EnhanceUtils.byteBufUtils));
return set;
default:
}
if (setField.getSetElementRegistration() instanceof ObjectProtocolField) {
var objectProtocolField = (ObjectProtocolField) setField.getSetElementRegistration();
builder.append(StringUtils.format("Set {} = {}.readPacketSet($1, {});", set, EnhanceUtils.byteBufUtils, EnhanceUtils.getProtocolRegistrationFieldNameByProtocolId(objectProtocolField.getProtocolId())));
return set;
}
var size = "size" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("int {} = {}.readInt($1);", size, EnhanceUtils.byteBufUtils));
builder.append(StringUtils.format("Set {} = CollectionUtils.newFixedSet({});", set, size));
var i = "i" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("for(int {}=0; {}<{}; {}++){", i, i, size, i));
var readObject = EnhanceUtils.enhanceSerializer(setField.getSetElementRegistration().serializer()).readObject(builder, field, setField.getSetElementRegistration());
builder.append(StringUtils.format("{}.add({});}", set, readObject));
return set;
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2020 The zfoo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.serializer.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceShortSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("{}.writeShort($1, {});", EnhanceUtils.byteBufUtils, objectStr));
} else {
builder.append(StringUtils.format("{}.writeShortBox($1, (Short){});", EnhanceUtils.byteBufUtils, objectStr));
}
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var result = "result" + GenerateUtils.index.getAndIncrement();
if (field.getType().isPrimitive() || (field.getType().isArray() && field.getType().getComponentType().isPrimitive())) {
builder.append(StringUtils.format("short {} = {}.readShort($1);", result, EnhanceUtils.byteBufUtils));
} else {
builder.append(StringUtils.format("Short {} = {}.readShortBox($1);", result, EnhanceUtils.byteBufUtils));
}
return result;
}
}
@@ -0,0 +1,41 @@
/*
* 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.enhance;
import com.zfoo.protocol.registration.EnhanceUtils;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public class EnhanceStringSerializer implements IEnhanceSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration) {
builder.append(StringUtils.format("{}.writeString($1, (String){});", EnhanceUtils.byteBufUtils, objectStr));
}
@Override
public String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration) {
var result = "result" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("String {} = {}.readString($1);", result, EnhanceUtils.byteBufUtils));
return result;
}
}
@@ -0,0 +1,39 @@
/*
* 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.enhance;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public interface IEnhanceSerializer {
/**
* IProtocolRegistration.write(ByteBuf buffer, IPacket packet);
* $1=buffer
* $2=packet
*/
void writeObject(StringBuilder builder, String objectStr, Field field, IFieldRegistration fieldRegistration);
/**
* IProtocolRegistration.Object read(ByteBuf buffer);
* $1=buffer
*/
String readObject(StringBuilder builder, Field field, IFieldRegistration fieldRegistration);
}
@@ -0,0 +1,277 @@
/*
* 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.js;
import com.zfoo.protocol.ProtocolManager;
import com.zfoo.protocol.collection.CollectionUtils;
import com.zfoo.protocol.generate.GenerateProtocolDocument;
import com.zfoo.protocol.generate.GenerateProtocolPath;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.*;
import com.zfoo.protocol.util.ClassUtils;
import com.zfoo.protocol.util.FileUtils;
import com.zfoo.protocol.util.IOUtils;
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.stream.Collectors;
import static com.zfoo.protocol.util.FileUtils.LS;
import static com.zfoo.protocol.util.StringUtils.TAB;
/**
* @author jaysunxiao
* @version 3.0
*/
public abstract class GenerateJsUtils {
private static final String PROTOCOL_OUTPUT_ROOT_PATH = "jsProtocol/";
private static Map<ISerializer, IJsSerializer> jsSerializerMap;
public static IJsSerializer jsSerializer(ISerializer serializer) {
return jsSerializerMap.get(serializer);
}
public static void init() {
FileUtils.deleteFile(new File(PROTOCOL_OUTPUT_ROOT_PATH));
FileUtils.createDirectory(PROTOCOL_OUTPUT_ROOT_PATH);
jsSerializerMap = new HashMap<>();
jsSerializerMap.put(BooleanSerializer.getInstance(), new JsBooleanSerializer());
jsSerializerMap.put(ByteSerializer.getInstance(), new JsByteSerializer());
jsSerializerMap.put(ShortSerializer.getInstance(), new JsShortSerializer());
jsSerializerMap.put(IntSerializer.getInstance(), new JsIntSerializer());
jsSerializerMap.put(LongSerializer.getInstance(), new JsLongSerializer());
jsSerializerMap.put(FloatSerializer.getInstance(), new JsFloatSerializer());
jsSerializerMap.put(DoubleSerializer.getInstance(), new JsDoubleSerializer());
jsSerializerMap.put(CharSerializer.getInstance(), new JsCharSerializer());
jsSerializerMap.put(StringSerializer.getInstance(), new JsStringSerializer());
jsSerializerMap.put(ArraySerializer.getInstance(), new JsArraySerializer());
jsSerializerMap.put(ListSerializer.getInstance(), new JsListSerializer());
jsSerializerMap.put(SetSerializer.getInstance(), new JsSetSerializer());
jsSerializerMap.put(MapSerializer.getInstance(), new JsMapSerializer());
jsSerializerMap.put(ObjectProtocolSerializer.getInstance(), new JsObjectProtocolSerializer());
}
public static void clear() {
jsSerializerMap = null;
}
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
var list = List.of("js/buffer/ByteBuffer.js"
, "js/buffer/long.js"
, "js/buffer/longbits.js");
for (var fileName : list) {
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
var createFile = new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, StringUtils.substringAfterFirst(fileName, "js/")));
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
}
// 生成ProtocolManager.js文件
var jsBuilder = new StringBuilder();
protocolList.stream()
.filter(it -> Objects.nonNull(it))
.forEach(it -> {
var name = it.protocolConstructor().getDeclaringClass().getSimpleName();
var path = GenerateProtocolPath.getProtocolPath(it.protocolId());
if (StringUtils.isBlank(path)) {
jsBuilder.append(StringUtils.format("import {} from './{}.js';", name, name)).append(LS);
} else {
jsBuilder.append(StringUtils.format("import {} from './{}/{}.js';", name, path, name)).append(LS);
}
});
jsBuilder.append(LS).append(LS);
var protocolManagerStr = StringUtils.bytesToString(IOUtils.toByteArray(ClassUtils.getFileFromClassPath("js/ProtocolManager.js")));
jsBuilder.append(protocolManagerStr);
jsBuilder.append("ProtocolManager.initProtocol = function initProtocol() {").append(LS);
protocolList.stream().filter(it -> Objects.nonNull(it))
.forEach(it -> jsBuilder.append(TAB).append(StringUtils.format("protocols.set({}, {});", it.protocolId(), it.protocolConstructor().getDeclaringClass().getSimpleName())).append(LS));
jsBuilder.append("};").append(LS + LS);
jsBuilder.append("export default ProtocolManager;").append(LS);
FileUtils.writeStringToFile(new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, "ProtocolManager.js")), jsBuilder.toString());
}
public static void createJsProtocolFile(ProtocolRegistration registration) {
// 初始化index
GenerateUtils.index.set(0);
var protocolId = registration.protocolId();
var registrationConstructor = registration.getConstructor();
var protocolClazzName = registrationConstructor.getDeclaringClass().getSimpleName();
var jsBuilder = new StringBuilder();
// 如果协议包含子协议则需要导入ProtocolManager
var subProtocols = ProtocolManager.getAllSubProtocolIds(protocolId);
if (CollectionUtils.isNotEmpty(subProtocols)) {
var path = GenerateProtocolPath.getProtocolPath(protocolId);
if (StringUtils.isBlank(path)) {
jsBuilder.append("import ProtocolManager from './ProtocolManager.js';").append(LS);
} else {
jsBuilder.append("import ProtocolManager from '");
Arrays.stream(path.split(StringUtils.SLASH)).forEach(it -> jsBuilder.append("../"));
jsBuilder.append("ProtocolManager.js';").append(LS);
}
}
// export object
jsBuilder.append(exportFunction(registration));
// protocolId method
jsBuilder.append(protocolIdFunction(registration));
// writeObject method
jsBuilder.append(writeObject(registration));
// readObject method
jsBuilder.append(readObject(registration));
jsBuilder.append(LS).append(StringUtils.format("export default {};", protocolClazzName)).append(LS);
var protocolOutputPath = StringUtils.format("{}{}/{}.js"
, PROTOCOL_OUTPUT_ROOT_PATH
, GenerateProtocolPath.getProtocolPath(protocolId)
, protocolClazzName);
FileUtils.writeStringToFile(new File(protocolOutputPath), jsBuilder.toString());
}
private static String exportFunction(ProtocolRegistration registration) {
var protocolId = registration.getId();
var fields = registration.getFields();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var protocolDocument = GenerateProtocolDocument.getProtocolDocument(protocolId);
var docTitle = protocolDocument.getKey();
var docFieldMap = protocolDocument.getValue();
var jsBuilder = new StringBuilder();
if (!StringUtils.isBlank(docTitle)) {
jsBuilder.append(docTitle).append(LS);
}
jsBuilder.append(StringUtils.format("const {} = function(", protocolClazzName));
jsBuilder.append(StringUtils.joinWith(", ", Arrays.stream(fields).map(it -> it.getName()).collect(Collectors.toList()).toArray()))
.append(") {")
.append(LS);
for (var field : fields) {
var propertyName = field.getName();
// 生成注释
var doc = docFieldMap.get(propertyName);
if (!StringUtils.isBlank(doc)) {
Arrays.stream(doc.split(LS)).forEach(it -> jsBuilder.append(TAB).append(it).append(LS));
}
jsBuilder.append(TAB)
.append(StringUtils.format("this.{} = {};", propertyName, propertyName))
// 生成类型的注释
.append(" // ").append(field.getGenericType().getTypeName())
.append(LS);
}
jsBuilder.append("};").append(LS).append(LS);
return jsBuilder.toString();
}
private static String protocolIdFunction(ProtocolRegistration registration) {
var protocolId = registration.getId();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var jsBuilder = new StringBuilder();
jsBuilder.append(StringUtils.format("{}.prototype.protocolId = function() {", protocolClazzName)).append(LS);
jsBuilder.append(TAB).append(StringUtils.format("return {};", protocolId)).append(LS);
jsBuilder.append("};").append(LS).append(LS);
return jsBuilder.toString();
}
private static String writeObject(ProtocolRegistration registration) {
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var jsBuilder = new StringBuilder();
jsBuilder.append(StringUtils.format("{}.writeObject = function(byteBuffer, packet) {", protocolClazzName)).append(LS);
jsBuilder.append(TAB).append("if (packet === null) {").append(LS);
jsBuilder.append(TAB + TAB).append("byteBuffer.writeBoolean(false);").append(LS);
jsBuilder.append(TAB + TAB).append("return;").append(LS);
jsBuilder.append(TAB).append("}").append(LS);
jsBuilder.append(TAB).append("byteBuffer.writeBoolean(true);").append(LS);
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
IFieldRegistration fieldRegistration = fieldRegistrations[i];
jsSerializer(fieldRegistration.serializer()).writeObject(jsBuilder, "packet." + field.getName(), 1, field, fieldRegistration);
}
jsBuilder.append("};").append(LS).append(LS);
return jsBuilder.toString();
}
private static String readObject(ProtocolRegistration registration) {
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var jsBuilder = new StringBuilder();
jsBuilder.append(StringUtils.format("{}.readObject = function(byteBuffer) {", protocolClazzName)).append(LS);
jsBuilder.append(TAB).append("if (!byteBuffer.readBoolean()) {").append(LS);
jsBuilder.append(TAB + TAB).append("return null;").append(LS);
jsBuilder.append(TAB).append("}").append(LS);
jsBuilder.append(TAB).append(StringUtils.format("const packet = new {}();", protocolClazzName)).append(LS);
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var fieldRegistration = fieldRegistrations[i];
var readObject = jsSerializer(fieldRegistration.serializer()).readObject(jsBuilder, 1, field, fieldRegistration);
jsBuilder.append(TAB).append(StringUtils.format("packet.{} = {};", field.getName(), readObject)).append(LS);
}
jsBuilder.append(TAB).append("return packet;").append(LS);
jsBuilder.append("};").append(LS);
return jsBuilder.toString();
}
}
@@ -0,0 +1,30 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public interface IJsSerializer {
void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration);
String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration);
}
@@ -0,0 +1,87 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.ArrayField;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsArraySerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
ArrayField arrayField = (ArrayField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} === null) {", objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("byteBuffer.writeInt(0);").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("} else {").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("byteBuffer.writeInt({}.length);", objectStr)).append(LS);
String element = "element" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("{}.forEach({} => {", objectStr, element)).append(LS);
GenerateJsUtils.jsSerializer(arrayField.getArrayElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, arrayField.getArrayElementRegistration());
GenerateUtils.addTab(builder, deep + 1);
builder.append("});").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
ArrayField arrayField = (ArrayField) fieldRegistration;
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = [];", result)).append(LS);
String i = "index" + GenerateUtils.index.getAndIncrement();
String size = "size" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readInt();", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("for (let {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS);
String readObject = GenerateJsUtils.jsSerializer(arrayField.getArrayElementRegistration().serializer())
.readObject(builder, deep + 2, field, arrayField.getArrayElementRegistration());
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.push({});", result, readObject)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsBooleanSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer.writeBoolean({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readBoolean(); ", result)).append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsByteSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer.writeByte({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readByte();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,43 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsCharSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer.writeChar({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readChar();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsDoubleSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer.writeDouble({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readDouble();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsFloatSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer.writeFloat({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readFloat();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,44 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsIntSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer.writeInt({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readInt();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,86 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ListField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsListSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
ListField listField = (ListField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} === null) {", objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("byteBuffer.writeInt(0);").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("} else {").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("byteBuffer.writeInt({}.length);", objectStr)).append(LS);
String element = "element" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("{}.forEach({} => {", objectStr, element)).append(LS);
GenerateJsUtils.jsSerializer(listField.getListElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, listField.getListElementRegistration());
GenerateUtils.addTab(builder, deep + 1);
builder.append("});").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
ListField listField = (ListField) fieldRegistration;
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = [];", result)).append(LS);
GenerateUtils.addTab(builder, deep);
String size = "size" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("const {} = byteBuffer.readInt();", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
String i = "index" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("for (let {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS);
String readObject = GenerateJsUtils.jsSerializer(listField.getListElementRegistration().serializer())
.readObject(builder, deep + 2, field, listField.getListElementRegistration());
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.push({});", result, readObject)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
return result;
}
}
@@ -0,0 +1,44 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsLongSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer.writeLong({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readLong();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,96 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.MapField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsMapSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
MapField mapField = (MapField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} === null) {", objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("byteBuffer.writeInt(0);").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("} else {").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("byteBuffer.writeInt({}.size);", objectStr)).append(LS);
String key = "key" + GenerateUtils.index.getAndIncrement();
String value = "value" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("{}.forEach(({}, {}) => {", objectStr, value, key)).append(LS);
GenerateJsUtils.jsSerializer(mapField.getMapKeyRegistration().serializer())
.writeObject(builder, key, deep + 2, field, mapField.getMapKeyRegistration());
GenerateJsUtils.jsSerializer(mapField.getMapValueRegistration().serializer())
.writeObject(builder, value, deep + 2, field, mapField.getMapValueRegistration());
GenerateUtils.addTab(builder, deep + 1);
builder.append("});").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
MapField mapField = (MapField) fieldRegistration;
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = new Map();", result)).append(LS);
GenerateUtils.addTab(builder, deep);
String size = "size" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("const {} = byteBuffer.readInt();", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS);
String i = "index" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("for (let {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS);
String keyObject = GenerateJsUtils.jsSerializer(mapField.getMapKeyRegistration().serializer())
.readObject(builder, deep + 2, field, mapField.getMapKeyRegistration());
String valueObject = GenerateJsUtils.jsSerializer(mapField.getMapValueRegistration().serializer())
.readObject(builder, deep + 2, field, mapField.getMapValueRegistration());
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.set({}, {});", result, keyObject, valueObject)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
return result;
}
}
@@ -0,0 +1,46 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.ObjectProtocolField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsObjectProtocolSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("ProtocolManager.getProtocol({}).writeObject(byteBuffer, {});", objectProtocolField.getProtocolId(), objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
ObjectProtocolField objectProtocolField = (ObjectProtocolField) fieldRegistration;
var result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = ProtocolManager.getProtocol({}).readObject(byteBuffer);", result, objectProtocolField.getProtocolId())).append(LS);
return result;
}
}
@@ -0,0 +1,86 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.registration.field.SetField;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsSetSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
SetField setField = (SetField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} === null) {", objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("byteBuffer.writeInt(0);").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("} else {").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("byteBuffer.writeInt({}.size);", objectStr)).append(LS);
String element = "element" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("{}.forEach({} => {", objectStr, element)).append(LS);
GenerateJsUtils.jsSerializer(setField.getSetElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, setField.getSetElementRegistration());
GenerateUtils.addTab(builder, deep + 1);
builder.append("});").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
SetField setField = (SetField) fieldRegistration;
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = new Set();", result)).append(LS);
GenerateUtils.addTab(builder, deep);
String size = "size" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("const {} = byteBuffer.readInt();", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if ({} > 0) {", size)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
String i = "index" + GenerateUtils.index.getAndIncrement();
builder.append(StringUtils.format("for (let {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS);
String readObject = GenerateJsUtils.jsSerializer(setField.getSetElementRegistration().serializer())
.readObject(builder, deep + 2, field, setField.getSetElementRegistration());
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("{}.add({});", result, readObject)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("}").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("}").append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsShortSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer.writeShort({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readShort();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,43 @@
/*
* 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.js;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class JsStringSerializer implements IJsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer.writeString({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("const {} = byteBuffer.readString();", result)).append(LS);
return result;
}
}
@@ -0,0 +1,301 @@
/*
* 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.lua;
import com.zfoo.protocol.ProtocolManager;
import com.zfoo.protocol.collection.CollectionUtils;
import com.zfoo.protocol.generate.GenerateProtocolDocument;
import com.zfoo.protocol.generate.GenerateProtocolPath;
import com.zfoo.protocol.registration.IProtocolRegistration;
import com.zfoo.protocol.registration.ProtocolRegistration;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.*;
import com.zfoo.protocol.util.ClassUtils;
import com.zfoo.protocol.util.FileUtils;
import com.zfoo.protocol.util.IOUtils;
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.stream.Collectors;
import static com.zfoo.protocol.util.FileUtils.LS;
import static com.zfoo.protocol.util.StringUtils.TAB;
/**
* @author jaysunxiao
* @version 3.0
*/
public abstract class GenerateLuaUtils {
private static final String PROTOCOL_OUTPUT_ROOT_PATH = "LuaProtocol/";
private static Map<ISerializer, ILuaSerializer> luaSerializerMap;
public static ILuaSerializer luaSerializer(ISerializer serializer) {
return luaSerializerMap.get(serializer);
}
public static void init() {
FileUtils.deleteFile(new File(PROTOCOL_OUTPUT_ROOT_PATH));
FileUtils.createDirectory(PROTOCOL_OUTPUT_ROOT_PATH);
luaSerializerMap = new HashMap<>();
luaSerializerMap.put(BooleanSerializer.getInstance(), new LuaBooleanSerializer());
luaSerializerMap.put(ByteSerializer.getInstance(), new LuaByteSerializer());
luaSerializerMap.put(ShortSerializer.getInstance(), new LuaShortSerializer());
luaSerializerMap.put(IntSerializer.getInstance(), new LuaIntSerializer());
luaSerializerMap.put(LongSerializer.getInstance(), new LuaLongSerializer());
luaSerializerMap.put(FloatSerializer.getInstance(), new LuaFloatSerializer());
luaSerializerMap.put(DoubleSerializer.getInstance(), new LuaDoubleSerializer());
luaSerializerMap.put(CharSerializer.getInstance(), new LuaCharSerializer());
luaSerializerMap.put(StringSerializer.getInstance(), new LuaStringSerializer());
luaSerializerMap.put(ArraySerializer.getInstance(), new LuaArraySerializer());
luaSerializerMap.put(ListSerializer.getInstance(), new LuaListSerializer());
luaSerializerMap.put(SetSerializer.getInstance(), new LuaSetSerializer());
luaSerializerMap.put(MapSerializer.getInstance(), new LuaMapSerializer());
luaSerializerMap.put(ObjectProtocolSerializer.getInstance(), new LuaObjectProtocolSerializer());
}
public static void clear() {
luaSerializerMap = null;
}
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("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, StringUtils.substringAfterFirst(fileName, "lua/")));
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
}
// 生成Protocol.lua文件
var luaBuilder = new StringBuilder();
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("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, "ProtocolManager.lua")), luaBuilder.toString());
}
public static void createLuaProtocolFile(ProtocolRegistration registration) {
// 初始化index
GenerateUtils.index.set(0);
var protocolId = registration.protocolId();
var registrationConstructor = registration.getConstructor();
var fieldRegistrations = registration.getFieldRegistrations();
var protocolClazzName = registrationConstructor.getDeclaringClass().getSimpleName();
var luaBuilder = new StringBuilder();
// document
luaBuilder.append(documentTitleAndImport(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 protocolOutputPath = StringUtils.format("{}{}/{}.lua"
, PROTOCOL_OUTPUT_ROOT_PATH
, GenerateProtocolPath.getCapitalizeProtocolPath(protocolId)
, protocolClazzName);
FileUtils.writeStringToFile(new File(protocolOutputPath), luaBuilder.toString());
}
private static String documentTitleAndImport(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.isBlank(docTitle)) {
Arrays.stream(docTitle.split(LS)).forEach(it -> luaBuilder.append(docToLuaDoc(it)).append(LS));
luaBuilder.append(LS);
}
// 如果协议包含子协议则需要导入ProtocolManager
var subProtocols = ProtocolManager.getAllSubProtocolIds(protocolId);
if (CollectionUtils.isNotEmpty(subProtocols)) {
luaBuilder.append("local ProtocolManager = require(\"LuaProtocol.ProtocolManager\")").append(LS + LS);
}
return luaBuilder.toString();
}
private static String newFunction(ProtocolRegistration registration) {
short protocolId = registration.getId();
var fields = registration.getFields();
var protocolClazzName = registration.getConstructor().getDeclaringClass().getSimpleName();
var protocolDocument = GenerateProtocolDocument.getProtocolDocument(protocolId);
var docFieldMap = protocolDocument.getValue();
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++) {
var field = fields[i];
var propertyName = field.getName();
// 生成注释
var doc = docFieldMap.get(propertyName);
if (!StringUtils.isBlank(doc)) {
Arrays.stream(doc.split(LS)).forEach(it -> luaBuilder.append(TAB + TAB).append(docToLuaDoc(it)).append(LS));
}
if (i == fields.length - 1) {
luaBuilder.append(TAB + TAB)
.append(StringUtils.format("{} = {}", propertyName, propertyName));
} else {
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();
}
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(byteBuffer, packet)", protocolClazzName)).append(LS);
luaBuilder.append(TAB).append("if packet == null then").append(LS);
luaBuilder.append(TAB + TAB).append("byteBuffer:writeBoolean(false)").append(LS);
luaBuilder.append(TAB + TAB).append("return").append(LS);
luaBuilder.append(TAB).append("end").append(LS);
luaBuilder.append(TAB).append("byteBuffer:writeBoolean(true)").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(byteBuffer)", protocolClazzName)).append(LS);
jsBuilder.append(TAB).append("if not(byteBuffer: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);
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);
}
jsBuilder.append(TAB).append("return packet").append(LS);
jsBuilder.append("end").append(LS);
return jsBuilder.toString();
}
private static String docToLuaDoc(String doc) {
return doc.replaceFirst("//", "--");
}
}
@@ -0,0 +1,30 @@
/*
* 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.lua;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import java.lang.reflect.Field;
/**
* @author jaysunxiao
* @version 3.0
*/
public interface ILuaSerializer {
void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration);
String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration);
}
@@ -0,0 +1,87 @@
/*
* 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.lua;
import com.zfoo.protocol.registration.field.ArrayField;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class LuaArraySerializer implements ILuaSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
ArrayField arrayField = (ArrayField) fieldRegistration;
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if {} == null then", objectStr)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("byteBuffer:writeInt(0)").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("else").append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("byteBuffer:writeInt(#{});", objectStr)).append(LS);
String index = "index" + GenerateUtils.index.getAndIncrement();
String element = "element" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("for {}, {} in pairs({}) do", index, element, objectStr)).append(LS);
GenerateLuaUtils.luaSerializer(arrayField.getArrayElementRegistration().serializer())
.writeObject(builder, element, deep + 2, field, arrayField.getArrayElementRegistration());
GenerateUtils.addTab(builder, deep + 1);
builder.append("end").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("end").append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
var arrayField = (ArrayField) fieldRegistration;
var result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("local {} = {}", result)).append(LS);
var i = "index" + GenerateUtils.index.getAndIncrement();
var size = "size" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("local {} = byteBuffer:readInt()", size)).append(LS);
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("if {} > 0 then", size)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append(StringUtils.format("for {} = 1, {} do", i, size)).append(LS);
String readObject = GenerateLuaUtils.luaSerializer(arrayField.getArrayElementRegistration().serializer())
.readObject(builder, deep + 2, field, arrayField.getArrayElementRegistration());
GenerateUtils.addTab(builder, deep + 2);
builder.append(StringUtils.format("table.insert({}, {})", result, readObject)).append(LS);
GenerateUtils.addTab(builder, deep + 1);
builder.append("end").append(LS);
GenerateUtils.addTab(builder, deep);
builder.append("end").append(LS);
return result;
}
}
@@ -0,0 +1,45 @@
/*
* 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.lua;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.serializer.GenerateUtils;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author jaysunxiao
* @version 3.0
*/
public class LuaBooleanSerializer implements ILuaSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("byteBuffer:writeBoolean({})", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateUtils.index.getAndIncrement();
GenerateUtils.addTab(builder, deep);
builder.append(StringUtils.format("local {} = byteBuffer:readBoolean()", result)).append(LS);
return result;
}
}

Some files were not shown because too many files have changed in this diff Show More