Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

55 lines · 2.0 KBRaw History
1import { ByteWriter, concat, fromUtf8, utf8 } from "./bytes.js";
2
3export const FLUSH = utf8("0000");
4export const DELIM = utf8("0001");
5export const RESPONSE_END = utf8("0002");
6
7export function pkt(data: string | Uint8Array): Uint8Array {
8 const body = typeof data === "string" ? utf8(data) : data;
9 if (body.length > 65516) throw new Error("pkt-line too long");
10 return concat([utf8((body.length + 4).toString(16).padStart(4, "0")), body]);
11}
12
13export type Pkt = { type: "data"; data: Uint8Array } | { type: "flush" } | { type: "delim" } | { type: "end" };
14
15/** Decode a buffer of pkt-lines. Returns the packets and the offset where parsing stopped. */
16export function readPkts(buf: Uint8Array, start = 0, stopAtFlush = false): { pkts: Pkt[]; offset: number } {
17 const pkts: Pkt[] = [];
18 let i = start;
19 while (i + 4 <= buf.length) {
20 const len = parseInt(fromUtf8(buf.subarray(i, i + 4)), 16);
21 if (Number.isNaN(len)) throw new Error(`bad pkt-line length at ${i}`);
22 if (len === 0) {
23 pkts.push({ type: "flush" });
24 i += 4;
25 if (stopAtFlush) break;
26 continue;
27 }
28 if (len === 1) {
29 pkts.push({ type: "delim" });
30 i += 4;
31 continue;
32 }
33 if (len === 2) {
34 pkts.push({ type: "end" });
35 i += 4;
36 continue;
37 }
38 if (len < 4 || i + len > buf.length) throw new Error(`truncated pkt-line at ${i}`);
39 pkts.push({ type: "data", data: buf.subarray(i + 4, i + len) });
40 i += len;
41 }
42 return { pkts, offset: i };
43}
44
45/** Text of a data pkt without its trailing newline. */
46export const pktText = (p: Pkt): string => (p.type === "data" ? fromUtf8(p.data).replace(/\n$/, "") : "");
47
48/** Wrap pack bytes in side-band-64k packets on the given band. */
49export function sideband(band: 1 | 2 | 3, data: Uint8Array, w: ByteWriter): void {
50 const max = 65515;
51 for (let i = 0; i < data.length; i += max) {
52 const chunk = data.subarray(i, Math.min(data.length, i + max));
53 w.write(pkt(concat([new Uint8Array([band]), chunk])));
54 }
55}