/* ---------- PHP serialize 反序列化(字节精确,覆盖 s/i/d/b/a/N) ---------- */ export function phpUnserialize(input: string): unknown { const buf = Buffer.from(input, "utf8"); let i = 0; function parse(): unknown { const type = String.fromCharCode(buf[i]); const colon = buf.indexOf(0x3a, i + 2); // 跳过 "类型:" 后定位计数值结束的冒号 if (type === "N") { i += 2; return null; } // N; if (type === "b") { const v = buf[i + 2] === 0x31; i += 4; return v; } // b:0; / b:1; if (type === "i") { const j = buf.indexOf(0x3b, i); const v = parseInt(buf.toString("utf8", i + 2, j)); i = j + 1; return v; } // i:123; if (type === "d") { const j = buf.indexOf(0x3b, i); const v = parseFloat(buf.toString("utf8", i + 2, j)); i = j + 1; return v; } // d:1.5; if (type === "s") { // s:LEN:"...";(LEN 为 UTF-8 字节数) const len = parseInt(buf.toString("utf8", i + 2, colon)); const start = colon + 2; const v = buf.toString("utf8", start, start + len); i = start + len + 2; return v; } if (type === "a") { // a:COUNT:{ key;value; ... } const n = parseInt(buf.toString("utf8", i + 2, colon)); i = colon + 2; // 跳过 '{' const arr: unknown[] = []; const obj: Record = {}; let isArr = true; for (let k = 0; k < n; k++) { const key = parse(); const val = parse(); if (typeof key === "number") { isArr = isArr && true; arr[key] = val; } else { isArr = false; obj[String(key)] = val; } } i += 1; // 消费 '}' return isArr ? arr : obj; } throw new Error(`phpUnserialize: unknown type '${type}' at byte ${i}`); } return parse(); }