From 0dcba22b38fcfa74139b76ed879ed1d9d97cc72a Mon Sep 17 00:00:00 2001 From: godotg Date: Tue, 26 Sep 2023 23:38:41 +0800 Subject: [PATCH] feat[ts]: compatible typescript inside class --- .../registration/ProtocolRegistration.java | 1 + .../typescript/GenerateTsUtils.java | 31 ++++-- .../typescript/TsCharSerializer.java | 48 --------- .../resources/typescript/ProtocolTemplate.ts | 10 +- .../resources/typescript/buffer/ByteBuffer.ts | 102 ++++++++---------- 5 files changed, 75 insertions(+), 117 deletions(-) delete mode 100644 protocol/src/main/java/com/zfoo/protocol/serializer/typescript/TsCharSerializer.java diff --git a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolRegistration.java b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolRegistration.java index 6892f67f..0aeab779 100644 --- a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolRegistration.java +++ b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolRegistration.java @@ -73,6 +73,7 @@ public class ProtocolRegistration implements IProtocolRegistration { @Override public void write(ByteBuf byteBuf, Object packet) { if (packet == null) { + // equals with ByteBufUtils.writeInt(byteBuf, 0); ByteBufUtils.writeByte(byteBuf, (byte) 0); return; } diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/GenerateTsUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/GenerateTsUtils.java index 2818da0a..05568b75 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/GenerateTsUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/GenerateTsUtils.java @@ -179,31 +179,42 @@ public abstract class GenerateTsUtils { private static String writeObject(ProtocolRegistration registration) { var fields = registration.getFields(); var fieldRegistrations = registration.getFieldRegistrations(); - var jsBuilder = new StringBuilder(); + var tsBuilder = new StringBuilder(); + if (registration.isCompatible()) { + tsBuilder.append("const beforeWriteIndex = buffer.getWriteOffset();").append(LS); + tsBuilder.append(TAB + TAB).append(StringUtils.format("buffer.writeInt({});", registration.getPredictionLength())).append(LS); + } else { + tsBuilder.append(TAB + TAB).append("buffer.writeInt(-1);").append(LS); + } for (var i = 0; i < fields.length; i++) { var field = fields[i]; var fieldRegistration = fieldRegistrations[i]; - tsSerializer(fieldRegistration.serializer()).writeObject(jsBuilder, "packet." + field.getName(), 2, field, fieldRegistration); + tsSerializer(fieldRegistration.serializer()).writeObject(tsBuilder, "packet." + field.getName(), 2, field, fieldRegistration); } - return jsBuilder.toString(); + if (registration.isCompatible()) { + tsBuilder.append(TAB + TAB).append(StringUtils.format("buffer.adjustPadding({}, beforeWriteIndex);", registration.getPredictionLength())).append(LS); + } + return tsBuilder.toString(); } private static String readObject(ProtocolRegistration registration) { var fields = registration.getFields(); var fieldRegistrations = registration.getFieldRegistrations(); - var jsBuilder = new StringBuilder(); + var tsBuilder = new StringBuilder(); for (var i = 0; i < fields.length; i++) { var field = fields[i]; var fieldRegistration = fieldRegistrations[i]; if (field.isAnnotationPresent(Compatible.class)) { - jsBuilder.append(TAB + TAB).append("if (!buffer.isReadable()) {").append(LS); - jsBuilder.append(TAB + TAB + TAB).append("return packet;").append(LS); - jsBuilder.append(TAB + TAB).append("}").append(LS); + tsBuilder.append(TAB + TAB).append("if (length !== -1 && buffer.getReadOffset() - readIndex < length) {").append(LS); + var compatibleReadObject = tsSerializer(fieldRegistration.serializer()).readObject(tsBuilder, 3, field, fieldRegistration); + tsBuilder.append(TAB + TAB+ TAB).append(StringUtils.format("packet.{} = {};", field.getName(), compatibleReadObject)).append(LS); + tsBuilder.append(TAB + TAB).append("}").append(LS); + continue; } - var readObject = tsSerializer(fieldRegistration.serializer()).readObject(jsBuilder, 2, field, fieldRegistration); - jsBuilder.append(TAB + TAB).append(StringUtils.format("packet.{} = {};", field.getName(), readObject)).append(LS); + var readObject = tsSerializer(fieldRegistration.serializer()).readObject(tsBuilder, 2, field, fieldRegistration); + tsBuilder.append(TAB + TAB).append(StringUtils.format("packet.{} = {};", field.getName(), readObject)).append(LS); } - return jsBuilder.toString(); + return tsBuilder.toString(); } public static String toTsClassName(String typeName) { diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/TsCharSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/TsCharSerializer.java deleted file mode 100644 index 981022c5..00000000 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/TsCharSerializer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2020 The zfoo Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and limitations under the License. - */ - -package com.zfoo.protocol.serializer.typescript; - -import com.zfoo.protocol.generate.GenerateProtocolFile; -import com.zfoo.protocol.model.Triple; -import com.zfoo.protocol.registration.field.IFieldRegistration; -import com.zfoo.protocol.util.StringUtils; - -import java.lang.reflect.Field; - -import static com.zfoo.protocol.util.FileUtils.LS; - -/** - * @author godotg - */ -public class TsCharSerializer implements ITsSerializer { - - @Override - public Triple field(Field field, IFieldRegistration fieldRegistration) { - return new Triple<>(": string", field.getName(), "''"); - } - - @Override - public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) { - GenerateProtocolFile.addTab(builder, deep); - builder.append(StringUtils.format("buffer.writeChar({});", objectStr)).append(LS); - } - - @Override - public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) { - String result = "result" + GenerateProtocolFile.index.getAndIncrement(); - GenerateProtocolFile.addTab(builder, deep); - builder.append(StringUtils.format("const {} = buffer.readChar();", result)).append(LS); - return result; - } -} diff --git a/protocol/src/main/resources/typescript/ProtocolTemplate.ts b/protocol/src/main/resources/typescript/ProtocolTemplate.ts index 8b5b15bf..ec203414 100644 --- a/protocol/src/main/resources/typescript/ProtocolTemplate.ts +++ b/protocol/src/main/resources/typescript/ProtocolTemplate.ts @@ -11,18 +11,24 @@ class {} { } static write(buffer: any, packet: {} | null) { - if (buffer.writePacketFlag(packet) || packet == null) { + if (packet === null) { + buffer.writeInt(0); return; } {} } static read(buffer: any): {} | null { - if (!buffer.readBoolean()) { + const length = buffer.readInt(); + if (length === 0) { return null; } + const readIndex = buffer.getReadOffset(); const packet = new {}(); {} + if (length > 0) { + buffer.setReadOffset(readIndex + length); + } return packet; } } diff --git a/protocol/src/main/resources/typescript/buffer/ByteBuffer.ts b/protocol/src/main/resources/typescript/buffer/ByteBuffer.ts index ffc52a1f..85b47671 100644 --- a/protocol/src/main/resources/typescript/buffer/ByteBuffer.ts +++ b/protocol/src/main/resources/typescript/buffer/ByteBuffer.ts @@ -57,6 +57,24 @@ class ByteBuffer { this.bufferView = new DataView(this.buffer, 0, this.buffer.byteLength); } + adjustPadding(predictionLength: number, beforeWriteIndex: number): void { + const currentWriteIndex = this.writeOffset; + const predictionCount = this.writeIntCount(predictionLength); + const length = currentWriteIndex - beforeWriteIndex - predictionCount; + const lengthCount = this.writeIntCount(length); + const padding = lengthCount - predictionCount; + if (padding == 0) { + this.setWriteOffset(beforeWriteIndex); + this.writeInt(length); + this.setWriteOffset(currentWriteIndex); + } else { + const retainedByteBuf = this.buffer.slice(currentWriteIndex - length, currentWriteIndex); + this.setWriteOffset(beforeWriteIndex); + this.writeInt(length); + this.writeBytes(retainedByteBuf); + } + } + setWriteOffset(writeOffset: number): void { if (writeOffset > this.buffer.byteLength) { throw new Error('index out of bounds exception:readerIndex:' + this.readOffset + @@ -66,6 +84,10 @@ class ByteBuffer { this.writeOffset = writeOffset; } + getWriteOffset(): number { + return this.writeOffset; + } + setReadOffset(readOffset: number): void { if (readOffset > this.writeOffset) { throw new Error('index out of bounds exception:readerIndex:' + this.readOffset + @@ -75,6 +97,10 @@ class ByteBuffer { this.readOffset = readOffset; } + getReadOffset(): number { + return this.readOffset; + } + getCapacity(): number { return this.buffer.byteLength - this.writeOffset; } @@ -209,6 +235,25 @@ class ByteBuffer { this.writeByte(value >>> 28); } + writeIntCount(value: number): number { + if (!(minInt <= value && value <= maxInt)) { + throw new Error('value must range between minInt:-2147483648 and maxInt:2147483647'); + } + if (value >>> 7 === 0) { + return 1; + } + if (value >>> 14 === 0) { + return 2; + } + if (value >>> 21 === 0) { + return 3; + } + if (value >>> 28 === 0) { + return 4; + } + return 5; + } + readInt(): number { let b = this.readByte(); let value = b & 0x7F; @@ -313,18 +358,6 @@ class ByteBuffer { return value; } - writeChar(value: string): void { - if (value === null || value === undefined || value.length === 0) { - this.writeString(empty_str); - return; - } - this.writeString(value.charAt(0)); - } - - readChar(): string { - return this.readString(); - } - writeString(value: string): void { if (value === null || value === undefined || value.trim().length === 0) { this.writeInt(0); @@ -542,28 +575,6 @@ class ByteBuffer { return array; }; - writeCharArray(array: Array | null) { - if (array === null) { - this.writeInt(0); - } else { - this.writeInt(array.length); - array.forEach(element => { - this.writeChar(element); - }); - } - }; - - readCharArray(): any { - const array: string[] = []; - const length = this.readInt(); - if (length > 0) { - for (let index = 0; index < length; index++) { - array.push(this.readChar()); - } - } - return array; - }; - writePacketArray(array: Array | null, protocolId: number) { if (array === null) { this.writeInt(0); @@ -653,14 +664,6 @@ class ByteBuffer { return this.readStringArray(); }; - writeCharList(list: any) { - this.writeCharArray(list); - }; - - readCharList(): any { - return this.readCharArray(); - }; - writePacketList(list: any, protocolId: number) { this.writePacketArray(list, protocolId); }; @@ -790,21 +793,6 @@ class ByteBuffer { return new Set(this.readStringArray()); }; - writeCharSet(set: Set | null) { - if (set === null) { - this.writeInt(0); - } else { - this.writeInt(set.size); - set.forEach(element => { - this.writeChar(element); - }); - } - }; - - readCharSet(): any { - return new Set(this.readCharArray()); - }; - writePacketSet(set: Set | null, protocolId: number) { if (set === null) { this.writeInt(0);