Skip to content
File

Blob: test/util/fetch-protocol.ts

typescript59 lines
1import type { PktItem } from "@/worker/git/core";
2 
3import { delimPkt, flushPkt, pktLine } from "@/worker/git";
4import { decodePktLines } from "@/worker/git/core";
5 
6export function buildFetchBody(args: {
7 wants: string[];
8 haves?: string[];
9 done?: boolean;
10 agent?: string | false;
11}): Uint8Array {
12 const chunks: Uint8Array[] = [];
13 chunks.push(pktLine("command=fetch\n"));
14 if (args.agent !== false) {
15 chunks.push(pktLine(`agent=${args.agent || "test"}\n`));
16 }
17 chunks.push(delimPkt());
18 for (const want of args.wants) chunks.push(pktLine(`want ${want}\n`));
19 for (const have of args.haves || []) chunks.push(pktLine(`have ${have}\n`));
20 if (args.done) chunks.push(pktLine("done\n"));
21 chunks.push(flushPkt());
22 const total = chunks.reduce((size, chunk) => size + chunk.byteLength, 0);
23 const out = new Uint8Array(total);
24 let offset = 0;
25 for (const chunk of chunks) {
26 out.set(chunk, offset);
27 offset += chunk.byteLength;
28 }
29 return out;
30}
31 
32function isPktLine(item: PktItem): item is Extract<PktItem, { type: "line" }> {
33 return item.type === "line";
34}
35 
36export function decodePktTextLines(bytes: Uint8Array): string[] {
37 return decodePktLines(bytes)
38 .filter(isPktLine)
39 .map((item) => item.text.trim());
40}
41 
42// Exact pkt-line payloads, including trailing LF. Use `decodePktTextLines`
43// when a test wants trimmed human-readable lines instead.
44export function decodePktLinePayloads(bytes: Uint8Array): string[] {
45 return decodePktLines(bytes)
46 .filter(isPktLine)
47 .map((item) => item.text);
48}
49 
50export function findBytes(haystack: Uint8Array, needle: Uint8Array): number {
51 outer: for (let i = 0; i <= haystack.length - needle.length; i++) {
52 for (let j = 0; j < needle.length; j++) {
53 if (haystack[i + j] !== needle[j]) continue outer;
54 }
55 return i;
56 }
57 return -1;
58}