wasm parser

used to modify wasm

Този скрипт не може да бъде инсталиран директно. Това е библиотека за други скриптове и може да бъде използвана с мета-директива // @require https://update.greasyfork.org/scripts/455550/1414617/wasm%20parser.js

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         wasm parser
// @version      1.0
// @description  used to modify wasm
// @author       bismuth
// ==/UserScript==
const OP = {
    "unreachable": 0,
    "nop": 1,
    "block": 2,
    "loop": 3,
    "if": 4,
    "else": 5,
    "end": 11,
    "br": 12,
    "br_if": 13,
    "br_table": 14,
    "return": 15,
    "call": 16,
    "call_indirect": 17,
    "drop": 26,
    "select": 27,
    "local": {
        "get": 32,
        "set": 33,
        "tee": 34
    },
    "global": {
        "get": 35,
        "set": 36
    },
    "i32": {
        "load": 40,
        "load8_s": 44,
        "load8_u": 45,
        "load16_s": 46,
        "load16_u": 47,
        "store": 54,
        "store8": 58,
        "store16": 59,
        "const": 65,
        "eqz": 69,
        "eq": 70,
        "ne": 71,
        "lt_s": 72,
        "lt_u": 73,
        "gt_s": 74,
        "gt_u": 75,
        "le_s": 76,
        "le_u": 77,
        "ge_s": 78,
        "ge_u": 79,
        "clz": 103,
        "ctz": 104,
        "popcnt": 105,
        "add": 106,
        "sub": 107,
        "mul": 108,
        "div_s": 109,
        "div_u": 110,
        "rem_s": 111,
        "rem_u": 112,
        "and": 113,
        "or": 114,
        "xor": 115,
        "shl": 116,
        "shr_s": 117,
        "shr_u": 118,
        "rotl": 119,
        "rotr": 120,
        "wrap_i64": 167,
        "wrap_f32_s": 168,
        "wrap_f32_u": 169,
        "wrap_f64_s": 170,
        "wrap_f64_u": 171,
        "reinterpret_f32": 188
    },
    "i64": {
        "load": 41,
        "load8_s": 48,
        "load8_u": 49,
        "load16_s": 50,
        "load16_u": 51,
        "load32_s": 52,
        "load32_u": 53,
        "store": 55,
        "store8": 60,
        "store16": 61,
        "store32": 62,
        "const": 66,
        "eqz": 80,
        "eq": 81,
        "ne": 82,
        "lt_s": 83,
        "lt_u": 84,
        "gt_s": 85,
        "gt_u": 86,
        "le_s": 87,
        "le_u": 88,
        "ge_s": 89,
        "ge_u": 90,
        "clz": 121,
        "ctz": 122,
        "popcnt": 123,
        "add": 124,
        "sub": 125,
        "mul": 126,
        "div_s": 127,
        "div_u": 128,
        "rem_s": 129,
        "rem_u": 130,
        "and": 131,
        "or": 132,
        "xor": 133,
        "shl": 134,
        "shr_s": 135,
        "shr_u": 136,
        "rotl": 137,
        "rotr": 138,
        "extend_i32_s": 172,
        "extend_i32_u": 173,
        "trunc_f32_s": 174,
        "trunc_f32_u": 175,
        "trunc_f64_s": 176,
        "trunc_f64_u": 177,
        "reinterpret_f64": 189
    },
    "f32": {
        "load": 42,
        "store": 56,
        "const": 67,
        "eq": 91,
        "ne": 92,
        "lt": 93,
        "gt": 95,
        "le": 94,
        "ge": 96,
        "abs": 139,
        "neg": 140,
        "ceil": 141,
        "floor": 142,
        "trunc": 143,
        "nearest": 144,
        "sqrt": 145,
        "add": 146,
        "sub": 147,
        "mul": 148,
        "div": 149,
        "min": 150,
        "max": 151,
        "copysign": 152,
        "convert_i32_s": 178,
        "convert_i32_u": 179,
        "convert_i64_s": 180,
        "convert_i64_u": 181,
        "demote_f64": 182,
        "reinterpret_i32": 190
    },
    "f64": {
        "load": 43,
        "store": 57,
        "const": 68,
        "eq": 97,
        "ne": 98,
        "lt": 99,
        "gt": 100,
        "le": 101,
        "ge": 102,
        "abs": 153,
        "neg": 154,
        "ceil": 155,
        "floor": 156,
        "trunc": 157,
        "nearest": 158,
        "sqrt": 159,
        "add": 160,
        "sub": 161,
        "mul": 162,
        "div": 163,
        "min": 164,
        "max": 165,
        "copysign": 166,
        "convert_i32_s": 183,
        "convert_i32_u": 184,
        "convert_i64_s": 185,
        "convert_i64_u": 186,
        "promote_f32": 187,
        "reinterpret_i64": 191
    },
    "memory": {
        "size": 63,
        "grow": 64
    }
};
class WASMSection {
    constructor(desc,length) {
        this.section = desc;
        this.body = new Array(length);
    }
}
class WASMParser {
    constructor(bin) {
        this.lexer = new Reader(new Uint8Array(bin));
        this.sections = new Array(13);
        this.adjustImports = 0;
        this.importFuncCount = 0;
        this.parseWASM();
    }
    read(bin) { this.lexer.packet = new Uint8Array(bin) }
    loadFunc(index) {
        this.lexer.set(this.sections[10].body[index - this.importFuncCount]);
        const localLength = this.lexer.vu();
        for (let n = 0; n < localLength; n++) {
            this.lexer.vu();
            this.lexer.u8();
        }
        return;
    }
    set(index, val = this.lexer.packet) {
        this.sections[10].body[index - this.importFuncCount] = val;
    }
    getAdjusted(index) {
        if (index < this.importFuncCount) return index;
        return index + this.adjustImports;
    }
    addImportEntry(options) {
        const map = ['f64','f32','i64','i32'];
        switch(options.kind) {
            case 'func':
                this.sections[2].body.push({
                    name: options.name,
                    type: "func",
                    index: this.sections[1].body.length,
                    isNew: true
                });
                this.sections[1].body.push({
                    param: options.params,
                    return: options.returns,
                    isNew: true
                });
                this.adjustImports++;
                return this.sections[2].body.length - 1;
            case 'global':
                this.sections[6].body.push({
                    type: options.type,
                    mutable: options.mutable,
                    value: options.mutable,
                    isNew: true
                });
                return this.sections[6].body.length - 1;
            default:
                throw new Error('oops, not supported yet');
        }
    }
    reindex() {
        let section = this.sections[10].body;
        let length = section.length;
        for (let n = 0; n < length; n++) this.sections[10].body[n] = this.parseFunction(section[n]);
        section = this.sections[9].body;
        length = section.length;
        for (let n = 0; n < length; n++) {
            const l = section[n].funcs.length;
            for (let p = 0; p < l; p++) this.sections[9].body[n].funcs[p] = this.getAdjusted(section[n].funcs[p]);
        }
        section = this.sections[7].body;
        length = section.length;
        for (let n = 0; n < length; n++) this.sections[7].body[n].index = this.getAdjusted(section[n].index);
        this.adjustImports = 0;
    }
    compile() {
        const bin = [0, 97, 115, 109, 1, 0, 0, 0];
        for (let n = 0; n < 12; n++) {
            if (!this.sections[n]) continue;
            const section = this[`compileSection0x${n.toString(16)}`]();
            bin.push(n);
            bin.push(...Writer.vu(section.length));
            for (const byte of section) bin.push(byte);
        }
        return new Uint8Array(bin);
    }
    compileSection0x1() {
        const map = ['f64','f32','i64','i32'];
        const section = this.sections[1].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) {
            bin.push(0x60);
            bin.push(...Writer.vu(section[n].param.length));
            for (const param of section[n].param) bin.push(map.indexOf(param) + 0x7C);
            bin.push(...Writer.vu(section[n].return.length));
            for (const param of section[n].return) bin.push(map.indexOf(param) + 0x7C);
        }
        return bin;
    }
    compileSection0x2() {
        const map = ['func','table','mem','global'];
        const section = this.sections[2].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) {
            const nameSplit = section[n].name.split('.');
            for (const part of nameSplit) bin.push(...Writer.stringLEN(part));
            bin.push(map.indexOf(section[n].type));
            bin.push(...Writer.vu(section[n].index));
            //console.log(bin);
        }
        return bin;
    }
    compileSection0x3() {
        const section = this.sections[3].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) bin.push(...Writer.vu(section[n]));
        return bin;
    }
    compileSection0x4() {
        const section = this.sections[4].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) for (let p = 0; p < 4; p++) bin.push(...Writer.vu(section[n][p]));
        return bin;
    }
    compileSection0x5() {
        const section = this.sections[5].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) {
            bin.push(...Writer.vu(section[n].type));
            bin.push(...Writer.vu(section[n].limit[0]));
            bin.push(...Writer.vu(section[n].limit[1]));
        }
        return bin;
    }
    compileSection0x6() {
        const map = ['f64','f32','i64','i32'];
        const section = this.sections[6].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) {
            bin.push(map.indexOf(section[n].type) + 0x7C);
            bin.push(section[n].mutable);
            for (const expr of section[n].expr) bin.push(...Writer.vu(expr));
            bin.push(11);
        }
        return bin;
    }
    compileSection0x7() {
        const map = ['func','table','mem','global'];
        const section = this.sections[7].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) {
            bin.push(...Writer.stringLEN(section[n].name));
            bin.push(map.indexOf(section[n].type));
            bin.push(...Writer.vu(section[n].index));
        }
        return bin;
    }
    compileSection0x8() {
        const section = this.sections[8].body;
        const length = 1;
        const bin = [1];
        bin.push(...Writer.vu(section));
        return bin;
    }
    compileSection0x9() {
        const section = this.sections[9].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) {
            bin.push(section[n].type, section[n].expr[0]);
            bin.push(...Writer.vi(section[n].expr[1]),11);
            bin.push(...Writer.vu(section[n].funcs.length));
            for (const funcIdx of section[n].funcs) bin.push(...Writer.vu(funcIdx));
        }
        return bin;
    }
    compileSection0xa() {
        const section = this.sections[10].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) {
            //section[n] = this.parseFunction(section[n]);
            bin.push(...Writer.vu(section[n].length));
            for (const byte of section[n]) bin.push(byte);
        }
        return bin;
    }
    compileSection0xb() {
        const section = this.sections[11].body;
        const length = section.length;
        const bin = Writer.vu(length);
        for (let n = 0; n < length; n++) {
            bin.push(section[n].type,section[n].expr[0]);
            bin.push(...Writer.vi(section[n].expr[1]),11);
            bin.push(...Writer.vu(section[n].contents.length));
            for (const byte of section[n].contents) bin.push(byte);
        }
        return bin;
    }
    parseWASM() {
        this.lexer.index = 8;
        while (this.lexer.has()) {
            const id = this.lexer.u8();
            if (id > 12) return;
            this[`parseSection0x${id.toString(16)}`]();
        }
        this.importFuncCount = this.sections[2].body.filter(({type}) => type === 'func').length;
    }
    parseSection0x1() {
        const map = ['f64','f32','i64','i32'];
        const rawLength = this.lexer.vu();
        const section = new WASMSection('functypes', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) {
            const type = { param: [], return: [] }
            if (this.lexer.u8() !== 0x60) break;
            let len = this.lexer.vu();
            for (let n = 0; n < len; n++) type.param.push(map[this.lexer.u8()-0x7C]);
            len = this.lexer.vu();
            for (let n = 0; n < len; n++) type.return.push(map[this.lexer.u8()-0x7C]);
            section.body[n] = type;
        }
        return (this.sections[1] = section);
    }
    parseSection0x2() {
        const map = ['func','table','mem','global'];
        this.lexer.vu();
        const section = new WASMSection('imports', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) section.body[n] = { name: this.lexer.stringLEN() + '.' + this.lexer.stringLEN(), type: map[this.lexer.u8()], index: this.lexer.vu() };
        return (this.sections[2] = section);
    }
    parseSection0x3() {
        this.lexer.vu();
        const section = new WASMSection('functions', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) section.body[n] = this.lexer.vu();
        return (this.sections[3] = section);
    }
    parseSection0x4() {
        this.lexer.vu();
        const section = new WASMSection('tables', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) section.body[n] = [this.lexer.vu(), this.lexer.vu(), this.lexer.vu(), this.lexer.vu()]; //incomplete
        return (this.sections[4] = section);
    }
    parseSection0x5() {
        this.lexer.vu();
        const section = new WASMSection('mem', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) section.body[n] = { type: this.lexer.vu(), limit: [this.lexer.vu(), this.lexer.vu()] }
        return (this.sections[5] = section);
    }
    parseSection0x6() {
        const map = ['f64','f32','i64','i32'];
        this.lexer.vu();
        const section = new WASMSection('globals', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) {
            section.body[n] = { type: map[this.lexer.u8()-0x7C], mutable: this.lexer.u8(), expr: [] }
            section.body[n].expr.push(this.lexer.ru8());
            switch(this.lexer.u8()) {
                case OP.i32.const:
                case OP.i64.const:
                    section.body[n].expr.push(this.lexer.vu());
                    break;
                case OP.f32.const:
                    section.body[n].expr.push(this.f32());
                    break;
                case OP.f64.const:
                    section.body[n].expr.push(this.f64());
                    break;
            }
            this.lexer.u8();
        }
        return (this.sections[6] = section);
    }
    parseSection0x7() {
        const map = ['func','table','mem','global'];
        this.lexer.vu();
        const section = new WASMSection('exports', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) {
            const name = this.lexer.stringLEN();
            const type = map[this.lexer.u8()];
            const index = this.lexer.vu();
            section.body[n] = { name, type, index };
        }
        return (this.sections[7] = section);
    }
    parseSection0x8() {
        this.lexer.vu();
        const section = new WASMSection('start', this.lexer.vu());
        section.body = this.vu();
        return (this.sections[8] = section);
    }
    parseSection0x9() {
        this.lexer.vu();
        const section = new WASMSection('elements', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) {
            section.body[n] = { type: this.lexer.u8() }; //NEED TO ACCOUNT FOR DIFFERENT TYPES
            section.body[n].expr = [this.lexer.u8(),this.lexer.vu()];
            this.lexer.u8();
            const repeat = this.lexer.vu();
            section.body[n].funcs = [];
            for (let p = 0; p < repeat; p++) section.body[n].funcs.push(this.lexer.vu());
        }
        return (this.sections[9] = section);
    }
    parseSection0xa() {
        this.lexer.vu();
        const section = new WASMSection('code', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) {
            const len = this.lexer.vu();
            section.body[n] = this.lexer.packet.slice(this.lexer.index, this.lexer.index += len);
        }
        return (this.sections[10] = section);
    }
    parseSection0xb() {
        this.lexer.vu();
        const t = this.lexer.index;

        const section = new WASMSection('data', this.lexer.vu());
        for (let n = 0; n < section.body.length; n++) {
            section.body[n] = { type: this.lexer.u8(), expr: [this.lexer.u8(),this.lexer.vu()] };
            this.lexer.u8();
            const len = this.lexer.vu();
            section.body[n].contents = this.lexer.packet.slice(this.lexer.index, this.lexer.index += len);
        }
        return (this.sections[11] = section);
    }
    parseFunction(func) {
        this.lexer.set(func);
        const localLength = this.lexer.vu();
        for (let n = 0; n < localLength; n++) {
            this.lexer.vu();
            this.lexer.u8();
        }
        while(this.lexer.has()) {
            const before = this.lexer.index;
            const instr = this.parseInstruction();
            if (instr.op === OP.call) {
                this.lexer.index = before + 1;
                this.lexer.replaceVu(this.getAdjusted(instr.immediates[0]));
            }
        }
        return this.lexer.packet;
    }
    parseInstruction() {
        let len;
        const op = this.lexer.u8();
        const immediates = [];
        switch(op) {
            case OP.block: case OP.loop: case OP.if:
            case OP.memory.size: case OP.memory.grow:
                immediates.push(this.lexer.u8());
                break;
            case OP.br: case OP.br_if:
            case OP.local.get: case OP.local.set: case OP.local.tee:
            case OP.i32.const: case OP.i64.const:
                immediates.push(this.lexer.vu());
                break;
            case OP.f32.const:
                immediates.push(this.lexer.f32());
                break;
            case OP.f64.const:
                immediates.push(this.lexer.f64());
                break;
            case OP.global.get: case OP.global.set:
                immediates.push(this.lexer.vu());
                break; //adjust global index later
            case OP.i32.load: case OP.i32.load8_s: case OP.i32.load8_u: case OP.i32.load16_s: case OP.i32.load16_u:
            case OP.i64.load: case OP.i64.load8_s: case OP.i64.load8_u: case OP.i64.load16_s: case OP.i64.load16_u: case OP.i64.load32_s: case OP.i64.load32_u:
            case OP.f32.load:
            case OP.f64.load:
            case OP.i32.store: case OP.i32.store8: case OP.i32.store16:
            case OP.i64.store: case OP.i64.store8: case OP.i64.store16: case OP.i64.store32:
            case OP.f32.store:
            case OP.f64.store:
                immediates.push(this.lexer.vu(),this.lexer.vu());
                break;
            case OP.call_indirect:
                immediates.push(this.lexer.vu(),this.lexer.u8());
                break;
            case OP.br_table:
                len = this.lexer.vu();
                immediates.push(len);
                for (let n = 0; n < len+1; n++) immediates.push(this.lexer.vu());
                break;
            case OP.call:
                immediates.push(this.lexer.vu());
                break;
            default:
                break;
        }
        return {op, immediates}
    }
    regex(func, instrRegex, cb = (sIndex,eIndex,instrs) => {}, all=true) {
        this.lexer.set(this.sections[10].body[func - this.importFuncCount]);
        const todos = [];
        let exprBlob = [];
        const localLength = this.lexer.vu();
        for (let n = 0; n < localLength; n++) {
            this.lexer.vu();
            this.lexer.u8();
        }
        let startIndex = this.lexer.index, regexPos = 0;
        while(startIndex < this.lexer.packet.length) {
            if (regexPos === 0) {
                exprBlob = [];
                startIndex = this.lexer.index;
            }
            const currIndex = this.lexer.index;
            const instr = this.parseInstruction();
            exprBlob.push(instr);
            if (instr.op === instrRegex[regexPos][0]) {
                let good = true;
                for (let n = 1; n < instrRegex[regexPos].length; n++) if (instrRegex[regexPos][n] !== instr.immediates[n-1] && instrRegex[regexPos][n] !== '*') good = false;
                if (good) regexPos++;
                else {
                    regexPos = 0;
                    this.lexer.index = startIndex;
                    this.parseInstruction();
                    continue;
                }
            }
            else {
                regexPos = 0;
                this.lexer.index = startIndex;
                this.parseInstruction();
                continue;
            }
            if (regexPos === instrRegex.length) {
                todos.push([startIndex, this.lexer.index, [...exprBlob]]);
                if (!all) break;
                regexPos = 0;
            }
        }
        for (const [si, ci, eb] of todos) {
            cb(si, ci, eb);
        }
        return this.lexer.packet;
    }
    inject(code, index = this.lexer.index) {
        return this.lexer.inject(code, index);
    }
    remove(code, index = this.lexer.index) {
        return this.lexer.remove(code, index);
    }
}
class Writer {
    static vu(num) {
        const ret = [];
        while (num >= 128) {
            ret.push((num & 127) | 128);
            num >>= 7;
        }
        ret.push(num);
        return ret;
    }
    static vi(num) {
        const ret = [];
        while (num >= 128) {
            ret.push((num & 127) | 128);
            num >>= 7;
        }
        if (num < 0x40) ret.push(num);
        else {
            ret.push(num | 0x80);
            ret.push(num<0?1:0);
        }
        return ret;
    }
    static f32(num) {
        return [...new Uint8Array(new Float32Array([num]).buffer)];
    }
    static stringLEN(str) {
        str = new TextEncoder().encode(str);
        if (str.length > 127) throw new Error('Unsupported string length: don\'t use a string that long (max 127 byte length)');
        return [str.length, ...str];
    }
}
class Reader {
    constructor(packet) {
        this.packet = packet;
        this.index = 0;
        const buffer = new ArrayBuffer(8);
        this._u8 = new Uint8Array(buffer);
        this._f32 = new Float32Array(buffer);
        this._f64 = new Float64Array(buffer);
    }
    inject(code, index = this.index) {
        this.index = index;
        const newBuf = new Uint8Array(code.length + this.packet.length);
        newBuf.set(this.packet.slice(0,this.index),0);
        newBuf.set(code,this.index);
        newBuf.set(this.packet.slice(this.index),(this.index+code.length));
        return (this.packet = newBuf);
    }
    remove(index1, index2 = this.index) {
        this.index = index2;
        const newBuf = new Uint8Array(index1 - index2 + this.packet.length);
        newBuf.set(this.packet.slice(0,index1),0);
        newBuf.set(this.packet.slice(index2,this.packet.length),index1);
        return (this.packet = newBuf);
    }
    replaceVu(replace) {
        const before = this.index, old = this.vu(), now = this.index;
        replace = Writer.vu(replace);
        if (replace.length === now - before) this.packet.set(replace, before);
        else {
            const newBuf = new Uint8Array(this.packet.length-now+before+replace.length);
            newBuf.set(this.packet.slice(0,before),0);
            newBuf.set(replace,before);
            newBuf.set(this.packet.slice(now),(this.index=before+replace.length));
            this.packet = newBuf;
        }
    }
    has() { return this.index < this.packet.length }
    set(packet) {
        this.packet = packet;
        this.index = 0;
    }
    ru8() { return this.packet[this.index] }
    u8() { return this.packet[this.index++] }
    f32() {
        this._u8.set(this.packet.slice(this.index, this.index += 4));
        return this._f32[0];
    }
    f64() {
        this._u8.set(this.packet.slice(this.index, this.index += 8));
        return this._f64[0];
    }
    vu() {
        let out = 0, at = 0;
        while (this.packet[this.index] & 0x80) {
            out |= (this.u8() & 0x7f) << at;
            at += 7;
        }
        out |= this.u8() << at;
        return out;
    }
    stringLEN() {
        const len = this.u8();
        const ret = new TextDecoder().decode(this.packet.slice(this.index, this.index += len));
        return ret;
    }
}