nits
This commit is contained in:
parent
1b7dde139d
commit
2f3bd1eef9
@ -1,3 +1,4 @@
|
||||
/* eslint-env commonjs */
|
||||
module.exports = {
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
@ -9,6 +10,9 @@ module.exports = {
|
||||
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
||||
plugins: ['react-refresh'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'react-hooks/exhaustive-deps': 'off',
|
||||
'react-refresh/only-export-components': 'warn',
|
||||
'no-regex-spaces': 'off',
|
||||
},
|
||||
}
|
||||
|
@ -151,9 +151,7 @@ error: Uncaught (in promise) "Could not find map!"
|
||||
|
||||
Running the command a second time typically shows a popup:
|
||||
|
||||
"""
|
||||
Developer Tools Access needs to take control of another process for debugging to continue
|
||||
"""
|
||||
> Developer Tools Access needs to take control of another process for debugging to continue
|
||||
|
||||
It will ask for Touch ID or password. After authorization, the build should run.
|
||||
|
||||
|
@ -10,17 +10,16 @@
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview",
|
||||
"postinstall": "patch-package"
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"cfb": "1.2.2",
|
||||
"printj": "1.3.1",
|
||||
"printj": "https://cdn.sheetjs.com/printj-1.3.2/printj-1.3.2.tgz",
|
||||
"react": "18.2.0",
|
||||
"react-contexify": "6.0.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-inspector": "6.0.1",
|
||||
"react-resizable-panels": "0.0.45",
|
||||
"react-resizable-panels": "1.0.1",
|
||||
"react-toastify": "9.1.3",
|
||||
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.0/xlsx-0.20.0.tgz"
|
||||
},
|
||||
@ -33,7 +32,6 @@
|
||||
"eslint": "8.40.0",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"eslint-plugin-react-refresh": "0.3.5",
|
||||
"patch-package": "7.0.0",
|
||||
"typescript": "5.0.4",
|
||||
"vite": "4.4.7",
|
||||
"vite-plugin-pwa": "0.14.7"
|
||||
|
16
src/App.tsx
16
src/App.tsx
@ -56,9 +56,9 @@ const FMT = [...Array.from({length:16}).map((_,i) =>
|
||||
), Y.repeat(8) + "|" + "%c".repeat(16) + "|\n"];
|
||||
|
||||
const xxd = (u8: Uint8Array): string => {
|
||||
let out: string[] = [];
|
||||
const out: string[] = [];
|
||||
for(let i = 0; i < u8.length; i+=16) {
|
||||
let d = [...u8.slice(i, i+16)];
|
||||
const d = [...u8.slice(i, i+16)];
|
||||
out.push(vsprintf(`%04x: ${FMT[d.length]}`, [i, ...d, ...d.map(x => String.fromCharCode(x).replace(/[^\x20-\x7E]/g,"."))]))
|
||||
}
|
||||
return out.join("");
|
||||
@ -163,7 +163,7 @@ const preparse = (id: any, message: string, f: ParsedFile, p: ProtoMap) => {
|
||||
if(!item.parsedmeta) {
|
||||
const m: $_TSP_MessageInfo = item.parsedmeta = process(item.rawmeta, ".TSP.MessageInfo", p);
|
||||
/* .TSP.MessageInfo */
|
||||
if(m.object_references) m.$object_references = m.object_references.map((n: BigInt) => {
|
||||
if(m.object_references) m.$object_references = m.object_references.map((n: bigint) => {
|
||||
/* create a fake reference for the inspector */
|
||||
const o: $_TSP_Reference = ({ identifier: n });
|
||||
Object.defineProperty(o, "PB_TYPE", {value: ".TSP.Reference", enumerable: false});
|
||||
@ -171,7 +171,7 @@ const preparse = (id: any, message: string, f: ParsedFile, p: ProtoMap) => {
|
||||
});
|
||||
if(m.field_infos) m.field_infos.forEach((fi) => {
|
||||
/* .TSP.FieldInfo */
|
||||
if(fi.object_references) fi.$object_references = fi.object_references.map((n: BigInt) => {
|
||||
if(fi.object_references) fi.$object_references = fi.object_references.map((n: bigint) => {
|
||||
/* create a fake reference for the inspector */
|
||||
const o: $_TSP_Reference = ({ identifier: n });
|
||||
Object.defineProperty(o, "PB_TYPE", {value: ".TSP.Reference", enumerable: false});
|
||||
@ -227,7 +227,7 @@ function App() {
|
||||
const rowelt = document.getElementById(`tr-${R}`);
|
||||
const top = rowelt?.offsetTop || 0;
|
||||
if(tblRef.current) {
|
||||
let tbl = tblRef.current;
|
||||
const tbl = tblRef.current;
|
||||
if(top > tbl.scrollTop + tbl.clientHeight - (rowelt?.clientHeight||0) || top < tbl.scrollTop + (rowelt?.clientHeight||0)) tbl.scrollTop = Math.max(0, top - tbl.clientHeight/2 - (rowelt?.clientHeight||0)/2);
|
||||
}
|
||||
};
|
||||
@ -387,13 +387,13 @@ function App() {
|
||||
<b>{data.PB_ENUM && <> = {data.PB_ENUM}</>} [{data.PB_TYPE}]</b>
|
||||
</a> );
|
||||
if(data.PB_TYPE == ".TSP.Reference") {
|
||||
let id = String(data?.identifier);
|
||||
const id = String(data?.identifier);
|
||||
return ( <span onContextMenu={(e) => {displayMenu(e, { type: data.PB_TYPE, id, data, field: data.PB_FIELD })}}>
|
||||
<ObjectName name={name} />: <b>{frag} -> <a onClick={() => {gotoRef(id)}}><b>{id}</b></a></b>
|
||||
</span> );
|
||||
}
|
||||
if(data.PB_TYPE == ".TSP.UUID") {
|
||||
let uuid = uuid2str(data.lower, data.upper);
|
||||
const uuid = uuid2str(data.lower, data.upper);
|
||||
return ( <span onContextMenu={(e) => {displayMenu(e, { type: data.PB_TYPE, id, data, field: data.PB_FIELD })}}>
|
||||
<ObjectName name={name} />: <b>{frag} -> {uuid}</b>
|
||||
</span> );
|
||||
@ -424,7 +424,7 @@ function App() {
|
||||
<b>{data.PB_ENUM && <> = {data.PB_ENUM}</>} [{data.PB_TYPE}]</b>
|
||||
</a> );
|
||||
if(data.PB_TYPE == ".TSP.Reference") {
|
||||
let id = String(data?.identifier);
|
||||
const id = String(data?.identifier);
|
||||
return ( <span onContextMenu={(e) => {displayMenu(e, { type: data.PB_TYPE, id, data, field: data.PB_FIELD })}}>
|
||||
<ObjectName name={name} />: <b>{frag} -> <a onClick={() => {gotoRef(id)}}><b>{id}</b></a></b>
|
||||
</span> );
|
||||
|
158
src/iwa.ts
158
src/iwa.ts
@ -3,8 +3,8 @@ import * as CFB from 'cfb';
|
||||
import Messages, { $_TSP_MessageInfo, MessageTypes } from "./messages/";
|
||||
|
||||
/* see https://bugs.webkit.org/show_bug.cgi?id=243148 -- affects iOS Safari */
|
||||
declare var Buffer: any; // Buffer is typeof-guarded but TS still needs this :(
|
||||
var subarray: "subarray" | "slice" = (() => {
|
||||
declare const Buffer: any; // Buffer is typeof-guarded but TS still needs this :(
|
||||
const subarray: "subarray" | "slice" = (() => {
|
||||
try {
|
||||
if(typeof Uint8Array == "undefined") return "slice";
|
||||
if(typeof Uint8Array.prototype.subarray == "undefined") return "slice";
|
||||
@ -20,13 +20,13 @@ var subarray: "subarray" | "slice" = (() => {
|
||||
|
||||
/** Concatenate Uint8Arrays */
|
||||
function u8concat(u8a: Uint8Array[]): Uint8Array {
|
||||
var len = 0;
|
||||
for(var i = 0; i < u8a.length; ++i) len += u8a[i].length;
|
||||
var out = new Uint8Array(len);
|
||||
var off = 0;
|
||||
for(i = 0; i < u8a.length; ++i) {
|
||||
var u8 = u8a[i], L = u8.length;
|
||||
if(L < 250) { for(var j = 0; j < L; ++j) out[off++] = u8[j]; }
|
||||
let len = 0;
|
||||
for(let i = 0; i < u8a.length; ++i) len += u8a[i].length;
|
||||
const out = new Uint8Array(len);
|
||||
let off = 0;
|
||||
for(let i = 0; i < u8a.length; ++i) {
|
||||
const u8 = u8a[i], L = u8.length;
|
||||
if(L < 250) { for(let j = 0; j < L; ++j) out[off++] = u8[j]; }
|
||||
else { out.set(u8, off); off += L; }
|
||||
}
|
||||
return out;
|
||||
@ -36,8 +36,8 @@ interface Ptr { l: number; }
|
||||
|
||||
/** Parse an integer from the varint that can be exactly stored in a double */
|
||||
function parse_varint49(buf: Uint8Array, ptr: Ptr): number {
|
||||
var l = ptr.l;
|
||||
var usz = buf[l] & 0x7F;
|
||||
let l = ptr.l;
|
||||
let usz = buf[l] & 0x7F;
|
||||
varint: if(buf[l++] >= 0x80) {
|
||||
usz |= (buf[l] & 0x7F) << 7; if(buf[l++] < 0x80) break varint;
|
||||
usz |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) break varint;
|
||||
@ -51,15 +51,15 @@ function parse_varint49(buf: Uint8Array, ptr: Ptr): number {
|
||||
}
|
||||
/** Parse a repeated varint [packed = true] field */
|
||||
function parse_packed_varints(buf: Uint8Array): number[] {
|
||||
var ptr: Ptr = {l: 0};
|
||||
var out: number[] = [];
|
||||
const ptr: Ptr = {l: 0};
|
||||
const out: number[] = [];
|
||||
while(ptr.l < buf.length) out.push(parse_varint49(buf, ptr));
|
||||
return out;
|
||||
}
|
||||
/** Parse a BigInt from the varint */
|
||||
function parse_varint64(buf: Uint8Array, ptr: Ptr): BigInt {
|
||||
var l = ptr.l;
|
||||
var usz = BigInt(buf[l] & 0x7F);
|
||||
function parse_varint64(buf: Uint8Array, ptr: Ptr): bigint {
|
||||
let l = ptr.l;
|
||||
let usz = BigInt(buf[l] & 0x7F);
|
||||
varint: if(buf[l++] >= 0x80) {
|
||||
usz += BigInt(buf[l] & 0x7F) << 7n; if(buf[l++] < 0x80) break varint;
|
||||
usz += BigInt(buf[l] & 0x7F) << 14n; if(buf[l++] < 0x80) break varint;
|
||||
@ -75,15 +75,15 @@ function parse_varint64(buf: Uint8Array, ptr: Ptr): BigInt {
|
||||
return usz;
|
||||
}
|
||||
/** Parse a repeated varint [packed = true] field */
|
||||
function parse_packed_varint64(buf: Uint8Array): BigInt[] {
|
||||
var ptr: Ptr = {l: 0};
|
||||
var out: BigInt[] = [];
|
||||
function parse_packed_varint64(buf: Uint8Array): bigint[] {
|
||||
const ptr: Ptr = {l: 0};
|
||||
const out: bigint[] = [];
|
||||
while(ptr.l < buf.length) out.push(parse_varint64(buf, ptr));
|
||||
return out;
|
||||
}
|
||||
/** Parse a 32-bit signed integer from the raw varint */
|
||||
function varint_to_i32(buf: Uint8Array): number {
|
||||
var l = 0,
|
||||
let l = 0,
|
||||
i32 = (buf[l] & 0x7F) ; if(buf[l++] < 0x80) return i32;
|
||||
i32 |= (buf[l] & 0x7F) << 7; if(buf[l++] < 0x80) return i32;
|
||||
i32 |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) return i32;
|
||||
@ -92,7 +92,7 @@ function varint_to_i32(buf: Uint8Array): number {
|
||||
}
|
||||
/** Parse a 64-bit unsigned integer as a pair */
|
||||
function varint_to_u64(buf: Uint8Array): [number, number] {
|
||||
var l = 0, lo = buf[l] & 0x7F, hi = 0;
|
||||
let l = 0, lo = buf[l] & 0x7F, hi = 0;
|
||||
varint: if(buf[l++] >= 0x80) {
|
||||
lo |= (buf[l] & 0x7F) << 7; if(buf[l++] < 0x80) break varint;
|
||||
lo |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) break varint;
|
||||
@ -130,13 +130,14 @@ interface IWAArchiveInfo {
|
||||
}
|
||||
/** Shallow parse of a Protobuf message */
|
||||
function parse_shallow(buf: Uint8Array): ProtoMessage {
|
||||
var out: ProtoMessage = [], ptr: Ptr = {l: 0};
|
||||
const out: ProtoMessage = [], ptr: Ptr = {l: 0};
|
||||
while(ptr.l < buf.length) {
|
||||
var off = ptr.l;
|
||||
var num = parse_varint49(buf, ptr);
|
||||
var type = num & 0x07; num = (num / 8)|0;
|
||||
var data: Uint8Array;
|
||||
var l = ptr.l;
|
||||
const off = ptr.l;
|
||||
let num = parse_varint49(buf, ptr);
|
||||
const type = num & 0x07;
|
||||
num = (num / 8)|0;
|
||||
let data: Uint8Array;
|
||||
let l = ptr.l;
|
||||
switch(type) {
|
||||
case 0: {
|
||||
while(buf[l++] >= 0x80);
|
||||
@ -145,14 +146,14 @@ function parse_shallow(buf: Uint8Array): ProtoMessage {
|
||||
} break;
|
||||
case 1: { data = buf[subarray](l, l + 8); ptr.l = l + 8; } break;
|
||||
case 2: {
|
||||
var len = parse_varint49(buf, ptr);
|
||||
const len = parse_varint49(buf, ptr);
|
||||
data = buf[subarray](ptr.l, ptr.l + len);
|
||||
ptr.l += len;
|
||||
} break;
|
||||
case 5: { data = buf[subarray](l, l + 4); ptr.l = l + 4; } break;
|
||||
default: throw new Error(`PB Type ${type} for Field ${num} at offset ${off}`);
|
||||
}
|
||||
var v: ProtoItem = { data, type };
|
||||
const v: ProtoItem = { data, type };
|
||||
if(out[num] == null) out[num] = [];
|
||||
out[num].push(v);
|
||||
}
|
||||
@ -161,21 +162,21 @@ function parse_shallow(buf: Uint8Array): ProtoMessage {
|
||||
|
||||
/** Extract all messages from a IWA file */
|
||||
function parse_iwa_file(buf: Uint8Array): IWAArchiveInfo[] {
|
||||
var out: IWAArchiveInfo[] = [], ptr: Ptr = {l: 0};
|
||||
const out: IWAArchiveInfo[] = [], ptr: Ptr = {l: 0};
|
||||
while(ptr.l < buf.length) {
|
||||
/* .TSP.ArchiveInfo */
|
||||
var len = parse_varint49(buf, ptr);
|
||||
var ai = parse_shallow(buf[subarray](ptr.l, ptr.l + len));
|
||||
const len = parse_varint49(buf, ptr);
|
||||
const ai = parse_shallow(buf[subarray](ptr.l, ptr.l + len));
|
||||
ptr.l += len;
|
||||
|
||||
var res: IWAArchiveInfo = {
|
||||
const res: IWAArchiveInfo = {
|
||||
/* TODO: technically ID is optional */
|
||||
id: varint_to_i32(ai[1][0].data),
|
||||
messages: []
|
||||
};
|
||||
ai[2].forEach(b => {
|
||||
var mi = parse_shallow(b.data);
|
||||
var fl = varint_to_i32(mi[3][0].data);
|
||||
const mi = parse_shallow(b.data);
|
||||
const fl = varint_to_i32(mi[3][0].data);
|
||||
res.messages.push({
|
||||
meta: mi,
|
||||
rawmeta: b.data,
|
||||
@ -192,18 +193,18 @@ function parse_iwa_file(buf: Uint8Array): IWAArchiveInfo[] {
|
||||
/** Decompress a snappy chunk */
|
||||
function parse_snappy_chunk(type: number, buf: Uint8Array): Uint8Array[] {
|
||||
if(type != 0) throw new Error(`Unexpected Snappy chunk type ${type}`);
|
||||
var ptr: Ptr = {l: 0};
|
||||
const ptr: Ptr = {l: 0};
|
||||
|
||||
var usz = parse_varint49(buf, ptr);
|
||||
var chunks: Uint8Array[] = [];
|
||||
var l = ptr.l;
|
||||
const usz = parse_varint49(buf, ptr);
|
||||
let chunks: Uint8Array[] = [];
|
||||
let l = ptr.l;
|
||||
while(l < buf.length) {
|
||||
var tag = buf[l] & 0x3;
|
||||
const tag = buf[l] & 0x3;
|
||||
if(tag == 0) {
|
||||
var len = buf[l++] >> 2;
|
||||
let len = buf[l++] >> 2;
|
||||
if(len < 60) ++len;
|
||||
else {
|
||||
var c = len - 59;
|
||||
const c = len - 59;
|
||||
len = buf[l];
|
||||
if(c > 1) len |= (buf[l+1]<<8);
|
||||
if(c > 2) len |= (buf[l+2]<<16);
|
||||
@ -213,7 +214,7 @@ function parse_snappy_chunk(type: number, buf: Uint8Array): Uint8Array[] {
|
||||
}
|
||||
chunks.push(buf[subarray](l, l + len)); l += len; continue;
|
||||
} else {
|
||||
var offset = 0, length = 0;
|
||||
let offset = 0, length = 0;
|
||||
if(tag == 1) {
|
||||
length = ((buf[l] >> 2) & 0x7) + 4;
|
||||
offset = (buf[l++] & 0xE0) << 3;
|
||||
@ -224,7 +225,7 @@ function parse_snappy_chunk(type: number, buf: Uint8Array): Uint8Array[] {
|
||||
else { offset = (buf[l] | (buf[l+1]<<8) | (buf[l+2]<<16) | (buf[l+3]<<24))>>>0; l += 4; }
|
||||
}
|
||||
if(offset == 0) throw new Error("Invalid offset 0");
|
||||
var j = chunks.length - 1, off = offset;
|
||||
let j = chunks.length - 1, off = offset;
|
||||
while(j >=0 && off >= chunks[j].length) { off -= chunks[j].length; --j; }
|
||||
if(j < 0) {
|
||||
if(off == 0) off = chunks[(j = 0)].length;
|
||||
@ -240,7 +241,7 @@ function parse_snappy_chunk(type: number, buf: Uint8Array): Uint8Array[] {
|
||||
if(chunks.length > 25) chunks = [u8concat(chunks)];
|
||||
}
|
||||
}
|
||||
var clen = 0; for(var u8i = 0; u8i < chunks.length; ++u8i) clen += chunks[u8i].length;
|
||||
let clen = 0; for(let u8i = 0; u8i < chunks.length; ++u8i) clen += chunks[u8i].length;
|
||||
if(clen != usz) throw new Error(`Unexpected length: ${clen} != ${usz}`);
|
||||
return chunks;
|
||||
}
|
||||
@ -248,12 +249,12 @@ function parse_snappy_chunk(type: number, buf: Uint8Array): Uint8Array[] {
|
||||
/** Decompress IWA file */
|
||||
function decompress_iwa_file(buf: Uint8Array): Uint8Array {
|
||||
if(Array.isArray(buf)) buf = new Uint8Array(buf);
|
||||
var out: Uint8Array[] = [];
|
||||
var l = 0;
|
||||
const out: Uint8Array[] = [];
|
||||
let l = 0;
|
||||
while(l < buf.length) {
|
||||
var t = buf[l++];
|
||||
var len = buf[l] | (buf[l+1]<<8) | (buf[l+2] << 16); l += 3;
|
||||
out.push.apply(out, parse_snappy_chunk(t, buf[subarray](l, l + len)));
|
||||
const t = buf[l++];
|
||||
const len = buf[l] | (buf[l+1]<<8) | (buf[l+2] << 16); l += 3;
|
||||
out.push(...parse_snappy_chunk(t, buf[subarray](l, l + len)));
|
||||
l += len;
|
||||
}
|
||||
if(l !== buf.length) throw new Error("data is not a valid framed stream!");
|
||||
@ -270,21 +271,21 @@ interface ParsedFile {
|
||||
}
|
||||
|
||||
function parse_iwa(cfb: CFB.CFB$Container): ParsedFile {
|
||||
var M: MessageSpace = {}, indices: number[] = [], tbl: TableItem[] = [];
|
||||
const M: MessageSpace = {}, indices: number[] = [], tbl: TableItem[] = [];
|
||||
cfb.FullPaths.forEach(p => { if(p.match(/\.iwpv2/)) throw new Error(`Unsupported password protection`); });
|
||||
|
||||
var root!: TableItem, rootmsg!: IWAMessage;
|
||||
let root!: TableItem, rootmsg!: IWAMessage;
|
||||
/* collect entire message space */
|
||||
cfb.FileIndex.forEach((s, idx) => {
|
||||
if(!s.name.match(/\.iwa$/)) return;
|
||||
if(s.content[0] != 0) return; // TODO: this should test if the iwa follows the framing format
|
||||
var o: Uint8Array;
|
||||
let o: Uint8Array;
|
||||
try { o = decompress_iwa_file(s.content as Uint8Array); } catch(e: any) { return console.log("?? " + s.content.length + " " + ((e as Error).message || e)); }
|
||||
var packets: IWAArchiveInfo[];
|
||||
let packets: IWAArchiveInfo[];
|
||||
try { packets = parse_iwa_file(o); } catch(e: any) { return console.log("## " + ((e as Error).message || e)); }
|
||||
packets.forEach(packet => { M[packet.id] = packet.messages; indices.push(packet.id);
|
||||
var type = varint_to_i32(packet.messages[0].meta[1][0].data);
|
||||
var item = {
|
||||
const type = varint_to_i32(packet.messages[0].meta[1][0].data);
|
||||
const item = {
|
||||
id: packet.id,
|
||||
type,
|
||||
path:cfb.FullPaths[idx].replace(/Root Entry/, ""),
|
||||
@ -296,7 +297,7 @@ function parse_iwa(cfb: CFB.CFB$Container): ParsedFile {
|
||||
});
|
||||
if(!indices.length) throw new Error("File has no messages");
|
||||
if(!root) throw new Error(`Root element (id 1) missing!`);
|
||||
var type: MessageTypes = "N";
|
||||
let type: MessageTypes = "N";
|
||||
if(root.type == 10000) type = "P";
|
||||
else if(parse_shallow(rootmsg.data)?.[2]?.[0]) type = "K";
|
||||
|
||||
@ -307,17 +308,18 @@ function parse_iwa(cfb: CFB.CFB$Container): ParsedFile {
|
||||
|
||||
function process_item(item: {data: Uint8Array; type: number}, type: string, protos: any) {
|
||||
switch(item.type) {
|
||||
case 0:
|
||||
var varint = parse_varint49(item.data, {l:0});
|
||||
case 0: {
|
||||
const varint = parse_varint49(item.data, {l:0});
|
||||
switch(type) {
|
||||
case "bool": return !!+varint;
|
||||
case "uint32": return varint;
|
||||
case "int32": return varint | 0;
|
||||
case "sint32": return (-(varint&1))^(varint>>1);
|
||||
case "uint64": var u64 = varint_to_u64(item.data); return (BigInt(u64[1])<<32n) + BigInt(u64[0]);
|
||||
case "int64": var u64 = varint_to_u64(item.data); return new BigInt64Array([(BigInt(u64[1])<<32n) + BigInt(u64[0])])[0];
|
||||
case "sint64": var u64 = varint_to_u64(item.data); var bi = (BigInt(u64[1])<<32n) + BigInt(u64[0]); return (-(bi&1n))^(bi>>1n);
|
||||
} break;
|
||||
case "uint64": { const u64 = varint_to_u64(item.data); return (BigInt(u64[1])<<32n) + BigInt(u64[0]); }
|
||||
case "int64": { const u64 = varint_to_u64(item.data); return new BigInt64Array([(BigInt(u64[1])<<32n) + BigInt(u64[0])])[0]; }
|
||||
case "sint64": { const u64 = varint_to_u64(item.data); const bi = (BigInt(u64[1])<<32n) + BigInt(u64[0]); return (-(bi&1n))^(bi>>1n); }
|
||||
}
|
||||
} break;
|
||||
case 1: switch(type) {
|
||||
case "fixed64": return new BigUint64Array(new Uint8Array([...item.data]).buffer)[0];
|
||||
case "sfixed64": return new BigInt64Array(new Uint8Array([...item.data]).buffer)[0];
|
||||
@ -339,15 +341,15 @@ function process_item(item: {data: Uint8Array; type: number}, type: string, prot
|
||||
}
|
||||
|
||||
function process_enum(data: Uint8Array, message: string, protos: any) {
|
||||
var val = parse_varint49(data, {l: 0});
|
||||
let val = parse_varint49(data, {l: 0});
|
||||
if(val >= 4294967296) val |= 0;
|
||||
var msg = protos[message].split("\n");
|
||||
for(let m of msg) {
|
||||
const msg = protos[message].split("\n");
|
||||
for(const m of msg) {
|
||||
if(m.startsWith("enum")) continue;
|
||||
if(m.indexOf("=")> -1) {
|
||||
let [field, , value] = m.trim().split(" ");
|
||||
const [field, , value] = m.trim().split(" ");
|
||||
if(val == parseInt(value, 10)) {
|
||||
var res = {}
|
||||
const res = {}
|
||||
Object.defineProperty(res, "value", { get: () => val});
|
||||
Object.defineProperty(res, "PB_ENUM", { value: field, enumerable: false})
|
||||
return res;
|
||||
@ -359,14 +361,14 @@ function process_enum(data: Uint8Array, message: string, protos: any) {
|
||||
|
||||
function process(data: Uint8Array, message: string, protos: any) {
|
||||
if(!protos[message]) return parse_shallow(data);
|
||||
var shallow = parse_shallow(data);
|
||||
var proto: string[] = protos[message].split("\n");
|
||||
var out: any = {};
|
||||
const shallow = parse_shallow(data);
|
||||
const proto: string[] = protos[message].split("\n");
|
||||
const out: any = {};
|
||||
if(proto[0].startsWith("enum")) return process_enum(data, message, protos);
|
||||
proto.forEach(line => {
|
||||
if(!line.startsWith(" ") || line.indexOf("=") == -1 || line.startsWith(" ")) return;
|
||||
const [freq, type, name, , idx] = line.trim().split(/\s+/);
|
||||
var i = parseInt(idx, 10);
|
||||
const i = parseInt(idx, 10);
|
||||
if(isNaN(i)) return;
|
||||
if(!shallow[i]?.length) return;
|
||||
switch(freq) {
|
||||
@ -387,16 +389,16 @@ function process(data: Uint8Array, message: string, protos: any) {
|
||||
default: throw `unsupported frequency ${freq}`;
|
||||
}
|
||||
if(type.startsWith(".")) {
|
||||
if(freq == "repeated") out[name].forEach((n: any) => {try { Object.defineProperty(n, "PB_TYPE", {value: type, enumerable: false}); } catch(e){}});
|
||||
else try { Object.defineProperty(out[name], "PB_TYPE", {value: type, enumerable: false}); } catch(e) {}
|
||||
if(freq == "repeated") out[name].forEach((n: any) => {try { Object.defineProperty(n, "PB_TYPE", {value: type, enumerable: false}); } catch(e){/*empty*/}});
|
||||
else try { Object.defineProperty(out[name], "PB_TYPE", {value: type, enumerable: false}); } catch(e) {/*empty*/}
|
||||
}
|
||||
try {
|
||||
if(freq == "repeated") out[name].forEach((n: any, idx:number) => {try { Object.defineProperty(n, "PB_RAW", {value: shallow[i][idx], enumerable: false}); } catch(e){}});
|
||||
else try { Object.defineProperty(out[name], "PB_RAW", {value: shallow[i][0], enumerable: false}); } catch(e) {}
|
||||
if(freq == "repeated") out[name].forEach((n: any, idx:number) => {try { Object.defineProperty(n, "PB_RAW", {value: shallow[i][idx], enumerable: false}); } catch(e){/*empty*/}});
|
||||
else try { Object.defineProperty(out[name], "PB_RAW", {value: shallow[i][0], enumerable: false}); } catch(e) {/*empty*/}
|
||||
} catch(e){console.log(e);}
|
||||
try {
|
||||
if(freq == "repeated") out[name].forEach((n: any, idx:number) => {try { Object.defineProperty(n, "PB_FIELD", {value: `${name}[${idx}]` , enumerable: false}); } catch(e){}});
|
||||
else try { Object.defineProperty(out[name], "PB_FIELD", {value: name, enumerable: false}); } catch(e) {}
|
||||
if(freq == "repeated") out[name].forEach((n: any, idx:number) => {try { Object.defineProperty(n, "PB_FIELD", {value: `${name}[${idx}]` , enumerable: false}); } catch(e){/*empty*/}});
|
||||
else try { Object.defineProperty(out[name], "PB_FIELD", {value: name, enumerable: false}); } catch(e) {/*empty*/}
|
||||
} catch(e){console.log(e);}
|
||||
})
|
||||
return out;
|
||||
|
@ -14,7 +14,7 @@ export default Messages;
|
||||
type ProtoMap = {[key: string]: string};
|
||||
|
||||
const post_process = (buf: string, key: string, out: ProtoMap) => {
|
||||
var payload = "", nested = false;
|
||||
let payload = "", nested = false;
|
||||
buf.split("\n").forEach(row => {
|
||||
if(row.startsWith(" message") || row.startsWith(" enum")) {
|
||||
nested = true
|
||||
@ -23,7 +23,7 @@ const post_process = (buf: string, key: string, out: ProtoMap) => {
|
||||
payload += row + "\n";
|
||||
nested = false;
|
||||
payload = payload.replace(/^ /mg, "");
|
||||
var new_key = "";
|
||||
let new_key = "";
|
||||
payload = payload.replace(/^(message|enum) ([\S]*)/, (_, $1, $2) => {
|
||||
new_key = key + "." + $2;
|
||||
return $1 + " " + key + "." + $2
|
||||
@ -49,7 +49,7 @@ const parse_protos = (text: string): ProtoMap => {
|
||||
out[key] = buf;
|
||||
post_process(buf, key, out);
|
||||
}
|
||||
else if(!line){}
|
||||
else if(!line){/*empty*/}
|
||||
else if(line.startsWith("extend")) {
|
||||
key = line.split(" ")[1];
|
||||
buf = out[key] + "\n" + line + "\n";
|
||||
@ -63,7 +63,7 @@ export { parse_protos };
|
||||
export type { ProtoMap };
|
||||
|
||||
interface $_TSP_Reference {
|
||||
identifier: BigInt;
|
||||
identifier: bigint;
|
||||
}
|
||||
interface $_TSP_FieldPath {
|
||||
path?: number[];
|
||||
@ -72,8 +72,8 @@ interface $_TSP_FieldInfo {
|
||||
path: $_TSP_FieldPath;
|
||||
type?: number;
|
||||
unknown_field_rule?: number;
|
||||
object_references?: BigInt[];
|
||||
data_references?: BigInt[];
|
||||
object_references?: bigint[];
|
||||
data_references?: bigint[];
|
||||
known_field_rule?: number;
|
||||
known_field_version?: number[];
|
||||
known_field_feature_identifier?: string;
|
||||
@ -84,8 +84,8 @@ interface $_TSP_MessageInfo {
|
||||
version: number[];
|
||||
length: number;
|
||||
field_infos?: $_TSP_FieldInfo[];
|
||||
object_references?: BigInt[];
|
||||
data_references?: BigInt[];
|
||||
object_references?: bigint[];
|
||||
data_references?: bigint[];
|
||||
base_message_index?: number;
|
||||
diff_merge_version?: number[];
|
||||
diff_field_path?: $_TSP_FieldPath;
|
||||
|
65
types.ts
65
types.ts
@ -1,65 +0,0 @@
|
||||
/// <reference path="../../types/index.d.ts"/>
|
||||
|
||||
declare type RawData = Uint8Array | number[];
|
||||
interface BinaryRecord {
|
||||
n?: string;
|
||||
f: any;
|
||||
T?: -1 | 1;
|
||||
p?: number;
|
||||
r?: number;
|
||||
}
|
||||
declare function recordhopper(data: RawData, cb:(val: any, R: BinaryRecord, RT: number)=>void): void;
|
||||
declare interface ReadableData {
|
||||
l: number;
|
||||
read_shift(t: 4): number;
|
||||
read_shift(t: any): any;
|
||||
}
|
||||
declare type ParseFunc<T> = (data: ReadableData, length: number) => T;
|
||||
declare var parse_XLWideString: ParseFunc<string>;
|
||||
|
||||
declare interface WritableData {
|
||||
l: number;
|
||||
write_shift(t: 4, val: number): void;
|
||||
write_shift(t: number, val: string|number, f?: string): any;
|
||||
}
|
||||
declare type WritableRawData = WritableData & RawData;
|
||||
interface BufArray {
|
||||
end(): RawData;
|
||||
next(sz: number): WritableData;
|
||||
push(buf: RawData): void;
|
||||
}
|
||||
declare function buf_array(): BufArray;
|
||||
declare function write_record(ba: BufArray, type: number, payload?: RawData, length?: number): void;
|
||||
declare function new_buf(sz: number): RawData & WritableData & ReadableData;
|
||||
|
||||
declare var tagregex: RegExp;
|
||||
declare var XML_HEADER: string;
|
||||
declare var RELS: any;
|
||||
declare function parsexmltag(tag: string, skip_root?: boolean, skip_LC?: boolean): object;
|
||||
declare function strip_ns(x: string): string;
|
||||
declare function write_UInt32LE(x: number, o?: WritableData): RawData;
|
||||
declare function write_XLWideString(data: string, o?: WritableData): RawData;
|
||||
declare function writeuint16(x: number): RawData;
|
||||
|
||||
declare function utf8read(x: string): string;
|
||||
declare function utf8write(x: string): string;
|
||||
|
||||
declare function a2s(a: RawData): string;
|
||||
declare function s2a(s: string): RawData;
|
||||
|
||||
interface ParseXLMetaOptions {
|
||||
WTF?: number|boolean;
|
||||
}
|
||||
interface XLMDT {
|
||||
name: string;
|
||||
offsets?: number[];
|
||||
}
|
||||
interface XLMetaRef {
|
||||
type: string;
|
||||
index: number;
|
||||
}
|
||||
interface XLMeta {
|
||||
Types: XLMDT[];
|
||||
Cell: XLMetaRef[];
|
||||
Value: XLMetaRef[];
|
||||
}
|
Loading…
Reference in New Issue
Block a user