UNPKG

fy-convertor

Version:

Convert excel/xml/json/bin/protocl/ts/as ...

265 lines 9.32 kB
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