mirror of
https://github.com/xCyanGrizzly/DragonsStash.git
synced 2026-09-21 13:31:42 +00:00
feat(worker): ranged 7z listing orchestrator + RangeReader
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
import type { Client } from "tdl";
|
||||||
|
import { downloadFileRange } from "../../tdlib/range-download.js";
|
||||||
|
|
||||||
|
export type RangeReader = (
|
||||||
|
fileId: string,
|
||||||
|
offset: number,
|
||||||
|
length: number,
|
||||||
|
partSize: bigint,
|
||||||
|
) => Promise<Buffer>;
|
||||||
|
|
||||||
|
export function tdlibRangeReader(client: Client): RangeReader {
|
||||||
|
return (fileId, offset, length, partSize) =>
|
||||||
|
downloadFileRange(client, fileId, offset, length, partSize);
|
||||||
|
}
|
||||||
@@ -28,3 +28,38 @@ describe("parseSevenZSignatureHeader", () => {
|
|||||||
expect(parseSevenZSignatureHeader(MAGIC)).toBeNull();
|
expect(parseSevenZSignatureHeader(MAGIC)).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
import { readSevenZListingRanged } from "./sevenz-ranged.js";
|
||||||
|
import type { RangeReader } from "./range-reader.js";
|
||||||
|
|
||||||
|
describe("readSevenZListingRanged", () => {
|
||||||
|
it("reads the signature + end-header regions and reconstructs for 7z l", async () => {
|
||||||
|
const size = 5_000_000;
|
||||||
|
const endHeaderOffset = 4_900_000; // absolute
|
||||||
|
const nextHeaderOffset = endHeaderOffset - 32;
|
||||||
|
const sig = Buffer.alloc(32);
|
||||||
|
Buffer.from([0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c]).copy(sig, 0);
|
||||||
|
sig.writeBigUInt64LE(BigInt(nextHeaderOffset), 12);
|
||||||
|
sig.writeBigUInt64LE(100n, 20);
|
||||||
|
|
||||||
|
const reads: { offset: number; length: number }[] = [];
|
||||||
|
const read: RangeReader = async (_id, offset, length) => {
|
||||||
|
reads.push({ offset, length });
|
||||||
|
if (offset === 0) return sig.subarray(0, length);
|
||||||
|
return Buffer.alloc(length, 0xAB); // stand-in end-header bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inject a fake lister via the module boundary: readSevenZListingRanged
|
||||||
|
// calls listFromSparse(parts, read7zContents). We assert the ranged reads
|
||||||
|
// it issued; the sparse file + real 7z is covered by live verification.
|
||||||
|
const entries = await readSevenZListingRanged(
|
||||||
|
[{ fileId: "1", fileSize: BigInt(size), fileName: "a.7z" }],
|
||||||
|
read,
|
||||||
|
);
|
||||||
|
// entries may be null here because the stand-in bytes aren't a real 7z;
|
||||||
|
// the contract under test is the ranged-read offsets:
|
||||||
|
expect(reads[0]).toEqual({ offset: 0, length: 32 });
|
||||||
|
expect(reads[1]).toEqual({ offset: endHeaderOffset, length: 100 });
|
||||||
|
expect(entries === null || Array.isArray(entries)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
import type { FileEntry } from "../zip-reader.js";
|
||||||
|
import { read7zContents } from "../sevenz-reader.js";
|
||||||
|
import { listFromSparse } from "./sparse-list.js";
|
||||||
|
import type { RangeReader } from "./range-reader.js";
|
||||||
|
import { childLogger } from "../../util/logger.js";
|
||||||
|
|
||||||
|
const log = childLogger("sevenz-ranged");
|
||||||
|
|
||||||
const SEVENZ_MAGIC = Buffer.from([0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c]);
|
const SEVENZ_MAGIC = Buffer.from([0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c]);
|
||||||
|
|
||||||
export function parseSevenZSignatureHeader(
|
export function parseSevenZSignatureHeader(
|
||||||
@@ -10,3 +18,36 @@ export function parseSevenZSignatureHeader(
|
|||||||
nextHeaderSize: Number(buf.readBigUInt64LE(20)),
|
nextHeaderSize: Number(buf.readBigUInt64LE(20)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RangedPart { fileId: string; fileSize: bigint; fileName: string }
|
||||||
|
|
||||||
|
export async function readSevenZListingRanged(
|
||||||
|
parts: RangedPart[],
|
||||||
|
read: RangeReader,
|
||||||
|
): Promise<FileEntry[] | null> {
|
||||||
|
const part = parts[0];
|
||||||
|
if (!part) return null;
|
||||||
|
const size = Number(part.fileSize);
|
||||||
|
try {
|
||||||
|
const sig = await read(part.fileId, 0, 32, part.fileSize);
|
||||||
|
const parsed = parseSevenZSignatureHeader(sig);
|
||||||
|
if (!parsed) return null;
|
||||||
|
const endStart = 32 + parsed.nextHeaderOffset;
|
||||||
|
if (endStart < 0 || endStart + parsed.nextHeaderSize > size) return null;
|
||||||
|
const endHeader = await read(part.fileId, endStart, parsed.nextHeaderSize, part.fileSize);
|
||||||
|
return listFromSparse(
|
||||||
|
[{
|
||||||
|
fileName: part.fileName,
|
||||||
|
size,
|
||||||
|
regions: [
|
||||||
|
{ offset: 0, bytes: sig },
|
||||||
|
{ offset: endStart, bytes: endHeader },
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
read7zContents,
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
log.warn({ err, fileId: part.fileId }, "ranged 7z listing failed");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user