Ctrl K
ComunidadGuías…

chatd/src/personal/ranged-read.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
export const rangeBytes = 6 * 1024 * 1024;

const contentRangePattern = /^bytes (?:(\d+)-(\d+)|\*)\/(\d+)$/;

export type FetchRange = (rangeHeader: string) => Promise<Response>;

export class RangeRefused extends Error {
	constructor(readonly status: number, detail: string) {
		super(detail);
		this.name = "RangeRefused";
	}
}

export async function* rangesOf(fetchRange: FetchRange): AsyncGenerator<Uint8Array> {
	let start = 0;
	for (;;) {
		const response = await fetchRange(`bytes=${start}-${start + rangeBytes - 1}`);
		if (response.status === 416) return;
		if (response.status === 200) {
			yield await wholeBodyWithinOneRange(response);
			return;
		}
		if (response.status !== 206) throw new RangeRefused(response.status, `the source answered ${response.status} for bytes from ${start}`);
		const totalBytes = totalBytesOf(response);
		const bytes = new Uint8Array(await response.arrayBuffer());
		yield bytes;
		start += bytes.byteLength;
		if (bytes.byteLength === 0 || start >= totalBytes) return;
	}
}

async function wholeBodyWithinOneRange(response: Response): Promise<Uint8Array> {
	const declared = Number(response.headers.get("content-length") ?? "0");
	if (declared > rangeBytes) {
		throw new RangeRefused(response.status, `the source ignored the range and offered ${declared} bytes at once`);
	}
	return new Uint8Array(await response.arrayBuffer());
}

function totalBytesOf(response: Response): number {
	const matched = contentRangePattern.exec(response.headers.get("content-range") ?? "");
	if (!matched) throw new RangeRefused(response.status, "the source answered a range without saying the whole size");
	return Number(matched[3]);
}