fy-convertor
Version:
Convert excel/xml/json/bin/protocl/ts/as ...
265 lines • 9.32 kB
JavaScript
import path from 'path';
import { indent } from '../tools/vendor.js';
import { BaseStructParser } from './BaseStructParser.js';
import { BigintLike, StringLike } from './def.js';
export class ProtocolStructParser extends BaseStructParser {
static ins;
static get Instance() {
if (!ProtocolStructParser.ins)
ProtocolStructParser.ins = new ProtocolStructParser();
return ProtocolStructParser.ins;
}
encodeOpMap = {
"byte": "writeByte",
"char": "writeByte",
"Double": "writeFloat32",
"Float": "writeFloat32",
"float": "writeFloat32",
"Int32": "writeInt32",
"Uint32": "writeUint32",
"Int16": "writeInt16",
"Uint16": "writeUint16",
"Int8": "writeByte",
"Uint8": "writeUint8",
"uchar": "writeByte",
"ushort": "writeUint16",
"short": "writeInt16",
"int": "writeInt32",
"uint": "writeUint32",
"Smallint": "writeInt16",
"smallint": "writeInt16",
"Smalluint": "writeUint16",
"smalluint": "writeUint16",
"Tinyuint": "writeUint8",
"Tinyint": "writeUint8"
};
decodeOpMap = {
"byte": "getUint8",
"char": "getByte",
"Double": "getFloat32",
"Float": "getFloat32",
"float": "getFloat32",
"Int32": "getInt32",
"Uint32": "getUint32",
"Int16": "getInt16",
"Uint16": "getUint16",
"Int8": "getByte",
"Uint8": "getUint8",
"uchar": "getUint8",
"ushort": "getUint16",
"short": "getInt16",
"int": "getInt32",
"uint": "getUint32",
"Smallint": "getInt16",
"smallint": "getInt16",
"Smalluint": "getUint16",
"smalluint": "getUint16",
"Tinyuint": "getUint8",
"Tinyint": "getByte"
};
sizeMap = {
"byte": 1,
"char": 1,
"Double": 4,
"Float": 4,
"float": 4,
"Int32": 4,
"Uint32": 4,
"Int16": 2,
"Uint16": 2,
"Int8": 1,
"Uint8": 1,
"uchar": 1,
"ushort": 2,
"short": 2,
"int": 4,
"uint": 4,
"Smallint": 2,
"smallint": 2,
"Smalluint": 2,
"smalluint": 2,
"Tinyuint": 1,
"Tinyint": 1
};
get rmFlashTail() {
return false;
}
async readStructs(root, projCfg) {
this.reset();
const XmlNames = projCfg.Project.ProjectType === 'H5ts' ? ['CommonCS.xml', 'ProtoTypeCS.xml', 'CS.xml'] : ['Common.xml', 'ProtoType.xml', 'CS.xml'];
for (const n of XmlNames) {
const f = path.join(root, n);
await this.readStructFile(f, false);
}
return this.m_cliStructs.sort();
}
isClientStruct(struct) {
return struct._attributes.server === undefined;
}
makeStructDecodeCode(structName) {
const wrap = this.m_structDefMap[structName];
if (!wrap) {
console.error('[ERROR] makeStructDecodeCode: No struct definition!', structName);
process.exit(1);
}
const def = wrap.def;
let code, body;
if (def._attributes.class === 'union') {
code = `private _decode${structName}(select: number, body: Protocol.${structName}, byte: Byte): Protocol.${structName} {\n`;
body = ' switch(select) {\n';
for (const e of def.entries) {
const macro = this.getMacro(e._attributes.value);
body += ` case ${macro?._attributes.value}: //${e._attributes.value}\n`;
body += ' {\n';
body += indent(this.makeEntryDecodeCode(e), ' ');
body += ' break;\n';
body += ' }\n';
}
body += ' }\n';
}
else {
code = `private _decode${structName}(body: Protocol.${structName}, byte: Byte): Protocol.${structName} {\n`;
body = '';
for (const e of def.entries) {
body += indent(this.makeEntryDecodeCode(e));
}
}
code += ` if (!body) body = {} as Protocol.${structName};\n`;
code += body;
code += ` return body;
}\n\n`;
return code;
}
makeEntryDecodeCode(e) {
let fieldName = `body.${e._attributes.name}`;
if (e._attributes.count) {
fieldName += '[i]';
}
const op = this.decodeOpMap[e._attributes.type];
let body;
if (op) {
body = `${fieldName} = byte.${op}();`;
}
else if (BigintLike.includes(e._attributes.type)) {
body = `${fieldName} = DrUtil.readLonglong(byte);`;
}
else if (StringLike.includes(e._attributes.type)) {
let opStr = `byte.getUTFBytes(__${e._attributes.name}Size - 1)`;
if (e._attributes.safeprintf) {
opStr = `this.__safeprintf(${opStr})`;
}
body = `const __${e._attributes.name}Size = byte.getUint32();
${fieldName} = ${opStr};
byte.getByte();`;
}
else {
if (e._attributes.select) {
body = `${fieldName} = this._decode${e._attributes.type}(body.${e._attributes.select}, null, byte);`;
}
else {
body = `${fieldName} = this._decode${e._attributes.type}(null, byte);`;
}
}
let out;
if (e._attributes.count) {
// 数组
let numdef;
if (e._attributes.refer) {
numdef = `body.${e._attributes.refer}`;
}
else {
numdef = `Macros.${e._attributes.count}`;
}
out = `if (!body.${e._attributes.name}) body.${e._attributes.name} = [];
else body.${e._attributes.name}.length = ${numdef};
for (let i = 0, num = ${numdef}; i < num; i++) {
${indent(body)}
}`;
}
else {
out = body;
}
return out + '\n';
}
makeStructEncodeCode(structName) {
const wrap = this.m_structDefMap[structName];
if (!wrap) {
console.error('[ERROR] makeStructDecodeCode: No struct definition!', structName);
process.exit(1);
}
const def = wrap.def;
let code, body;
if (def._attributes.class === 'union') {
code = `private _encode${structName}(select: number, body: Protocol.${structName}, byte: Byte): void {\n`;
body = ' switch(select) {\n';
for (const e of def.entries) {
const macro = this.getMacro(e._attributes.value);
body += ` case ${macro?._attributes.value}: //${e._attributes.value}\n`;
body += ' {\n';
body += indent(this.makeEntryEncodeCode(structName, e), ' ');
body += ' break;\n';
body += ' }\n';
}
body += ' }\n';
}
else {
code = `private _encode${structName}(body: Protocol.${structName}, byte: Byte): void {\n`;
body = '';
for (const e of def.entries) {
body += indent(this.makeEntryEncodeCode(structName, e));
}
}
code += body;
code += '}\n\n';
return code;
}
makeEntryEncodeCode(structName, e) {
let fieldName = `body.${e._attributes.name}`;
if (e._attributes.count) {
fieldName += '[i]';
}
let body;
const op = this.encodeOpMap[e._attributes.type];
if (op) {
body = `byte.${op}(${fieldName});\n`;
}
else if (BigintLike.includes(e._attributes.type)) {
body = `DrUtil.writeLonglong(byte, ${fieldName});\n`;
}
else if (StringLike.includes(e._attributes.type)) {
body = `const __${e._attributes.name}Size = byte.pos;
byte.pos += 4;
const __${e._attributes.name}Begin = byte.pos;
byte.writeUTFBytes(${fieldName});
byte.writeByte(0);
DrUtil.directWriteUint(byte, __${e._attributes.name}Size, byte.pos - __${e._attributes.name}Begin);\n`;
}
else {
if (e._attributes.select) {
body = `this._encode${e._attributes.type}(body.${e._attributes.select}, ${fieldName}, byte);\n`;
}
else {
body = `this._encode${e._attributes.type}(${fieldName}, byte);\n`;
}
}
let out;
if (e._attributes.count) {
// 数组
let numdef;
if (e._attributes.refer) {
numdef = `body.${e._attributes.refer}`;
}
else {
numdef = `Macros.${e._attributes.count}`;
}
out = `for (let i = 0, num = ${numdef}; i < num; i++) {\n`;
out += indent(body);
out += '}\n';
}
else {
out = body;
}
return out;
}
}
//# sourceMappingURL=ProtocolStructParser.js.map