Greasy Fork is available in English.

wasm parser

used to modify wasm

Tento skript by neměl být instalován přímo. Jedná se o knihovnu, kterou by měly jiné skripty využívat pomocí meta příkazu // @require https://update.greatest.deepsurf.us/scripts/455550/1414617/wasm%20parser.js

  1. // ==UserScript==
  2. // @name wasm parser
  3. // @version 1.0
  4. // @description used to modify wasm
  5. // @author bismuth
  6. // ==/UserScript==
  7. const OP = {
  8. "unreachable": 0,
  9. "nop": 1,
  10. "block": 2,
  11. "loop": 3,
  12. "if": 4,
  13. "else": 5,
  14. "end": 11,
  15. "br": 12,
  16. "br_if": 13,
  17. "br_table": 14,
  18. "return": 15,
  19. "call": 16,
  20. "call_indirect": 17,
  21. "drop": 26,
  22. "select": 27,
  23. "local": {
  24. "get": 32,
  25. "set": 33,
  26. "tee": 34
  27. },
  28. "global": {
  29. "get": 35,
  30. "set": 36
  31. },
  32. "i32": {
  33. "load": 40,
  34. "load8_s": 44,
  35. "load8_u": 45,
  36. "load16_s": 46,
  37. "load16_u": 47,
  38. "store": 54,
  39. "store8": 58,
  40. "store16": 59,
  41. "const": 65,
  42. "eqz": 69,
  43. "eq": 70,
  44. "ne": 71,
  45. "lt_s": 72,
  46. "lt_u": 73,
  47. "gt_s": 74,
  48. "gt_u": 75,
  49. "le_s": 76,
  50. "le_u": 77,
  51. "ge_s": 78,
  52. "ge_u": 79,
  53. "clz": 103,
  54. "ctz": 104,
  55. "popcnt": 105,
  56. "add": 106,
  57. "sub": 107,
  58. "mul": 108,
  59. "div_s": 109,
  60. "div_u": 110,
  61. "rem_s": 111,
  62. "rem_u": 112,
  63. "and": 113,
  64. "or": 114,
  65. "xor": 115,
  66. "shl": 116,
  67. "shr_s": 117,
  68. "shr_u": 118,
  69. "rotl": 119,
  70. "rotr": 120,
  71. "wrap_i64": 167,
  72. "wrap_f32_s": 168,
  73. "wrap_f32_u": 169,
  74. "wrap_f64_s": 170,
  75. "wrap_f64_u": 171,
  76. "reinterpret_f32": 188
  77. },
  78. "i64": {
  79. "load": 41,
  80. "load8_s": 48,
  81. "load8_u": 49,
  82. "load16_s": 50,
  83. "load16_u": 51,
  84. "load32_s": 52,
  85. "load32_u": 53,
  86. "store": 55,
  87. "store8": 60,
  88. "store16": 61,
  89. "store32": 62,
  90. "const": 66,
  91. "eqz": 80,
  92. "eq": 81,
  93. "ne": 82,
  94. "lt_s": 83,
  95. "lt_u": 84,
  96. "gt_s": 85,
  97. "gt_u": 86,
  98. "le_s": 87,
  99. "le_u": 88,
  100. "ge_s": 89,
  101. "ge_u": 90,
  102. "clz": 121,
  103. "ctz": 122,
  104. "popcnt": 123,
  105. "add": 124,
  106. "sub": 125,
  107. "mul": 126,
  108. "div_s": 127,
  109. "div_u": 128,
  110. "rem_s": 129,
  111. "rem_u": 130,
  112. "and": 131,
  113. "or": 132,
  114. "xor": 133,
  115. "shl": 134,
  116. "shr_s": 135,
  117. "shr_u": 136,
  118. "rotl": 137,
  119. "rotr": 138,
  120. "extend_i32_s": 172,
  121. "extend_i32_u": 173,
  122. "trunc_f32_s": 174,
  123. "trunc_f32_u": 175,
  124. "trunc_f64_s": 176,
  125. "trunc_f64_u": 177,
  126. "reinterpret_f64": 189
  127. },
  128. "f32": {
  129. "load": 42,
  130. "store": 56,
  131. "const": 67,
  132. "eq": 91,
  133. "ne": 92,
  134. "lt": 93,
  135. "gt": 95,
  136. "le": 94,
  137. "ge": 96,
  138. "abs": 139,
  139. "neg": 140,
  140. "ceil": 141,
  141. "floor": 142,
  142. "trunc": 143,
  143. "nearest": 144,
  144. "sqrt": 145,
  145. "add": 146,
  146. "sub": 147,
  147. "mul": 148,
  148. "div": 149,
  149. "min": 150,
  150. "max": 151,
  151. "copysign": 152,
  152. "convert_i32_s": 178,
  153. "convert_i32_u": 179,
  154. "convert_i64_s": 180,
  155. "convert_i64_u": 181,
  156. "demote_f64": 182,
  157. "reinterpret_i32": 190
  158. },
  159. "f64": {
  160. "load": 43,
  161. "store": 57,
  162. "const": 68,
  163. "eq": 97,
  164. "ne": 98,
  165. "lt": 99,
  166. "gt": 100,
  167. "le": 101,
  168. "ge": 102,
  169. "abs": 153,
  170. "neg": 154,
  171. "ceil": 155,
  172. "floor": 156,
  173. "trunc": 157,
  174. "nearest": 158,
  175. "sqrt": 159,
  176. "add": 160,
  177. "sub": 161,
  178. "mul": 162,
  179. "div": 163,
  180. "min": 164,
  181. "max": 165,
  182. "copysign": 166,
  183. "convert_i32_s": 183,
  184. "convert_i32_u": 184,
  185. "convert_i64_s": 185,
  186. "convert_i64_u": 186,
  187. "promote_f32": 187,
  188. "reinterpret_i64": 191
  189. },
  190. "memory": {
  191. "size": 63,
  192. "grow": 64
  193. }
  194. };
  195. class WASMSection {
  196. constructor(desc,length) {
  197. this.section = desc;
  198. this.body = new Array(length);
  199. }
  200. }
  201. class WASMParser {
  202. constructor(bin) {
  203. this.lexer = new Reader(new Uint8Array(bin));
  204. this.sections = new Array(13);
  205. this.adjustImports = 0;
  206. this.importFuncCount = 0;
  207. this.parseWASM();
  208. }
  209. read(bin) { this.lexer.packet = new Uint8Array(bin) }
  210. loadFunc(index) {
  211. this.lexer.set(this.sections[10].body[index - this.importFuncCount]);
  212. const localLength = this.lexer.vu();
  213. for (let n = 0; n < localLength; n++) {
  214. this.lexer.vu();
  215. this.lexer.u8();
  216. }
  217. return;
  218. }
  219. set(index, val = this.lexer.packet) {
  220. this.sections[10].body[index - this.importFuncCount] = val;
  221. }
  222. getAdjusted(index) {
  223. if (index < this.importFuncCount) return index;
  224. return index + this.adjustImports;
  225. }
  226. addImportEntry(options) {
  227. const map = ['f64','f32','i64','i32'];
  228. switch(options.kind) {
  229. case 'func':
  230. this.sections[2].body.push({
  231. name: options.name,
  232. type: "func",
  233. index: this.sections[1].body.length,
  234. isNew: true
  235. });
  236. this.sections[1].body.push({
  237. param: options.params,
  238. return: options.returns,
  239. isNew: true
  240. });
  241. this.adjustImports++;
  242. return this.sections[2].body.length - 1;
  243. case 'global':
  244. this.sections[6].body.push({
  245. type: options.type,
  246. mutable: options.mutable,
  247. value: options.mutable,
  248. isNew: true
  249. });
  250. return this.sections[6].body.length - 1;
  251. default:
  252. throw new Error('oops, not supported yet');
  253. }
  254. }
  255. reindex() {
  256. let section = this.sections[10].body;
  257. let length = section.length;
  258. for (let n = 0; n < length; n++) this.sections[10].body[n] = this.parseFunction(section[n]);
  259. section = this.sections[9].body;
  260. length = section.length;
  261. for (let n = 0; n < length; n++) {
  262. const l = section[n].funcs.length;
  263. for (let p = 0; p < l; p++) this.sections[9].body[n].funcs[p] = this.getAdjusted(section[n].funcs[p]);
  264. }
  265. section = this.sections[7].body;
  266. length = section.length;
  267. for (let n = 0; n < length; n++) this.sections[7].body[n].index = this.getAdjusted(section[n].index);
  268. this.adjustImports = 0;
  269. }
  270. compile() {
  271. const bin = [0, 97, 115, 109, 1, 0, 0, 0];
  272. for (let n = 0; n < 12; n++) {
  273. if (!this.sections[n]) continue;
  274. const section = this[`compileSection0x${n.toString(16)}`]();
  275. bin.push(n);
  276. bin.push(...Writer.vu(section.length));
  277. for (const byte of section) bin.push(byte);
  278. }
  279. return new Uint8Array(bin);
  280. }
  281. compileSection0x1() {
  282. const map = ['f64','f32','i64','i32'];
  283. const section = this.sections[1].body;
  284. const length = section.length;
  285. const bin = Writer.vu(length);
  286. for (let n = 0; n < length; n++) {
  287. bin.push(0x60);
  288. bin.push(...Writer.vu(section[n].param.length));
  289. for (const param of section[n].param) bin.push(map.indexOf(param) + 0x7C);
  290. bin.push(...Writer.vu(section[n].return.length));
  291. for (const param of section[n].return) bin.push(map.indexOf(param) + 0x7C);
  292. }
  293. return bin;
  294. }
  295. compileSection0x2() {
  296. const map = ['func','table','mem','global'];
  297. const section = this.sections[2].body;
  298. const length = section.length;
  299. const bin = Writer.vu(length);
  300. for (let n = 0; n < length; n++) {
  301. const nameSplit = section[n].name.split('.');
  302. for (const part of nameSplit) bin.push(...Writer.stringLEN(part));
  303. bin.push(map.indexOf(section[n].type));
  304. bin.push(...Writer.vu(section[n].index));
  305. //console.log(bin);
  306. }
  307. return bin;
  308. }
  309. compileSection0x3() {
  310. const section = this.sections[3].body;
  311. const length = section.length;
  312. const bin = Writer.vu(length);
  313. for (let n = 0; n < length; n++) bin.push(...Writer.vu(section[n]));
  314. return bin;
  315. }
  316. compileSection0x4() {
  317. const section = this.sections[4].body;
  318. const length = section.length;
  319. const bin = Writer.vu(length);
  320. for (let n = 0; n < length; n++) for (let p = 0; p < 4; p++) bin.push(...Writer.vu(section[n][p]));
  321. return bin;
  322. }
  323. compileSection0x5() {
  324. const section = this.sections[5].body;
  325. const length = section.length;
  326. const bin = Writer.vu(length);
  327. for (let n = 0; n < length; n++) {
  328. bin.push(...Writer.vu(section[n].type));
  329. bin.push(...Writer.vu(section[n].limit[0]));
  330. bin.push(...Writer.vu(section[n].limit[1]));
  331. }
  332. return bin;
  333. }
  334. compileSection0x6() {
  335. const map = ['f64','f32','i64','i32'];
  336. const section = this.sections[6].body;
  337. const length = section.length;
  338. const bin = Writer.vu(length);
  339. for (let n = 0; n < length; n++) {
  340. bin.push(map.indexOf(section[n].type) + 0x7C);
  341. bin.push(section[n].mutable);
  342. for (const expr of section[n].expr) bin.push(...Writer.vu(expr));
  343. bin.push(11);
  344. }
  345. return bin;
  346. }
  347. compileSection0x7() {
  348. const map = ['func','table','mem','global'];
  349. const section = this.sections[7].body;
  350. const length = section.length;
  351. const bin = Writer.vu(length);
  352. for (let n = 0; n < length; n++) {
  353. bin.push(...Writer.stringLEN(section[n].name));
  354. bin.push(map.indexOf(section[n].type));
  355. bin.push(...Writer.vu(section[n].index));
  356. }
  357. return bin;
  358. }
  359. compileSection0x8() {
  360. const section = this.sections[8].body;
  361. const length = 1;
  362. const bin = [1];
  363. bin.push(...Writer.vu(section));
  364. return bin;
  365. }
  366. compileSection0x9() {
  367. const section = this.sections[9].body;
  368. const length = section.length;
  369. const bin = Writer.vu(length);
  370. for (let n = 0; n < length; n++) {
  371. bin.push(section[n].type, section[n].expr[0]);
  372. bin.push(...Writer.vi(section[n].expr[1]),11);
  373. bin.push(...Writer.vu(section[n].funcs.length));
  374. for (const funcIdx of section[n].funcs) bin.push(...Writer.vu(funcIdx));
  375. }
  376. return bin;
  377. }
  378. compileSection0xa() {
  379. const section = this.sections[10].body;
  380. const length = section.length;
  381. const bin = Writer.vu(length);
  382. for (let n = 0; n < length; n++) {
  383. //section[n] = this.parseFunction(section[n]);
  384. bin.push(...Writer.vu(section[n].length));
  385. for (const byte of section[n]) bin.push(byte);
  386. }
  387. return bin;
  388. }
  389. compileSection0xb() {
  390. const section = this.sections[11].body;
  391. const length = section.length;
  392. const bin = Writer.vu(length);
  393. for (let n = 0; n < length; n++) {
  394. bin.push(section[n].type,section[n].expr[0]);
  395. bin.push(...Writer.vi(section[n].expr[1]),11);
  396. bin.push(...Writer.vu(section[n].contents.length));
  397. for (const byte of section[n].contents) bin.push(byte);
  398. }
  399. return bin;
  400. }
  401. parseWASM() {
  402. this.lexer.index = 8;
  403. while (this.lexer.has()) {
  404. const id = this.lexer.u8();
  405. if (id > 12) return;
  406. this[`parseSection0x${id.toString(16)}`]();
  407. }
  408. this.importFuncCount = this.sections[2].body.filter(({type}) => type === 'func').length;
  409. }
  410. parseSection0x1() {
  411. const map = ['f64','f32','i64','i32'];
  412. const rawLength = this.lexer.vu();
  413. const section = new WASMSection('functypes', this.lexer.vu());
  414. for (let n = 0; n < section.body.length; n++) {
  415. const type = { param: [], return: [] }
  416. if (this.lexer.u8() !== 0x60) break;
  417. let len = this.lexer.vu();
  418. for (let n = 0; n < len; n++) type.param.push(map[this.lexer.u8()-0x7C]);
  419. len = this.lexer.vu();
  420. for (let n = 0; n < len; n++) type.return.push(map[this.lexer.u8()-0x7C]);
  421. section.body[n] = type;
  422. }
  423. return (this.sections[1] = section);
  424. }
  425. parseSection0x2() {
  426. const map = ['func','table','mem','global'];
  427. this.lexer.vu();
  428. const section = new WASMSection('imports', this.lexer.vu());
  429. 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() };
  430. return (this.sections[2] = section);
  431. }
  432. parseSection0x3() {
  433. this.lexer.vu();
  434. const section = new WASMSection('functions', this.lexer.vu());
  435. for (let n = 0; n < section.body.length; n++) section.body[n] = this.lexer.vu();
  436. return (this.sections[3] = section);
  437. }
  438. parseSection0x4() {
  439. this.lexer.vu();
  440. const section = new WASMSection('tables', this.lexer.vu());
  441. 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
  442. return (this.sections[4] = section);
  443. }
  444. parseSection0x5() {
  445. this.lexer.vu();
  446. const section = new WASMSection('mem', this.lexer.vu());
  447. for (let n = 0; n < section.body.length; n++) section.body[n] = { type: this.lexer.vu(), limit: [this.lexer.vu(), this.lexer.vu()] }
  448. return (this.sections[5] = section);
  449. }
  450. parseSection0x6() {
  451. const map = ['f64','f32','i64','i32'];
  452. this.lexer.vu();
  453. const section = new WASMSection('globals', this.lexer.vu());
  454. for (let n = 0; n < section.body.length; n++) {
  455. section.body[n] = { type: map[this.lexer.u8()-0x7C], mutable: this.lexer.u8(), expr: [] }
  456. section.body[n].expr.push(this.lexer.ru8());
  457. switch(this.lexer.u8()) {
  458. case OP.i32.const:
  459. case OP.i64.const:
  460. section.body[n].expr.push(this.lexer.vu());
  461. break;
  462. case OP.f32.const:
  463. section.body[n].expr.push(this.f32());
  464. break;
  465. case OP.f64.const:
  466. section.body[n].expr.push(this.f64());
  467. break;
  468. }
  469. this.lexer.u8();
  470. }
  471. return (this.sections[6] = section);
  472. }
  473. parseSection0x7() {
  474. const map = ['func','table','mem','global'];
  475. this.lexer.vu();
  476. const section = new WASMSection('exports', this.lexer.vu());
  477. for (let n = 0; n < section.body.length; n++) {
  478. const name = this.lexer.stringLEN();
  479. const type = map[this.lexer.u8()];
  480. const index = this.lexer.vu();
  481. section.body[n] = { name, type, index };
  482. }
  483. return (this.sections[7] = section);
  484. }
  485. parseSection0x8() {
  486. this.lexer.vu();
  487. const section = new WASMSection('start', this.lexer.vu());
  488. section.body = this.vu();
  489. return (this.sections[8] = section);
  490. }
  491. parseSection0x9() {
  492. this.lexer.vu();
  493. const section = new WASMSection('elements', this.lexer.vu());
  494. for (let n = 0; n < section.body.length; n++) {
  495. section.body[n] = { type: this.lexer.u8() }; //NEED TO ACCOUNT FOR DIFFERENT TYPES
  496. section.body[n].expr = [this.lexer.u8(),this.lexer.vu()];
  497. this.lexer.u8();
  498. const repeat = this.lexer.vu();
  499. section.body[n].funcs = [];
  500. for (let p = 0; p < repeat; p++) section.body[n].funcs.push(this.lexer.vu());
  501. }
  502. return (this.sections[9] = section);
  503. }
  504. parseSection0xa() {
  505. this.lexer.vu();
  506. const section = new WASMSection('code', this.lexer.vu());
  507. for (let n = 0; n < section.body.length; n++) {
  508. const len = this.lexer.vu();
  509. section.body[n] = this.lexer.packet.slice(this.lexer.index, this.lexer.index += len);
  510. }
  511. return (this.sections[10] = section);
  512. }
  513. parseSection0xb() {
  514. this.lexer.vu();
  515. const t = this.lexer.index;
  516.  
  517. const section = new WASMSection('data', this.lexer.vu());
  518. for (let n = 0; n < section.body.length; n++) {
  519. section.body[n] = { type: this.lexer.u8(), expr: [this.lexer.u8(),this.lexer.vu()] };
  520. this.lexer.u8();
  521. const len = this.lexer.vu();
  522. section.body[n].contents = this.lexer.packet.slice(this.lexer.index, this.lexer.index += len);
  523. }
  524. return (this.sections[11] = section);
  525. }
  526. parseFunction(func) {
  527. this.lexer.set(func);
  528. const localLength = this.lexer.vu();
  529. for (let n = 0; n < localLength; n++) {
  530. this.lexer.vu();
  531. this.lexer.u8();
  532. }
  533. while(this.lexer.has()) {
  534. const before = this.lexer.index;
  535. const instr = this.parseInstruction();
  536. if (instr.op === OP.call) {
  537. this.lexer.index = before + 1;
  538. this.lexer.replaceVu(this.getAdjusted(instr.immediates[0]));
  539. }
  540. }
  541. return this.lexer.packet;
  542. }
  543. parseInstruction() {
  544. let len;
  545. const op = this.lexer.u8();
  546. const immediates = [];
  547. switch(op) {
  548. case OP.block: case OP.loop: case OP.if:
  549. case OP.memory.size: case OP.memory.grow:
  550. immediates.push(this.lexer.u8());
  551. break;
  552. case OP.br: case OP.br_if:
  553. case OP.local.get: case OP.local.set: case OP.local.tee:
  554. case OP.i32.const: case OP.i64.const:
  555. immediates.push(this.lexer.vu());
  556. break;
  557. case OP.f32.const:
  558. immediates.push(this.lexer.f32());
  559. break;
  560. case OP.f64.const:
  561. immediates.push(this.lexer.f64());
  562. break;
  563. case OP.global.get: case OP.global.set:
  564. immediates.push(this.lexer.vu());
  565. break; //adjust global index later
  566. case OP.i32.load: case OP.i32.load8_s: case OP.i32.load8_u: case OP.i32.load16_s: case OP.i32.load16_u:
  567. 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:
  568. case OP.f32.load:
  569. case OP.f64.load:
  570. case OP.i32.store: case OP.i32.store8: case OP.i32.store16:
  571. case OP.i64.store: case OP.i64.store8: case OP.i64.store16: case OP.i64.store32:
  572. case OP.f32.store:
  573. case OP.f64.store:
  574. immediates.push(this.lexer.vu(),this.lexer.vu());
  575. break;
  576. case OP.call_indirect:
  577. immediates.push(this.lexer.vu(),this.lexer.u8());
  578. break;
  579. case OP.br_table:
  580. len = this.lexer.vu();
  581. immediates.push(len);
  582. for (let n = 0; n < len+1; n++) immediates.push(this.lexer.vu());
  583. break;
  584. case OP.call:
  585. immediates.push(this.lexer.vu());
  586. break;
  587. default:
  588. break;
  589. }
  590. return {op, immediates}
  591. }
  592. regex(func, instrRegex, cb = (sIndex,eIndex,instrs) => {}, all=true) {
  593. this.lexer.set(this.sections[10].body[func - this.importFuncCount]);
  594. const todos = [];
  595. let exprBlob = [];
  596. const localLength = this.lexer.vu();
  597. for (let n = 0; n < localLength; n++) {
  598. this.lexer.vu();
  599. this.lexer.u8();
  600. }
  601. let startIndex = this.lexer.index, regexPos = 0;
  602. while(startIndex < this.lexer.packet.length) {
  603. if (regexPos === 0) {
  604. exprBlob = [];
  605. startIndex = this.lexer.index;
  606. }
  607. const currIndex = this.lexer.index;
  608. const instr = this.parseInstruction();
  609. exprBlob.push(instr);
  610. if (instr.op === instrRegex[regexPos][0]) {
  611. let good = true;
  612. for (let n = 1; n < instrRegex[regexPos].length; n++) if (instrRegex[regexPos][n] !== instr.immediates[n-1] && instrRegex[regexPos][n] !== '*') good = false;
  613. if (good) regexPos++;
  614. else {
  615. regexPos = 0;
  616. this.lexer.index = startIndex;
  617. this.parseInstruction();
  618. continue;
  619. }
  620. }
  621. else {
  622. regexPos = 0;
  623. this.lexer.index = startIndex;
  624. this.parseInstruction();
  625. continue;
  626. }
  627. if (regexPos === instrRegex.length) {
  628. todos.push([startIndex, this.lexer.index, [...exprBlob]]);
  629. if (!all) break;
  630. regexPos = 0;
  631. }
  632. }
  633. for (const [si, ci, eb] of todos) {
  634. cb(si, ci, eb);
  635. }
  636. return this.lexer.packet;
  637. }
  638. inject(code, index = this.lexer.index) {
  639. return this.lexer.inject(code, index);
  640. }
  641. remove(code, index = this.lexer.index) {
  642. return this.lexer.remove(code, index);
  643. }
  644. }
  645. class Writer {
  646. static vu(num) {
  647. const ret = [];
  648. while (num >= 128) {
  649. ret.push((num & 127) | 128);
  650. num >>= 7;
  651. }
  652. ret.push(num);
  653. return ret;
  654. }
  655. static vi(num) {
  656. const ret = [];
  657. while (num >= 128) {
  658. ret.push((num & 127) | 128);
  659. num >>= 7;
  660. }
  661. if (num < 0x40) ret.push(num);
  662. else {
  663. ret.push(num | 0x80);
  664. ret.push(num<0?1:0);
  665. }
  666. return ret;
  667. }
  668. static f32(num) {
  669. return [...new Uint8Array(new Float32Array([num]).buffer)];
  670. }
  671. static stringLEN(str) {
  672. str = new TextEncoder().encode(str);
  673. if (str.length > 127) throw new Error('Unsupported string length: don\'t use a string that long (max 127 byte length)');
  674. return [str.length, ...str];
  675. }
  676. }
  677. class Reader {
  678. constructor(packet) {
  679. this.packet = packet;
  680. this.index = 0;
  681. const buffer = new ArrayBuffer(8);
  682. this._u8 = new Uint8Array(buffer);
  683. this._f32 = new Float32Array(buffer);
  684. this._f64 = new Float64Array(buffer);
  685. }
  686. inject(code, index = this.index) {
  687. this.index = index;
  688. const newBuf = new Uint8Array(code.length + this.packet.length);
  689. newBuf.set(this.packet.slice(0,this.index),0);
  690. newBuf.set(code,this.index);
  691. newBuf.set(this.packet.slice(this.index),(this.index+code.length));
  692. return (this.packet = newBuf);
  693. }
  694. remove(index1, index2 = this.index) {
  695. this.index = index2;
  696. const newBuf = new Uint8Array(index1 - index2 + this.packet.length);
  697. newBuf.set(this.packet.slice(0,index1),0);
  698. newBuf.set(this.packet.slice(index2,this.packet.length),index1);
  699. return (this.packet = newBuf);
  700. }
  701. replaceVu(replace) {
  702. const before = this.index, old = this.vu(), now = this.index;
  703. replace = Writer.vu(replace);
  704. if (replace.length === now - before) this.packet.set(replace, before);
  705. else {
  706. const newBuf = new Uint8Array(this.packet.length-now+before+replace.length);
  707. newBuf.set(this.packet.slice(0,before),0);
  708. newBuf.set(replace,before);
  709. newBuf.set(this.packet.slice(now),(this.index=before+replace.length));
  710. this.packet = newBuf;
  711. }
  712. }
  713. has() { return this.index < this.packet.length }
  714. set(packet) {
  715. this.packet = packet;
  716. this.index = 0;
  717. }
  718. ru8() { return this.packet[this.index] }
  719. u8() { return this.packet[this.index++] }
  720. f32() {
  721. this._u8.set(this.packet.slice(this.index, this.index += 4));
  722. return this._f32[0];
  723. }
  724. f64() {
  725. this._u8.set(this.packet.slice(this.index, this.index += 8));
  726. return this._f64[0];
  727. }
  728. vu() {
  729. let out = 0, at = 0;
  730. while (this.packet[this.index] & 0x80) {
  731. out |= (this.u8() & 0x7f) << at;
  732. at += 7;
  733. }
  734. out |= this.u8() << at;
  735. return out;
  736. }
  737. stringLEN() {
  738. const len = this.u8();
  739. const ret = new TextDecoder().decode(this.packet.slice(this.index, this.index += len));
  740. return ret;
  741. }
  742. }